diff options
author | Michael Brown | 2014-03-10 16:42:21 +0100 |
---|---|---|
committer | Michael Brown | 2014-03-10 17:39:46 +0100 |
commit | 8de6b973c487605002143d65d0082bb2ed50714e (patch) | |
tree | f30472b7cb371345aa5ee8bbc11570a6ec6bd536 /src/interface/efi/efi_init.c | |
parent | [efi] Allow for 64-bit EFI_STATUS codes (diff) | |
download | ipxe-8de6b973c487605002143d65d0082bb2ed50714e.tar.gz ipxe-8de6b973c487605002143d65d0082bb2ed50714e.tar.xz ipxe-8de6b973c487605002143d65d0082bb2ed50714e.zip |
[efi] Allow driver to be unloaded
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi/efi_init.c')
-rw-r--r-- | src/interface/efi/efi_init.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index 2f6ca89c..b4ed5c14 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <string.h> #include <errno.h> #include <ipxe/efi/efi.h> +#include <ipxe/efi/efi_driver.h> #include <ipxe/efi/Protocol/LoadedImage.h> #include <ipxe/efi/Protocol/DevicePath.h> #include <ipxe/uuid.h> @@ -50,6 +51,64 @@ static EFI_GUID efi_loaded_image_device_path_protocol_guid /** Event used to signal shutdown */ static EFI_EVENT efi_shutdown_event; +/* Forward declarations */ +static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle ); + +/** + * Check to see if driver supports a device + * + * @v driver EFI driver + * @v device EFI device + * @v child Path to child device, if any + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_image_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, + EFI_HANDLE device __unused, + EFI_DEVICE_PATH_PROTOCOL *child __unused ) { + + return EFI_UNSUPPORTED; +} + +/** + * Attach driver to device + * + * @v driver EFI driver + * @v device EFI device + * @v child Path to child device, if any + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_image_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, + EFI_HANDLE device __unused, + EFI_DEVICE_PATH_PROTOCOL *child __unused ) { + + return EFI_UNSUPPORTED; +} + +/** + * Detach driver from device + * + * @v driver EFI driver + * @v device EFI device + * @v pci PCI device + * @v num_children Number of child devices + * @v children List of child devices + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_image_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused, + EFI_HANDLE device __unused, UINTN num_children __unused, + EFI_HANDLE *children __unused ) { + + return EFI_UNSUPPORTED; +} + +/** EFI loaded image driver */ +static struct efi_driver efi_image_driver = + EFI_DRIVER_INIT ( NULL, efi_image_supported, efi_image_start, + efi_image_stop ); + /** * Shut down in preparation for booting an OS. * @@ -189,5 +248,43 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, return efirc; } + /* Install an EFI driver on the image handle, to allow the + * driver to be subsequently unloaded. + */ + efi_image_driver.driver.DriverBindingHandle = image_handle; + if ( ( rc = efi_driver_install ( &efi_image_driver ) ) != 0 ) { + DBGC ( systab, "EFI could not install loaded image driver: " + "%s\n", strerror ( rc ) ); + return EFIRC ( rc ); + } + + /* Install image unload method */ + efi_loaded_image->Unload = efi_unload; + + return 0; +} + +/** + * Shut down EFI environment + * + * @v image_handle Image handle + */ +static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_SYSTEM_TABLE *systab = efi_systab; + + DBGC ( systab, "EFI image unloading\n" ); + + /* Shut down */ + shutdown_exit(); + + /* Uninstall exit boot services event */ + bs->CloseEvent ( efi_shutdown_event ); + + /* Uninstall loaded image driver */ + efi_driver_uninstall ( &efi_image_driver ); + + DBGC ( systab, "EFI image unloaded\n" ); + return 0; } |