summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_driver.c
diff options
context:
space:
mode:
authorMichael Brown2014-03-10 16:42:21 +0100
committerMichael Brown2014-03-10 17:39:46 +0100
commit8de6b973c487605002143d65d0082bb2ed50714e (patch)
treef30472b7cb371345aa5ee8bbc11570a6ec6bd536 /src/interface/efi/efi_driver.c
parent[efi] Allow for 64-bit EFI_STATUS codes (diff)
downloadipxe-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_driver.c')
-rw-r--r--src/interface/efi/efi_driver.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c
index 13ed1f50..25145aca 100644
--- a/src/interface/efi/efi_driver.c
+++ b/src/interface/efi/efi_driver.c
@@ -122,7 +122,7 @@ efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
* Install EFI driver
*
* @v efidrv EFI driver
- * @ret efirc EFI status code
+ * @ret rc Return status code
*/
int efi_driver_install ( struct efi_driver *efidrv ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
@@ -143,7 +143,9 @@ int efi_driver_install ( struct efi_driver *efidrv ) {
efi_snprintf ( efidrv->wname,
( sizeof ( efidrv->wname ) /
sizeof ( efidrv->wname[0] ) ),
- PRODUCT_SHORT_NAME " - %s", efidrv->name );
+ PRODUCT_SHORT_NAME "%s%s",
+ ( efidrv->name ? " - " : "" ),
+ ( efidrv->name ? efidrv->name : "" ) );
/* Install driver */
if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
@@ -160,3 +162,43 @@ int efi_driver_install ( struct efi_driver *efidrv ) {
DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name );
return 0;
}
+
+/**
+ * Uninstall EFI driver
+ *
+ * @v efidrv EFI driver
+ */
+void efi_driver_uninstall ( struct efi_driver *efidrv ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE *handles;
+ UINTN num_handles;
+ EFI_STATUS efirc;
+ UINTN i;
+ int rc;
+
+ /* Disconnect the driver from its devices */
+ if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL,
+ &num_handles,
+ &handles ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( efidrv, "EFIDRV %s could not list handles: %s\n",
+ efidrv->name, strerror ( rc ) );
+ /* No way to disconnect driver; leave it loaded */
+ return;
+ }
+ DBGC ( efidrv, "EFIDRV %s disconnecting devices\n", efidrv->name );
+ for ( i = 0 ; i < num_handles ; i++ ) {
+ bs->DisconnectController ( handles[i],
+ efidrv->driver.DriverBindingHandle,
+ NULL );
+ }
+ bs->FreePool ( handles );
+
+ /* Uninstall the driver */
+ bs->UninstallMultipleProtocolInterfaces (
+ efidrv->driver.DriverBindingHandle,
+ &efi_driver_binding_protocol_guid, &efidrv->driver,
+ &efi_component_name2_protocol_guid, &efidrv->wtf,
+ NULL );
+ DBGC ( efidrv, "EFIDRV %s uninstalled\n", efidrv->name );
+}