aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@gmail.com>2010-02-12 18:06:34 +0000
committerMarty Connor <mdc@etherboot.org>2010-02-24 12:58:29 -0500
commitb7af0aa34ee3e35ba4f94f4104c29b299bc0ed0d (patch)
treea5f4c783c2d3ebbba867c4f3c2505fd40992db86 /src
parentcd9c94851bd62bad6bbcb64dd47a8d86bb428b64 (diff)
downloadipxe-b7af0aa34ee3e35ba4f94f4104c29b299bc0ed0d.zip
ipxe-b7af0aa34ee3e35ba4f94f4104c29b299bc0ed0d.tar.gz
ipxe-b7af0aa34ee3e35ba4f94f4104c29b299bc0ed0d.tar.bz2
[undi] Ensure only one UNDI instance is loaded
Loading multiple UNDI instances would be useful in systems that have several network cards with vendor PXE ROMs. However, we cannot rely on UNDI ROMs working correctly with multiple instances loaded simultaneously. The gPXE UNDI driver supports the following multi-NIC configurations: 1. Chainloading undionly.kpxe on a specific NIC. 2. Loading the UNDI driver for the first probed device and ignoring all other UNDI devices in the system. This patch refuses to probe additional UNDI devices so there can never be multiple instances of UNDI loaded. Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com> Signed-off-by: Marty Connor <mdc@etherboot.org>
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/drivers/net/undiload.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/arch/i386/drivers/net/undiload.c b/src/arch/i386/drivers/net/undiload.c
index 1d4e88d..47a2bae 100644
--- a/src/arch/i386/drivers/net/undiload.c
+++ b/src/arch/i386/drivers/net/undiload.c
@@ -58,6 +58,12 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
uint16_t exit;
int rc;
+ /* Only one UNDI instance may be loaded at any given time */
+ if ( undi_loader_entry.segment ) {
+ DBG ( "UNDI %p cannot load multiple instances\n", undi );
+ return -EBUSY;
+ }
+
/* Set up START_UNDI parameters */
memset ( &undi_loader, 0, sizeof ( undi_loader ) );
undi_loader.AX = undi->pci_busdevfn;
@@ -109,6 +115,9 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
gateA20_set();
if ( exit != PXENV_EXIT_SUCCESS ) {
+ /* Clear entry point */
+ memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) );
+
rc = -undi_loader.Status;
if ( rc == 0 ) /* Paranoia */
rc = -EIO;
@@ -151,6 +160,9 @@ int undi_unload ( struct undi_device *undi ) {
DBGC ( undi, "UNDI %p unloading\n", undi );
+ /* Clear entry point */
+ memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) );
+
/* Erase signatures */
if ( undi->pxenv.segment )
put_real ( dead, undi->pxenv.segment, undi->pxenv.offset );