david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[efi] Ensure that all drivers are shut down before the OS boots

Reported-by: Itay Gazit <itayg@mellanox.co.il>
Suggested-by: Michael R Turner <mikeyt@us.ibm.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2011-03-29 21:35:06 +01:00
parent 797c29adda
commit fc7239bdc8
3 changed files with 51 additions and 32 deletions

View File

@ -26,20 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
/** Event used to signal shutdown */
static EFI_EVENT efi_shutdown_event;
/**
* Shut down in preparation for booting an OS.
*
* This hook gets called at ExitBootServices time in order to make sure that
* the network cards are properly shut down before the OS takes over.
*/
static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
void *context __unused ) {
shutdown_boot();
}
/**
* Execute EFI image
*
@ -64,30 +50,14 @@ static int efi_image_exec ( struct image *image ) {
return -ENOEXEC;
}
/* Be sure to shut down the NIC at ExitBootServices time, or else
* DMA from the card can corrupt the OS.
*/
efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_CALLBACK, efi_shutdown_hook,
NULL, &efi_shutdown_event );
if ( efirc ) {
rc = EFIRC_TO_RC ( efirc );
goto done;
}
/* Start the image */
if ( ( efirc = bs->StartImage ( handle, &exit_data_size,
&exit_data ) ) != 0 ) {
DBGC ( image, "EFIIMAGE %p returned with status %s\n",
image, efi_strerror ( efirc ) );
}
rc = EFIRC_TO_RC ( efirc );
/* Remove the shutdown hook */
bs->CloseEvent ( efi_shutdown_event );
done:
/* Unload the image. We can't leave it loaded, because we
* have no "unload" operation.
*/

View File

@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/LoadedImage.h>
#include <ipxe/uuid.h>
#include <ipxe/init.h>
/** Image handle passed to entry point */
EFI_HANDLE efi_image_handle;
@ -36,6 +37,21 @@ EFI_SYSTEM_TABLE *efi_systab;
static EFI_GUID efi_loaded_image_protocol_guid
= EFI_LOADED_IMAGE_PROTOCOL_GUID;
/** Event used to signal shutdown */
static EFI_EVENT efi_shutdown_event;
/**
* Shut down in preparation for booting an OS.
*
* This hook gets called at ExitBootServices time in order to make
* sure that everything is properly shut down before the OS takes
* over.
*/
static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
void *context __unused ) {
shutdown_boot();
}
/**
* Look up EFI configuration table
*
@ -129,5 +145,18 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
}
}
/* EFI is perfectly capable of gracefully shutting down any
* loaded devices if it decides to fall back to a legacy boot.
* For no particularly comprehensible reason, it doesn't
* bother doing so when ExitBootServices() is called.
*/
if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_CALLBACK, efi_shutdown_hook,
NULL, &efi_shutdown_event ) ) != 0 ) {
DBGC ( systab, "EFI could not create ExitBootServices event: "
"%s\n", efi_strerror ( efirc ) );
return efirc;
}
return 0;
}

View File

@ -489,7 +489,7 @@ static struct efi_driver efipci_driver =
* Install EFI PCI driver
*
*/
static void efipci_driver_init ( void ) {
static void efipci_driver_startup ( void ) {
struct efi_driver *efidrv = &efipci_driver;
EFI_STATUS efirc;
@ -503,7 +503,27 @@ static void efipci_driver_init ( void ) {
DBGC ( efidrv, "EFIPCI driver installed\n" );
}
/**
* Shut down EFI PCI driver
*
* @v booting System is shutting down for OS boot
*/
static void efipci_driver_shutdown ( int booting __unused ) {
struct efi_driver *efidrv = &efipci_driver;
struct efi_pci_device *efipci;
struct efi_pci_device *tmp;
/* Shut down any remaining devices */
list_for_each_entry_safe ( efipci, tmp, &efi_pci_devices, list ) {
DBGC ( efipci, "EFIPCI " PCI_FMT " still active at shutdown; "
"forcing close\n", PCI_ARGS ( &efipci->pci ) );
pci_remove ( &efipci->pci );
efipci_destroy ( efidrv, efipci );
}
}
/** EFI PCI startup function */
struct startup_fn startup_pci __startup_fn ( STARTUP_NORMAL ) = {
.startup = efipci_driver_init,
.startup = efipci_driver_startup,
.shutdown = efipci_driver_shutdown,
};