]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Allow for custom methods for disconnecting existing drivers
authorMichael Brown <mcb30@ipxe.org>
Wed, 16 Apr 2025 20:26:45 +0000 (21:26 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 17 Apr 2025 09:08:54 +0000 (10:08 +0100)
Allow for greater control over the process used to disconnect existing
drivers from a device handle, by converting the "exclude" field from a
simple protocol GUID to a per-driver method.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/efi/nii.c
src/drivers/net/efi/nii.h
src/drivers/net/efi/snp.c
src/drivers/net/efi/snpnet.c
src/drivers/net/efi/snpnet.h
src/drivers/net/efi/snponly.c
src/drivers/usb/usbio.c
src/include/ipxe/efi/efi_driver.h
src/interface/efi/efi_driver.c
src/interface/efi/efi_pci.c

index 81f1838a4abe0812db24738d8afc15b62064169a..6381fb2dd31ed10ca2701b9fe2c096649ea59bb4 100644 (file)
@@ -1257,6 +1257,26 @@ static struct net_device_operations nii_operations = {
        .poll = nii_poll,
 };
 
+/**
+ * Exclude existing drivers
+ *
+ * @v device           EFI device handle
+ * @ret rc             Return status code
+ */
+int nii_exclude ( EFI_HANDLE device ) {
+       EFI_GUID *protocol = &efi_nii31_protocol_guid;
+       int rc;
+
+       /* Exclude existing NII protocol drivers */
+       if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) {
+               DBGC ( device, "NII %s could not exclude drivers: %s\n",
+                      efi_handle_name ( device ), strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
 /**
  * Attach driver to device
  *
index c10be9db5bf63871eff9b9c4aa62fb89f99e1387..df7ab7dbef53627a66a4842e7abb743d2c750c6e 100644 (file)
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 struct efi_device;
 
+extern int nii_exclude ( EFI_HANDLE device );
 extern int nii_start ( struct efi_device *efidev );
 extern void nii_stop ( struct efi_device *efidev );
 
index 7c4123677a4b7b1ab04c3edacc221acac36f6254..2e0d9df3ac35e7d5aab5fa19a72138e26fe738fe 100644 (file)
@@ -59,8 +59,8 @@ static int nii_supported ( EFI_HANDLE device ) {
 /** EFI SNP driver */
 struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_SNP ) = {
        .name = "SNP",
-       .exclude = &efi_simple_network_protocol_guid,
        .supported = snp_supported,
+       .exclude = snpnet_exclude,
        .start = snpnet_start,
        .stop = snpnet_stop,
 };
@@ -68,8 +68,8 @@ struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_SNP ) = {
 /** EFI NII driver */
 struct efi_driver nii_driver __efi_driver ( EFI_DRIVER_NII ) = {
        .name = "NII",
-       .exclude = &efi_nii31_protocol_guid,
        .supported = nii_supported,
+       .exclude = nii_exclude,
        .start = nii_start,
        .stop = nii_stop,
 };
index c8e2f2f6875eb9a36e9987fe4f19cf15a955a807..c4062a5a737d760fb0c2d7579f2347d9ca56018d 100644 (file)
@@ -528,6 +528,26 @@ int snpnet_supported ( EFI_HANDLE device, EFI_GUID *protocol ) {
        return 0;
 }
 
+/**
+ * Exclude existing drivers
+ *
+ * @v device           EFI device handle
+ * @ret rc             Return status code
+ */
+int snpnet_exclude ( EFI_HANDLE device ) {
+       EFI_GUID *protocol = &efi_simple_network_protocol_guid;
+       int rc;
+
+       /* Exclude existing SNP drivers */
+       if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) {
+               DBGC ( device, "SNP %s could not exclude drivers: %s\n",
+                      efi_handle_name ( device ), strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
 /**
  * Attach driver to device
  *
index 4699c7892f8d59da46cb46f9f7d269242d28bc0f..d3602a589c15412501ce74f16e0f54452b0a1463 100644 (file)
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 struct efi_device;
 
 extern int snpnet_supported ( EFI_HANDLE device, EFI_GUID *protocol );
+extern int snpnet_exclude ( EFI_HANDLE device );
 extern int snpnet_start ( struct efi_device *efidev );
 extern void snpnet_stop ( struct efi_device *efidev );
 
index 267572e34a55a489ca91a4480afa3d8388ad0b8f..88c74ed4282fff86600db353eecfcf65300e8c0e 100644 (file)
@@ -209,8 +209,8 @@ static int mnponly_supported ( EFI_HANDLE device ) {
 /** EFI SNP chainloading-device-only driver */
 struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_SNP ) = {
        .name = "SNPONLY",
-       .exclude = &efi_simple_network_protocol_guid,
        .supported = snponly_supported,
+       .exclude = snpnet_exclude,
        .start = snpnet_start,
        .stop = snpnet_stop,
 };
@@ -218,8 +218,8 @@ struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_SNP ) = {
 /** EFI NII chainloading-device-only driver */
 struct efi_driver niionly_driver __efi_driver ( EFI_DRIVER_NII ) = {
        .name = "NIIONLY",
-       .exclude = &efi_nii31_protocol_guid,
        .supported = niionly_supported,
+       .exclude = nii_exclude,
        .start = nii_start,
        .stop = nii_stop,
 };
index 991b290adcffb34d7fd78a843711dd27cbdc3d76..97860a2819e48b1971bcd53851d1b5a6c9bc8049 100644 (file)
@@ -1542,6 +1542,26 @@ static int usbio_interfaces ( struct usbio_device *usbio ) {
        return rc;
 }
 
+/**
+ * Exclude existing drivers
+ *
+ * @v device           EFI device handle
+ * @ret rc             Return status code
+ */
+static int usbio_exclude ( EFI_HANDLE device ) {
+       EFI_GUID *protocol = &efi_usb_io_protocol_guid;
+       int rc;
+
+       /* Exclude existing USB I/O protocol drivers */
+       if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) {
+               DBGC ( device, "USBIO %s could not exclude drivers: %s\n",
+                      efi_handle_name ( device ), strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
 /**
  * Attach driver to device
  *
@@ -1651,8 +1671,8 @@ static void usbio_stop ( struct efi_device *efidev ) {
 /** EFI USB I/O driver */
 struct efi_driver usbio_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
        .name = "USBIO",
-       .exclude = &efi_usb_io_protocol_guid,
        .supported = usbio_supported,
+       .exclude = usbio_exclude,
        .start = usbio_start,
        .stop = usbio_stop,
 };
index 4c21489199548ba5d43efb04797210dfe456a26e..5ab2d011a3330b90ddc2b502e5c1335b6fa7cc60 100644 (file)
@@ -33,8 +33,13 @@ struct efi_device {
 struct efi_driver {
        /** Name */
        const char *name;
-       /** Protocol to which exclusive access is required, if any */
-       EFI_GUID *exclude;
+       /**
+        * Exclude existing drivers
+        *
+        * @v device            EFI device handle
+        * @ret rc              Return status code
+        */
+       int ( * exclude ) ( EFI_HANDLE device );
        /**
         * Check if driver supports device
         *
@@ -95,6 +100,7 @@ extern void efidev_free ( struct efi_device *efidev );
 extern struct efi_device * efidev_parent ( struct device *dev );
 extern int efi_driver_install ( void );
 extern void efi_driver_uninstall ( void );
+extern int efi_driver_exclude ( EFI_HANDLE device, EFI_GUID *protocol );
 extern int efi_driver_connect_all ( void );
 extern void efi_driver_disconnect_all ( void );
 extern void efi_driver_reconnect_all ( void );
index 8c5e00bfbff7fb23ba87a194e176022c595de37e..ce1db228dcd9404afb6adec699ef51841df99e2d 100644 (file)
@@ -448,7 +448,7 @@ void efi_driver_uninstall ( void ) {
  * @v protocol         Protocol GUID
  * @ret rc             Return status code
  */
-static int efi_driver_exclude ( EFI_HANDLE device, EFI_GUID *protocol ) {
+int efi_driver_exclude ( EFI_HANDLE device, EFI_GUID *protocol ) {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers;
        EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener;
@@ -479,6 +479,8 @@ static int efi_driver_exclude ( EFI_HANDLE device, EFI_GUID *protocol ) {
        }
 
        /* Try to disconnect driver */
+       DBGC ( device, "EFIDRV %s disconnecting %s drivers\n",
+              efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
        if ( driver ) {
                DBGC ( device, "EFIDRV %s disconnecting %s driver ",
                       efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
@@ -514,7 +516,6 @@ static int efi_driver_connect ( EFI_HANDLE device ) {
        EFI_HANDLE drivers[2] =
                { efi_driver_binding.DriverBindingHandle, NULL };
        struct efi_driver *efidrv;
-       EFI_GUID *exclude;
        EFI_STATUS efirc;
        int rc;
 
@@ -533,17 +534,14 @@ static int efi_driver_connect ( EFI_HANDLE device ) {
               efi_handle_name ( device ) );
        efi_driver_disconnecting = 1;
        for_each_table_entry_reverse ( efidrv, EFI_DRIVERS ) {
-               exclude = efidrv->exclude;
-               if ( ! exclude )
+               if ( ! efidrv->exclude )
                        continue;
                if ( ( rc = efidrv->supported ( device ) ) != 0 )
                        continue;
-               DBGC ( device, "EFIDRV %s disconnecting %s drivers\n",
-                      efi_handle_name ( device ), efi_guid_ntoa ( exclude ) );
-               if ( ( rc = efi_driver_exclude ( device, exclude ) ) != 0 ) {
-                       DBGC ( device, "EFIDRV %s could not disconnect %s "
+               if ( ( rc = efidrv->exclude ( device ) ) != 0 ) {
+                       DBGC ( device, "EFIDRV %s could not disconnect "
                               "drivers: %s\n", efi_handle_name ( device ),
-                              efi_guid_ntoa ( exclude ), strerror ( rc ) );
+                              strerror ( rc ) );
                        /* Ignore the error and attempt to connect anyway */
                }
        }
index f98794c2715323e8f537305f65527933f0184ea8..dd11dd3425a0baf90a4bafe0c25d94214a7b3c07 100644 (file)
@@ -829,6 +829,26 @@ static int efipci_supported ( EFI_HANDLE device ) {
        return 0;
 }
 
+/**
+ * Exclude existing drivers
+ *
+ * @v device           EFI device handle
+ * @ret rc             Return status code
+ */
+static int efipci_exclude ( EFI_HANDLE device ) {
+       EFI_GUID *protocol = &efi_pci_io_protocol_guid;
+       int rc;
+
+       /* Exclude existing PCI I/O protocol drivers */
+       if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) {
+               DBGC ( device, "EFIPCI %s could not exclude drivers: %s\n",
+                      efi_handle_name ( device ), strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
 /**
  * Attach driver to device
  *
@@ -916,8 +936,8 @@ static void efipci_stop ( struct efi_device *efidev ) {
 /** EFI PCI driver */
 struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
        .name = "PCI",
-       .exclude = &efi_pci_io_protocol_guid,
        .supported = efipci_supported,
+       .exclude = efipci_exclude,
        .start = efipci_start,
        .stop = efipci_stop,
 };