summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_driver.c
diff options
context:
space:
mode:
authorMichael Brown2014-03-11 16:34:47 +0100
committerMichael Brown2014-03-12 16:34:44 +0100
commit26029658063dcafcca746640a28a76d4f7f4a66e (patch)
treeceb5eb29ea8c2f9e3933770829dcf6ff0dc45e29 /src/interface/efi/efi_driver.c
parent[efi] Allow driver to be unloaded (diff)
downloadipxe-26029658063dcafcca746640a28a76d4f7f4a66e.tar.gz
ipxe-26029658063dcafcca746640a28a76d4f7f4a66e.tar.xz
ipxe-26029658063dcafcca746640a28a76d4f7f4a66e.zip
[efi] Connect driver to devices as part of installation
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.c89
1 files changed, 69 insertions, 20 deletions
diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c
index 25145aca..1bc28e7c 100644
--- a/src/interface/efi/efi_driver.c
+++ b/src/interface/efi/efi_driver.c
@@ -119,6 +119,70 @@ efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
}
/**
+ * Try to connect EFI driver
+ *
+ * @v efidrv EFI driver
+ * @v handle Controller handle
+ */
+static void efi_driver_connect ( struct efi_driver *efidrv, EFI_HANDLE handle ){
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE drivers[2] = { efidrv->driver.DriverBindingHandle, NULL };
+
+ bs->ConnectController ( handle, drivers, NULL, FALSE );
+}
+
+/**
+ * Try to disconnect EFI driver
+ *
+ * @v efidrv EFI driver
+ * @v handle Controller handle
+ */
+static void efi_driver_disconnect ( struct efi_driver *efidrv,
+ EFI_HANDLE handle ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ bs->DisconnectController ( handle, efidrv->driver.DriverBindingHandle,
+ NULL );
+}
+
+/**
+ * Connect/disconnect EFI driver from all handles
+ *
+ * @v efidrv EFI driver
+ * @v method Connect/disconnect method
+ * @ret rc Return status code
+ */
+static int efi_driver_handles ( struct efi_driver *efidrv,
+ void ( * method ) ( struct efi_driver *efidrv,
+ EFI_HANDLE handle ) ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE *handles;
+ UINTN num_handles;
+ EFI_STATUS efirc;
+ UINTN i;
+ int rc;
+
+ /* Enumerate all handles */
+ 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 ) );
+ return rc;
+ }
+
+ /* Connect/disconnect driver from all handles */
+ for ( i = 0 ; i < num_handles ; i++ )
+ method ( efidrv, handles[i] );
+
+ /* Free list of handles */
+ bs->FreePool ( handles );
+
+ return 0;
+}
+
+/**
* Install EFI driver
*
* @v efidrv EFI driver
@@ -159,6 +223,10 @@ int efi_driver_install ( struct efi_driver *efidrv ) {
return rc;
}
+ /* Connect devices */
+ DBGC ( efidrv, "EFIDRV %s connecting devices\n", efidrv->name );
+ efi_driver_handles ( efidrv, efi_driver_connect );
+
DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name );
return 0;
}
@@ -170,29 +238,10 @@ int efi_driver_install ( struct efi_driver *efidrv ) {
*/
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 );
+ efi_driver_handles ( efidrv, efi_driver_disconnect );
/* Uninstall the driver */
bs->UninstallMultipleProtocolInterfaces (