Skip to content

Commit

Permalink
[efi] Inhibit our driver Start() method during disconnection attempts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Sep 22, 2017
1 parent 7428ab7 commit 74d90b3
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/interface/efi/efi_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 );
Expand All @@ -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 );
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 74d90b3

Please sign in to comment.