mirror of
https://github.com/ipxe/ipxe
synced 2026-02-28 03:11:18 +03:00
[efi] Allow for custom methods for disconnecting existing drivers
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>
This commit is contained in:
@@ -1257,6 +1257,26 @@ static struct net_device_operations nii_operations = {
|
|||||||
.poll = nii_poll,
|
.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
|
* Attach driver to device
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
|
|
||||||
struct efi_device;
|
struct efi_device;
|
||||||
|
|
||||||
|
extern int nii_exclude ( EFI_HANDLE device );
|
||||||
extern int nii_start ( struct efi_device *efidev );
|
extern int nii_start ( struct efi_device *efidev );
|
||||||
extern void nii_stop ( struct efi_device *efidev );
|
extern void nii_stop ( struct efi_device *efidev );
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ static int nii_supported ( EFI_HANDLE device ) {
|
|||||||
/** EFI SNP driver */
|
/** EFI SNP driver */
|
||||||
struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_SNP ) = {
|
struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_SNP ) = {
|
||||||
.name = "SNP",
|
.name = "SNP",
|
||||||
.exclude = &efi_simple_network_protocol_guid,
|
|
||||||
.supported = snp_supported,
|
.supported = snp_supported,
|
||||||
|
.exclude = snpnet_exclude,
|
||||||
.start = snpnet_start,
|
.start = snpnet_start,
|
||||||
.stop = snpnet_stop,
|
.stop = snpnet_stop,
|
||||||
};
|
};
|
||||||
@@ -68,8 +68,8 @@ struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_SNP ) = {
|
|||||||
/** EFI NII driver */
|
/** EFI NII driver */
|
||||||
struct efi_driver nii_driver __efi_driver ( EFI_DRIVER_NII ) = {
|
struct efi_driver nii_driver __efi_driver ( EFI_DRIVER_NII ) = {
|
||||||
.name = "NII",
|
.name = "NII",
|
||||||
.exclude = &efi_nii31_protocol_guid,
|
|
||||||
.supported = nii_supported,
|
.supported = nii_supported,
|
||||||
|
.exclude = nii_exclude,
|
||||||
.start = nii_start,
|
.start = nii_start,
|
||||||
.stop = nii_stop,
|
.stop = nii_stop,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -528,6 +528,26 @@ int snpnet_supported ( EFI_HANDLE device, EFI_GUID *protocol ) {
|
|||||||
return 0;
|
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
|
* Attach driver to device
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
struct efi_device;
|
struct efi_device;
|
||||||
|
|
||||||
extern int snpnet_supported ( EFI_HANDLE device, EFI_GUID *protocol );
|
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 int snpnet_start ( struct efi_device *efidev );
|
||||||
extern void snpnet_stop ( struct efi_device *efidev );
|
extern void snpnet_stop ( struct efi_device *efidev );
|
||||||
|
|
||||||
|
|||||||
@@ -209,8 +209,8 @@ static int mnponly_supported ( EFI_HANDLE device ) {
|
|||||||
/** EFI SNP chainloading-device-only driver */
|
/** EFI SNP chainloading-device-only driver */
|
||||||
struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_SNP ) = {
|
struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_SNP ) = {
|
||||||
.name = "SNPONLY",
|
.name = "SNPONLY",
|
||||||
.exclude = &efi_simple_network_protocol_guid,
|
|
||||||
.supported = snponly_supported,
|
.supported = snponly_supported,
|
||||||
|
.exclude = snpnet_exclude,
|
||||||
.start = snpnet_start,
|
.start = snpnet_start,
|
||||||
.stop = snpnet_stop,
|
.stop = snpnet_stop,
|
||||||
};
|
};
|
||||||
@@ -218,8 +218,8 @@ struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_SNP ) = {
|
|||||||
/** EFI NII chainloading-device-only driver */
|
/** EFI NII chainloading-device-only driver */
|
||||||
struct efi_driver niionly_driver __efi_driver ( EFI_DRIVER_NII ) = {
|
struct efi_driver niionly_driver __efi_driver ( EFI_DRIVER_NII ) = {
|
||||||
.name = "NIIONLY",
|
.name = "NIIONLY",
|
||||||
.exclude = &efi_nii31_protocol_guid,
|
|
||||||
.supported = niionly_supported,
|
.supported = niionly_supported,
|
||||||
|
.exclude = nii_exclude,
|
||||||
.start = nii_start,
|
.start = nii_start,
|
||||||
.stop = nii_stop,
|
.stop = nii_stop,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1542,6 +1542,26 @@ static int usbio_interfaces ( struct usbio_device *usbio ) {
|
|||||||
return rc;
|
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
|
* Attach driver to device
|
||||||
*
|
*
|
||||||
@@ -1651,8 +1671,8 @@ static void usbio_stop ( struct efi_device *efidev ) {
|
|||||||
/** EFI USB I/O driver */
|
/** EFI USB I/O driver */
|
||||||
struct efi_driver usbio_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
|
struct efi_driver usbio_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
|
||||||
.name = "USBIO",
|
.name = "USBIO",
|
||||||
.exclude = &efi_usb_io_protocol_guid,
|
|
||||||
.supported = usbio_supported,
|
.supported = usbio_supported,
|
||||||
|
.exclude = usbio_exclude,
|
||||||
.start = usbio_start,
|
.start = usbio_start,
|
||||||
.stop = usbio_stop,
|
.stop = usbio_stop,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,8 +33,13 @@ struct efi_device {
|
|||||||
struct efi_driver {
|
struct efi_driver {
|
||||||
/** Name */
|
/** Name */
|
||||||
const char *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
|
* 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 struct efi_device * efidev_parent ( struct device *dev );
|
||||||
extern int efi_driver_install ( void );
|
extern int efi_driver_install ( void );
|
||||||
extern void efi_driver_uninstall ( 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 int efi_driver_connect_all ( void );
|
||||||
extern void efi_driver_disconnect_all ( void );
|
extern void efi_driver_disconnect_all ( void );
|
||||||
extern void efi_driver_reconnect_all ( void );
|
extern void efi_driver_reconnect_all ( void );
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ void efi_driver_uninstall ( void ) {
|
|||||||
* @v protocol Protocol GUID
|
* @v protocol Protocol GUID
|
||||||
* @ret rc Return status code
|
* @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_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||||
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers;
|
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers;
|
||||||
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener;
|
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 */
|
/* Try to disconnect driver */
|
||||||
|
DBGC ( device, "EFIDRV %s disconnecting %s drivers\n",
|
||||||
|
efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
|
||||||
if ( driver ) {
|
if ( driver ) {
|
||||||
DBGC ( device, "EFIDRV %s disconnecting %s driver ",
|
DBGC ( device, "EFIDRV %s disconnecting %s driver ",
|
||||||
efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
|
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_HANDLE drivers[2] =
|
||||||
{ efi_driver_binding.DriverBindingHandle, NULL };
|
{ efi_driver_binding.DriverBindingHandle, NULL };
|
||||||
struct efi_driver *efidrv;
|
struct efi_driver *efidrv;
|
||||||
EFI_GUID *exclude;
|
|
||||||
EFI_STATUS efirc;
|
EFI_STATUS efirc;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -533,17 +534,14 @@ static int efi_driver_connect ( EFI_HANDLE device ) {
|
|||||||
efi_handle_name ( device ) );
|
efi_handle_name ( device ) );
|
||||||
efi_driver_disconnecting = 1;
|
efi_driver_disconnecting = 1;
|
||||||
for_each_table_entry_reverse ( efidrv, EFI_DRIVERS ) {
|
for_each_table_entry_reverse ( efidrv, EFI_DRIVERS ) {
|
||||||
exclude = efidrv->exclude;
|
if ( ! efidrv->exclude )
|
||||||
if ( ! exclude )
|
|
||||||
continue;
|
continue;
|
||||||
if ( ( rc = efidrv->supported ( device ) ) != 0 )
|
if ( ( rc = efidrv->supported ( device ) ) != 0 )
|
||||||
continue;
|
continue;
|
||||||
DBGC ( device, "EFIDRV %s disconnecting %s drivers\n",
|
if ( ( rc = efidrv->exclude ( device ) ) != 0 ) {
|
||||||
efi_handle_name ( device ), efi_guid_ntoa ( exclude ) );
|
DBGC ( device, "EFIDRV %s could not disconnect "
|
||||||
if ( ( rc = efi_driver_exclude ( device, exclude ) ) != 0 ) {
|
|
||||||
DBGC ( device, "EFIDRV %s could not disconnect %s "
|
|
||||||
"drivers: %s\n", efi_handle_name ( device ),
|
"drivers: %s\n", efi_handle_name ( device ),
|
||||||
efi_guid_ntoa ( exclude ), strerror ( rc ) );
|
strerror ( rc ) );
|
||||||
/* Ignore the error and attempt to connect anyway */
|
/* Ignore the error and attempt to connect anyway */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -829,6 +829,26 @@ static int efipci_supported ( EFI_HANDLE device ) {
|
|||||||
return 0;
|
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
|
* Attach driver to device
|
||||||
*
|
*
|
||||||
@@ -916,8 +936,8 @@ static void efipci_stop ( struct efi_device *efidev ) {
|
|||||||
/** EFI PCI driver */
|
/** EFI PCI driver */
|
||||||
struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
|
struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
|
||||||
.name = "PCI",
|
.name = "PCI",
|
||||||
.exclude = &efi_pci_io_protocol_guid,
|
|
||||||
.supported = efipci_supported,
|
.supported = efipci_supported,
|
||||||
|
.exclude = efipci_exclude,
|
||||||
.start = efipci_start,
|
.start = efipci_start,
|
||||||
.stop = efipci_stop,
|
.stop = efipci_stop,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user