]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Connect driver to devices as part of installation
authorMichael Brown <mcb30@ipxe.org>
Tue, 11 Mar 2014 15:34:47 +0000 (15:34 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 12 Mar 2014 15:34:44 +0000 (15:34 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/interface/efi/efi_driver.c

index 25145aca5bc6bf666d2a421ebb6f1a0f0ee7eaa7..1bc28e7c339400592bbd57d2a605d1ce80b00de7 100644 (file)
@@ -118,6 +118,70 @@ efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
        return EFI_UNSUPPORTED;
 }
 
+/**
+ * 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
  *
@@ -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 (