From 62149deb116516bb0d70b756bfc4f5b4669034da Mon Sep 17 00:00:00 2001 From: Geoff Lywood Date: Thu, 27 May 2010 20:08:28 -0700 Subject: [efi] Add the "snpnet" driver Add a new network driver that consumes the EFI Simple Network Protocol. Also add a bus driver that can find the Simple Network Protocol that iPXE was loaded from; the resulting behavior is similar to the "undionly" driver for BIOS systems. Signed-off-by: Michael Brown --- src/image/efi_image.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'src/image') diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 6eb943b61..6b6600de8 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -21,12 +21,27 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 ); struct image_type efi_image_type __image_type ( PROBE_NORMAL ); +/** 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 ( SHUTDOWN_BOOT ); +} + /** * Execute EFI image * @@ -39,6 +54,7 @@ static int efi_image_exec ( struct image *image ) { UINTN exit_data_size; CHAR16 *exit_data; EFI_STATUS efirc; + int rc; /* Attempt loading image */ if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL, @@ -50,21 +66,36 @@ 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 ) ); - goto done; } - done: + 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. */ bs->UnloadImage ( handle ); - return EFIRC_TO_RC ( efirc ); + return rc; } /** -- cgit v1.2.3-55-g7522