summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_driver.c
diff options
context:
space:
mode:
authorMichael Brown2017-09-22 15:02:40 +0200
committerMichael Brown2017-09-22 19:39:04 +0200
commit74d90b33f8490adcee2026ece18d8411d93b6a39 (patch)
tree8a2fb502c0e1f24328304a7ebe305b98132de147 /src/interface/efi/efi_driver.c
parent[build] Exclude selected directories from Secure Boot builds (diff)
downloadipxe-74d90b33f8490adcee2026ece18d8411d93b6a39.tar.gz
ipxe-74d90b33f8490adcee2026ece18d8411d93b6a39.tar.xz
ipxe-74d90b33f8490adcee2026ece18d8411d93b6a39.zip
[efi] Inhibit our driver Start() method during disconnection attempts
Some HP BIOSes (observed with a Z840) seem to attempt to connect our drivers in the middle of our call to DisconnectController(). The precise chain of events is unclear, but the symptom is that we see several calls to our Supported() and Start() methods, followed by a system lock-up. Work around this dubious BIOS behaviour by explicitly failing calls to our Start() method while we are in the middle of attempting to disconnect drivers. Reported-by: Jordan Wright <jordan.m.wright@disney.com> Debugged-by: Adrian Lucrèce Céleste <adrianlucrececeleste@airmail.cc> Debugged-by: Christian Nilsson <nikize@gmail.com> Tested-by: Jordan Wright <jordan.m.wright@disney.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi/efi_driver.c')
-rw-r--r--src/interface/efi/efi_driver.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c
index 2cefed2f..de0f61f9 100644
--- a/src/interface/efi/efi_driver.c
+++ b/src/interface/efi/efi_driver.c
@@ -44,6 +44,9 @@ static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding;
/** List of controlled EFI devices */
static LIST_HEAD ( efi_devices );
+/** We are currently disconnecting drivers */
+static int efi_driver_disconnecting;
+
/**
* Find EFI device
*
@@ -159,6 +162,14 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
goto err_already_started;
}
+ /* Do nothing if we are currently disconnecting drivers */
+ if ( efi_driver_disconnecting ) {
+ DBGC ( device, "EFIDRV %s refusing to start during "
+ "disconnection\n", efi_handle_name ( device ) );
+ efirc = EFI_NOT_READY;
+ goto err_disconnecting;
+ }
+
/* Open device path */
if ( ( efirc = bs->OpenProtocol ( device,
&efi_device_path_protocol_guid,
@@ -220,6 +231,7 @@ efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
efi_image_handle, device );
}
err_open_path:
+ err_disconnecting:
err_already_started:
return efirc;
}
@@ -411,6 +423,7 @@ static int efi_driver_connect ( EFI_HANDLE device ) {
DBGC2_EFI_PROTOCOLS ( device, device );
DBGC ( device, "EFIDRV %s disconnecting existing drivers\n",
efi_handle_name ( device ) );
+ efi_driver_disconnecting = 1;
if ( ( efirc = bs->DisconnectController ( device, NULL,
NULL ) ) != 0 ) {
rc = -EEFI ( efirc );
@@ -419,6 +432,7 @@ static int efi_driver_connect ( EFI_HANDLE device ) {
strerror ( rc ) );
/* Ignore the error and attempt to connect our drivers */
}
+ efi_driver_disconnecting = 0;
DBGC2 ( device, "EFIDRV %s after disconnecting:\n",
efi_handle_name ( device ) );
DBGC2_EFI_PROTOCOLS ( device, device );
@@ -450,9 +464,11 @@ static int efi_driver_disconnect ( EFI_HANDLE device ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
/* Disconnect our driver */
+ efi_driver_disconnecting = 1;
bs->DisconnectController ( device,
efi_driver_binding.DriverBindingHandle,
NULL );
+ efi_driver_disconnecting = 0;
return 0;
}