This commit is contained in:
Michael Brown
2023-06-27 18:15:17 +01:00
parent 570134c7ba
commit 22916e6284
+250 -214
View File
@@ -37,71 +37,82 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
*/ */
/** A driver veto candidate */ /** A driver veto */
struct efi_veto_candidate { struct efi_veto {
/** Veto name (for debugging) */ /** Veto name (for debugging) */
const char *name; const char *name;
/** /**
* Check if driver is vetoed * Check if driver is vetoed
* *
* @v binding Driver binding protocol
* @v loaded Loaded image protocol
* @v wtf Component name protocol, if present
* @v manufacturer Manufacturer name, if present * @v manufacturer Manufacturer name, if present
* @v name Driver name (in "eng" language), if present * @v name Driver name (in "eng" language), if present
* @ret vetoed Driver is to be vetoed * @ret vetoed Driver is to be vetoed
*/ */
int ( * veto ) ( EFI_DRIVER_BINDING_PROTOCOL *binding, int ( * veto ) ( const char *manufacturer, const CHAR16 *name );
EFI_LOADED_IMAGE_PROTOCOL *loaded,
EFI_COMPONENT_NAME_PROTOCOL *wtf,
const char *manufacturer, const CHAR16 *name );
};
/** A driver veto */
struct efi_veto {
/** Target handle */
EFI_HANDLE target;
/** Image handle */
EFI_HANDLE image;
/** Loaded image protocol */
EFI_LOADED_IMAGE_PROTOCOL *loaded;
}; };
/** /**
* Unload an EFI driver * Unload an EFI driver
* *
* @v veto Driver veto * @v driver Driver binding handle
* @v image Image handle to fill in on failure
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_unload ( struct efi_veto *veto ) { static int efi_veto_unload ( EFI_HANDLE driver, EFI_HANDLE *image ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE target = veto->target; union {
EFI_HANDLE image = veto->image; EFI_DRIVER_BINDING_PROTOCOL *binding;
void *interface;
} binding;
EFI_STATUS efirc; EFI_STATUS efirc;
int rc; int rc;
/* Unload the driver */ /* Clear image handle */
if ( ( efirc = bs->UnloadImage ( image ) ) != 0 ) { *image = NULL;
/* Open driver binding protocol */
if ( ( efirc = bs->OpenProtocol (
driver, &efi_driver_binding_protocol_guid,
&binding.interface, efi_image_handle, driver,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not unload", DBGC ( driver, "EFIVETO %s could not open driver binding "
efi_handle_name ( target ) ); "protocol: %s\n", efi_handle_name ( driver ),
DBGC ( target, " %s: %s\n", efi_handle_name ( image ),
strerror ( rc ) ); strerror ( rc ) );
return rc; goto err_binding;
} }
return 0; /* Identify image handle */
*image = binding.binding->ImageHandle;
/* Unload the driver */
if ( ( efirc = bs->UnloadImage ( *image ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( driver, "EFIVETO %s could not unload",
efi_handle_name ( driver ) );
DBGC ( driver, " %s: %s\n",
efi_handle_name ( *image ), strerror ( rc ) );
goto err_unload;
}
/* Invalidate now-unloaded image handle */
*image = NULL;
err_unload:
bs->CloseProtocol ( driver, &efi_driver_binding_protocol_guid,
efi_image_handle, driver );
err_binding:
return rc;
} }
/** /**
* Disconnect an EFI driver from all handles * Disconnect an EFI driver from all handles
* *
* @v veto Driver veto * @v driver Driver binding handle
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_disconnect ( struct efi_veto *veto ) { static int efi_veto_disconnect ( EFI_HANDLE driver ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE target = veto->target;
EFI_HANDLE *handles; EFI_HANDLE *handles;
EFI_HANDLE handle; EFI_HANDLE handle;
UINTN count; UINTN count;
@@ -113,20 +124,20 @@ static int efi_veto_disconnect ( struct efi_veto *veto ) {
if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL, if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL,
&count, &handles ) ) != 0 ) { &count, &handles ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not enumerate handles: %s\n", DBGC ( driver, "EFIVETO %s could not enumerate handles: %s\n",
efi_handle_name ( target ), strerror ( rc ) ); efi_handle_name ( driver ), strerror ( rc ) );
goto err_list; goto err_list;
} }
/* Disconnect driver from all handles, in reverse order */ /* Disconnect driver from all handles, in reverse order */
for ( i = 0 ; i < count ; i++ ) { for ( i = 0 ; i < count ; i++ ) {
handle = handles[ count - i - 1 ]; handle = handles[ count - i - 1 ];
efirc = bs->DisconnectController ( handle, target, NULL ); efirc = bs->DisconnectController ( handle, driver, NULL );
if ( ( efirc != 0 ) && ( efirc != EFI_NOT_FOUND ) ) { if ( ( efirc != 0 ) && ( efirc != EFI_NOT_FOUND ) ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not disconnect", DBGC ( driver, "EFIVETO %s could not disconnect",
efi_handle_name ( target ) ); efi_handle_name ( driver ) );
DBGC ( target, " %s: %s\n", DBGC ( driver, " %s: %s\n",
efi_handle_name ( handle ), strerror ( rc ) ); efi_handle_name ( handle ), strerror ( rc ) );
goto err_disconnect; goto err_disconnect;
} }
@@ -134,8 +145,8 @@ static int efi_veto_disconnect ( struct efi_veto *veto ) {
/* Success */ /* Success */
rc = 0; rc = 0;
DBGC2 ( target, "EFIVETO %s disconnected all handles\n", DBGC2 ( driver, "EFIVETO %s disconnected all handles\n",
efi_handle_name ( target ) ); efi_handle_name ( driver ) );
err_disconnect: err_disconnect:
bs->FreePool ( handles ); bs->FreePool ( handles );
@@ -144,66 +155,79 @@ static int efi_veto_disconnect ( struct efi_veto *veto ) {
} }
/** /**
* Uninstall an EFI driver binding protocol * Uninstall an EFI protocol
* *
* @v veto Driver veto * @v agent Agent handle
* @v loaded Loaded image protocol filter, or NULL
* @v handle Potentially opened handle
* @v protocol Installed protocol
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_uninstall ( struct efi_veto *veto ) { static int efi_veto_uninstall ( EFI_HANDLE agent,
EFI_LOADED_IMAGE_PROTOCOL *loaded,
EFI_HANDLE handle, EFI_GUID *protocol ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE target = veto->target; void *interface;
union { void *method;
EFI_DRIVER_BINDING_PROTOCOL *binding; size_t offset;
void *interface;
} binding;
EFI_STATUS efirc; EFI_STATUS efirc;
int rc; int rc;
/* Open driver binding protocol */ /* Open protocol */
if ( ( efirc = bs->OpenProtocol ( if ( ( efirc = bs->OpenProtocol (
target, &efi_driver_binding_protocol_guid, handle, protocol, &interface, efi_image_handle, agent,
&binding.interface, efi_image_handle, target,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not open driver binding " DBGC ( agent, "EFIVETO %s could not open %s",
"protocol: %s\n", efi_handle_name ( target ), efi_handle_name ( agent ), efi_guid_ntoa ( protocol ) );
strerror ( rc ) ); DBGC ( agent, " on %s: %s\n",
efi_handle_name ( handle ), strerror ( rc ) );
return rc; return rc;
} }
/* Close driver binding protocol */ /* Get representative method pointer, if known */
bs->CloseProtocol ( target, &efi_driver_binding_protocol_guid, method = efi_veto_method ( protocol, interface );
efi_image_handle, target );
/* Uninstall driver binding protocol */ /* Close protocol */
bs->CloseProtocol ( handle, protocol, efi_image_handle, agent );
/* Do nothing if method does not match filter */
if ( loaded ) {
offset = ( method - loaded->ImageBase );
if ( offset > loaded->ImageSize )
return 0;
}
/* Print debug message before potential invalidation of handle */
DBGC2 ( agent, "EFIVETO %s uninstalling %s",
efi_handle_name ( agent ), efi_guid_ntoa ( protocol ) );
DBGC2 ( agent, " from %s\n", efi_handle_name ( handle ) );
/* Uninstall protocol */
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces ( if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
target, &efi_driver_binding_protocol_guid, handle, protocol, interface, NULL ) ) != 0 ) {
binding.binding, NULL ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not uninstall driver " DBGC ( agent, "EFIVETO %s could not uninstall %s",
"binding protocol: %s\n", efi_handle_name ( agent ), efi_guid_ntoa ( protocol ) );
efi_handle_name ( target ), strerror ( rc ) ); DBGC ( agent, " from %s: %s\n",
efi_handle_name ( handle ), strerror ( rc ) );
return rc; return rc;
} }
DBGC2 ( target, "EFIVETO %s uninstalled driver binding protocol\n",
efi_handle_name ( target ) );
return 0; return 0;
} }
/** /**
* Close protocol on handle potentially opened by an EFI driver * Close protocol on handle potentially opened by an EFI driver
* *
* @v veto Driver veto * @v agent Agent handle
* @v handle Potentially opened handle * @v handle Potentially opened handle
* @v protocol Opened protocol * @v protocol Opened protocol
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_close_protocol ( struct efi_veto *veto, EFI_HANDLE handle, static int efi_veto_close ( EFI_HANDLE agent, EFI_HANDLE handle,
EFI_GUID *protocol ) { EFI_GUID *protocol ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE target = veto->target;
EFI_HANDLE image = veto->image;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener;
EFI_HANDLE controller; EFI_HANDLE controller;
@@ -216,9 +240,9 @@ static int efi_veto_close_protocol ( struct efi_veto *veto, EFI_HANDLE handle,
if ( ( efirc = bs->OpenProtocolInformation ( handle, protocol, &openers, if ( ( efirc = bs->OpenProtocolInformation ( handle, protocol, &openers,
&count ) ) != 0 ) { &count ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not retrieve openers", DBGC ( agent, "EFIVETO %s could not retrieve openers",
efi_handle_name ( target ) ); efi_handle_name ( agent ) );
DBGC ( target, " of %s %s: %s", efi_handle_name ( handle ), DBGC ( agent, " of %s %s: %s", efi_handle_name ( handle ),
efi_guid_ntoa ( protocol ), strerror ( rc ) ); efi_guid_ntoa ( protocol ), strerror ( rc ) );
goto err_list; goto err_list;
} }
@@ -226,19 +250,18 @@ static int efi_veto_close_protocol ( struct efi_veto *veto, EFI_HANDLE handle,
/* Close anything opened by this driver */ /* Close anything opened by this driver */
for ( i = 0 ; i < count ; i++ ) { for ( i = 0 ; i < count ; i++ ) {
opener = &openers[ count - i - 1 ]; opener = &openers[ count - i - 1 ];
if ( ( opener->AgentHandle != target ) && if ( opener->AgentHandle != agent )
( opener->AgentHandle != image ) ) {
continue; continue;
}
controller = opener->ControllerHandle; controller = opener->ControllerHandle;
DBGC_EFI_OPENER ( target, handle, protocol, opener ); DBGC_EFI_OPENER ( agent, handle, protocol, opener );
if ( ( efirc = bs->CloseProtocol ( handle, protocol, target, if ( ( efirc = bs->CloseProtocol ( handle, protocol, agent,
controller ) ) != 0 ) { controller ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not close stray open", DBGC ( agent, "EFIVETO %s could not close stray open",
efi_handle_name ( target ) ); efi_handle_name ( agent ) );
DBGC ( target, " of %s: %s\n", DBGC ( agent, " of %s %s: %s\n",
efi_handle_name ( handle ), strerror ( rc ) ); efi_handle_name ( handle ),
efi_guid_ntoa ( protocol ), strerror ( rc ) );
goto err_close; goto err_close;
} }
} }
@@ -253,15 +276,17 @@ static int efi_veto_close_protocol ( struct efi_veto *veto, EFI_HANDLE handle,
} }
/** /**
* Close handle potentially opened by an EFI driver * Close/uninstall handle potentially used by an EFI driver
* *
* @v veto Driver veto * @v agent Agent handle
* @v loaded Loaded image protocol for uninstallation, or NULL
* @v handle Potentially opened handle * @v handle Potentially opened handle
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_close_handle ( struct efi_veto *veto, EFI_HANDLE handle ) { static int efi_veto_handle ( EFI_HANDLE agent,
EFI_LOADED_IMAGE_PROTOCOL *loaded,
EFI_HANDLE handle ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE target = veto->target;
EFI_GUID **protocols; EFI_GUID **protocols;
EFI_GUID *protocol; EFI_GUID *protocol;
UINTN count; UINTN count;
@@ -273,9 +298,9 @@ static int efi_veto_close_handle ( struct efi_veto *veto, EFI_HANDLE handle ) {
if ( ( efirc = bs->ProtocolsPerHandle ( handle, &protocols, if ( ( efirc = bs->ProtocolsPerHandle ( handle, &protocols,
&count ) ) != 0 ) { &count ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not retrieve protocols", DBGC ( agent, "EFIVETO %s could not retrieve protocols",
efi_handle_name ( target ) ); efi_handle_name ( agent ) );
DBGC ( target, " for %s: %s\n", DBGC ( agent, " for %s: %s\n",
efi_handle_name ( handle ), strerror ( rc ) ); efi_handle_name ( handle ), strerror ( rc ) );
goto err_list; goto err_list;
} }
@@ -283,14 +308,24 @@ static int efi_veto_close_handle ( struct efi_veto *veto, EFI_HANDLE handle ) {
/* Close each protocol */ /* Close each protocol */
for ( i = 0 ; i < count ; i++ ) { for ( i = 0 ; i < count ; i++ ) {
protocol = protocols[ count - i - 1]; protocol = protocols[ count - i - 1];
if ( ( rc = efi_veto_close_protocol ( veto, handle, if ( ( rc = efi_veto_close ( agent, handle, protocol ) ) != 0 )
protocol ) ) != 0 )
goto err_close; goto err_close;
} }
/* Uninstall each protocol, if applicable */
if ( loaded ) {
for ( i = 0 ; i < count ; i++ ) {
protocol = protocols[ count - i - 1];
if ( ( rc = efi_veto_uninstall ( agent, loaded, handle,
protocol ) ) != 0 )
goto err_uninstall;
}
}
/* Success */ /* Success */
rc = 0; rc = 0;
err_uninstall:
err_close: err_close:
bs->FreePool ( protocols ); bs->FreePool ( protocols );
err_list: err_list:
@@ -298,14 +333,15 @@ static int efi_veto_close_handle ( struct efi_veto *veto, EFI_HANDLE handle ) {
} }
/** /**
* Close all remaining handles opened by an EFI driver * Close/uninstall all remaining handles used by an EFI driver
* *
* @v veto Driver veto * @v agent Agent handle
* @v loaded Loaded image protocol for uninstallation, or NULL
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_close ( struct efi_veto *veto ) { static int efi_veto_handles ( EFI_HANDLE agent,
EFI_LOADED_IMAGE_PROTOCOL *loaded ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE target = veto->target;
EFI_HANDLE *handles; EFI_HANDLE *handles;
EFI_HANDLE handle; EFI_HANDLE handle;
UINTN count; UINTN count;
@@ -317,24 +353,25 @@ static int efi_veto_close ( struct efi_veto *veto ) {
if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL, if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL,
&count, &handles ) ) != 0 ) { &count, &handles ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( target, "EFIVETO %s could not enumerate handles: %s\n", DBGC ( agent, "EFIVETO %s could not enumerate handles: %s\n",
efi_handle_name ( target ), strerror ( rc ) ); efi_handle_name ( agent ), strerror ( rc ) );
goto err_list; goto err_list;
} }
/* Close each handle */ /* Close and/or uninstall each handle */
for ( i = 0 ; i < count ; i++ ) { for ( i = 0 ; i < count ; i++ ) {
handle = handles[ count - i - 1 ]; handle = handles[ count - i - 1 ];
if ( ( rc = efi_veto_close_handle ( veto, handle ) ) != 0 ) if ( ( rc = efi_veto_handle ( agent, loaded, handle ) ) != 0 )
goto err_close; goto err_handle;
} }
/* Success */ /* Success */
rc = 0; rc = 0;
DBGC2 ( target, "EFIVETO %s closed all remaining handles\n", DBGC2 ( agent, "EFIVETO %s closed%s all remaining handles\n",
efi_handle_name ( target ) ); efi_handle_name ( agent ),
( loaded ? " and uninstalled" : "" ) );
err_close: err_handle:
bs->FreePool ( handles ); bs->FreePool ( handles );
err_list: err_list:
return rc; return rc;
@@ -343,65 +380,103 @@ static int efi_veto_close ( struct efi_veto *veto ) {
/** /**
* Terminate an EFI driver with extreme prejudice * Terminate an EFI driver with extreme prejudice
* *
* @v veto Driver veto * @v driver Driver handle
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_destroy ( struct efi_veto *veto ) { static int efi_veto_destroy ( EFI_HANDLE driver ) {
EFI_HANDLE target = veto->target; EFI_GUID *binding = &efi_driver_binding_protocol_guid;
int rc; int rc;
/* Disconnect driver from all handles */ /* Disconnect driver from all handles */
if ( ( rc = efi_veto_disconnect ( veto ) ) != 0 ) if ( ( rc = efi_veto_disconnect ( driver ) ) != 0 )
return rc; return rc;
/* Uninstall driver binding protocol */ /* Uninstall driver binding protocol */
if ( ( rc = efi_veto_uninstall ( veto ) ) != 0 ) if ( ( rc = efi_veto_uninstall ( driver, NULL, driver,
binding ) ) != 0 )
return rc; return rc;
/* Close any remaining opened handles */ /* Close any remaining opened handles */
if ( ( rc = efi_veto_close ( veto ) ) != 0 ) if ( ( rc = efi_veto_handles ( driver, NULL ) ) != 0 )
return rc; return rc;
DBGC ( target, "EFIVETO %s forcibly removed\n", DBGC ( driver, "EFIVETO %s forcibly removed driver\n",
efi_handle_name ( target ) ); efi_handle_name ( driver ) );
return 0; return 0;
} }
/** /**
* Veto an EFI driver * Veto an EFI driver handle
* *
* @v veto Driver veto * @v driver Driver handle
* @ret image Image handle, if still present after veto attempt
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_driver ( struct efi_veto *veto ) { static int efi_veto_driver ( EFI_HANDLE driver, EFI_HANDLE *image ) {
int rc; int rc;
/* Try gracefully unloading the driver */ /* Try gracefully unloading the underlying image */
if ( ( rc = efi_veto_unload ( veto ) ) == 0 ) if ( ( rc = efi_veto_unload ( driver, image ) ) == 0 )
return 0; return 0;
/* If that fails, use a hammer */ /* If that fails, use a hammer */
if ( ( rc = efi_veto_destroy ( veto ) ) == 0 ) if ( ( rc = efi_veto_destroy ( driver ) ) == 0 )
return 0; return 0;
DBGC ( driver, "EFIVETO %s could not veto driver: %s\n",
efi_handle_name ( driver ), strerror ( rc ) );
return rc;
}
/**
* Veto an EFI image handle
*
* @v image Image handle
* @ret rc Return status code
*/
static int efi_veto_image ( EFI_HANDLE image ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
EFI_LOADED_IMAGE_PROTOCOL *loaded;
void *interface;
} loaded;
EFI_STATUS efirc;
int rc;
/* Open loaded image protocol */
if ( ( efirc = bs->OpenProtocol (
image, &efi_loaded_image_protocol_guid,
&loaded.interface, efi_image_handle, image,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( image, "EFIVETO %s could not open loaded image "
"protocol: %s\n", efi_handle_name ( image ),
strerror ( rc ) );
goto err_loaded;
}
/* Close and uninstall any remaining handles */
if ( ( rc = efi_veto_handles ( image, loaded.loaded ) ) != 0 )
return rc;
DBGC ( image, "EFIVETO %s forcibly removed image\n",
efi_handle_name ( image ) );
bs->CloseProtocol ( image, &efi_loaded_image_protocol_guid,
efi_image_handle, image );
err_loaded:
return rc; return rc;
} }
/** /**
* Veto Ip4ConfigDxe driver on some platforms * Veto Ip4ConfigDxe driver on some platforms
* *
* @v binding Driver binding protocol
* @v loaded Loaded image protocol
* @v wtf Component name protocol, if present
* @v manufacturer Manufacturer name, if present * @v manufacturer Manufacturer name, if present
* @v name Driver name, if present * @v name Driver name, if present
* @ret vetoed Driver is to be vetoed * @ret vetoed Driver is to be vetoed
*/ */
static int static int efi_veto_ip4config ( const char *manufacturer,
efi_veto_ip4config ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused, const CHAR16 *name ) {
EFI_LOADED_IMAGE_PROTOCOL *loaded __unused,
EFI_COMPONENT_NAME_PROTOCOL *wtf __unused,
const char *manufacturer, const CHAR16 *name ) {
static const CHAR16 ip4cfg[] = L"IP4 CONFIG Network Service Driver"; static const CHAR16 ip4cfg[] = L"IP4 CONFIG Network Service Driver";
static const char *dell = "Dell Inc."; static const char *dell = "Dell Inc.";
static const char *itautec = "Itautec S.A."; static const char *itautec = "Itautec S.A.";
@@ -423,18 +498,11 @@ efi_veto_ip4config ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
/** /**
* Veto HP XhciDxe driver * Veto HP XhciDxe driver
* *
* @v binding Driver binding protocol
* @v loaded Loaded image protocol
* @v wtf Component name protocol, if present
* @v manufacturer Manufacturer name, if present * @v manufacturer Manufacturer name, if present
* @v name Driver name, if present * @v name Driver name, if present
* @ret vetoed Driver is to be vetoed * @ret vetoed Driver is to be vetoed
*/ */
static int static int efi_veto_hp_xhci ( const char *manufacturer, const CHAR16 *name ) {
efi_veto_hp_xhci ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
EFI_LOADED_IMAGE_PROTOCOL *loaded __unused,
EFI_COMPONENT_NAME_PROTOCOL *wtf __unused,
const char *manufacturer, const CHAR16 *name ) {
static const CHAR16 xhci[] = L"Usb Xhci Driver"; static const CHAR16 xhci[] = L"Usb Xhci Driver";
static const char *hp = "HP"; static const char *hp = "HP";
struct pci_driver *driver; struct pci_driver *driver;
@@ -465,17 +533,13 @@ efi_veto_hp_xhci ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
* Veto VMware UefiPxeBcDxe driver * Veto VMware UefiPxeBcDxe driver
* *
* @v binding Driver binding protocol * @v binding Driver binding protocol
* @v loaded Loaded image protocol
* @v wtf Component name protocol, if present * @v wtf Component name protocol, if present
* @v manufacturer Manufacturer name, if present * @v manufacturer Manufacturer name, if present
* @v name Driver name, if present * @v name Driver name, if present
* @ret vetoed Driver is to be vetoed * @ret vetoed Driver is to be vetoed
*/ */
static int static int efi_veto_vmware_uefipxebc ( const char *manufacturer,
efi_veto_vmware_uefipxebc ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused, const CHAR16 *name ) {
EFI_LOADED_IMAGE_PROTOCOL *loaded __unused,
EFI_COMPONENT_NAME_PROTOCOL *wtf __unused,
const char *manufacturer, const CHAR16 *name ) {
static const CHAR16 uefipxebc[] = L"UEFI PXE Base Code Driver"; static const CHAR16 uefipxebc[] = L"UEFI PXE Base Code Driver";
static const char *vmware = "VMware, Inc."; static const char *vmware = "VMware, Inc.";
@@ -495,18 +559,12 @@ efi_veto_vmware_uefipxebc ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
/** /**
* Veto VirtualBox E1kNetDxe driver * Veto VirtualBox E1kNetDxe driver
* *
* @v binding Driver binding protocol
* @v loaded Loaded image protocol
* @v wtf Component name protocol, if present
* @v manufacturer Manufacturer name, if present * @v manufacturer Manufacturer name, if present
* @v name Driver name, if present * @v name Driver name, if present
* @ret vetoed Driver is to be vetoed * @ret vetoed Driver is to be vetoed
*/ */
static int static int efi_veto_vbox_e1knet ( const char *manufacturer,
efi_veto_vbox_e1knet ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused, const CHAR16 *name ) {
EFI_LOADED_IMAGE_PROTOCOL *loaded __unused,
EFI_COMPONENT_NAME_PROTOCOL *wtf __unused,
const char *manufacturer, const CHAR16 *name ) {
static const CHAR16 e1knet[] = L"E1000 network interface card Driver"; static const CHAR16 e1knet[] = L"E1000 network interface card Driver";
static const char *vbox = "innotek GmbH"; static const char *vbox = "innotek GmbH";
@@ -524,7 +582,7 @@ efi_veto_vbox_e1knet ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
} }
/** Driver vetoes */ /** Driver vetoes */
static struct efi_veto_candidate efi_vetoes[] = { static struct efi_veto efi_vetoes[] = {
{ {
.name = "Ip4Config", .name = "Ip4Config",
.veto = efi_veto_ip4config, .veto = efi_veto_ip4config,
@@ -552,57 +610,21 @@ static struct efi_veto_candidate efi_vetoes[] = {
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer, static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
struct efi_veto *veto ) { struct efi_veto **veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
EFI_DRIVER_BINDING_PROTOCOL *binding;
void *interface;
} binding;
union {
EFI_LOADED_IMAGE_PROTOCOL *loaded;
void *interface;
} loaded;
union { union {
EFI_COMPONENT_NAME_PROTOCOL *wtf; EFI_COMPONENT_NAME_PROTOCOL *wtf;
void *interface; void *interface;
} wtf; } wtf;
CHAR16 *name; CHAR16 *name;
unsigned int i; unsigned int i;
EFI_HANDLE image;
EFI_STATUS efirc; EFI_STATUS efirc;
int rc;
DBGC2 ( &efi_vetoes, "EFIVETO checking %s\n", DBGC2 ( &efi_vetoes, "EFIVETO checking %s\n",
efi_handle_name ( driver ) ); efi_handle_name ( driver ) );
/* Mark as not vetoed */ /* Mark as not vetoed */
memset ( veto, 0, sizeof ( *veto ) ); *veto = NULL;
/* Open driver binding protocol */
if ( ( efirc = bs->OpenProtocol (
driver, &efi_driver_binding_protocol_guid,
&binding.interface, efi_image_handle, driver,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( driver, "EFIVETO %s could not open driver binding "
"protocol: %s\n", efi_handle_name ( driver ),
strerror ( rc ) );
goto err_binding;
}
image = binding.binding->ImageHandle;
/* Open loaded image protocol */
if ( ( efirc = bs->OpenProtocol (
image, &efi_loaded_image_protocol_guid,
&loaded.interface, efi_image_handle, image,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( driver, "EFIVETO %s could not open",
efi_handle_name ( driver ) );
DBGC ( driver, " %s loaded image protocol: %s\n",
efi_handle_name ( image ), strerror ( rc ) );
goto err_loaded;
}
/* Open component name protocol, if present*/ /* Open component name protocol, if present*/
if ( ( efirc = bs->OpenProtocol ( if ( ( efirc = bs->OpenProtocol (
@@ -626,33 +648,25 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
/* Check vetoes */ /* Check vetoes */
for ( i = 0 ; i < ( sizeof ( efi_vetoes ) / for ( i = 0 ; i < ( sizeof ( efi_vetoes ) /
sizeof ( efi_vetoes[0] ) ) ; i++ ) { sizeof ( efi_vetoes[0] ) ) ; i++ ) {
if ( efi_vetoes[i].veto ( binding.binding, loaded.loaded,
wtf.wtf, manufacturer, name ) ) {
DBGC ( driver, "EFIVETO %s is vetoed (%s)\n",
efi_handle_name ( driver ),
efi_vetoes[i].name );
veto->target = driver;
veto->image = image;
veto->loaded = loaded.loaded;
break;
}
}
/* Success */ /* Check if this veto applies */
rc = 0; if ( ! efi_vetoes[i].veto ( manufacturer, name ) )
continue;
DBGC ( driver, "EFIVETO %s is vetoed (%s)\n",
efi_handle_name ( driver ), efi_vetoes[i].name );
*veto = &efi_vetoes[i];
break;
}
/* Close protocols */ /* Close protocols */
if ( wtf.wtf ) { if ( wtf.wtf ) {
bs->CloseProtocol ( driver, &efi_component_name_protocol_guid, bs->CloseProtocol ( driver, &efi_component_name_protocol_guid,
efi_image_handle, driver ); efi_image_handle, driver );
} }
bs->CloseProtocol ( image, &efi_loaded_image_protocol_guid,
efi_image_handle, image ); return 0;
err_loaded:
bs->CloseProtocol ( driver, &efi_driver_binding_protocol_guid,
efi_image_handle, driver );
err_binding:
return rc;
} }
/** /**
@@ -661,9 +675,10 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
*/ */
void efi_veto ( void ) { void efi_veto ( void ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_veto veto; struct efi_veto *veto;
EFI_HANDLE *targets; EFI_HANDLE *targets;
EFI_HANDLE driver; EFI_HANDLE driver;
EFI_HANDLE image;
UINTN count; UINTN count;
unsigned int i; unsigned int i;
char *manufacturer; char *manufacturer;
@@ -685,9 +700,14 @@ void efi_veto ( void ) {
&manufacturer ); &manufacturer );
DBGC ( &efi_vetoes, "EFIVETO manufacturer is \"%s\"\n", manufacturer ); DBGC ( &efi_vetoes, "EFIVETO manufacturer is \"%s\"\n", manufacturer );
/* Unload any vetoed drivers */ /* Identify any vetoed drivers and veto the driver handles */
for ( i = 0 ; i < count ; i++ ) { for ( i = 0 ; i < count ; i++ ) {
/* Consume driver handle from target list */
driver = targets[ count - i - 1 ]; driver = targets[ count - i - 1 ];
targets[ count - i - 1 ] = NULL;
/* Check if this driver is vetoed */
if ( ( rc = efi_veto_find ( driver, manufacturer, if ( ( rc = efi_veto_find ( driver, manufacturer,
&veto ) ) != 0 ) { &veto ) ) != 0 ) {
DBGC ( driver, "EFIVETO %s could not determine " DBGC ( driver, "EFIVETO %s could not determine "
@@ -695,12 +715,28 @@ void efi_veto ( void ) {
efi_handle_name ( driver ), strerror ( rc ) ); efi_handle_name ( driver ), strerror ( rc ) );
continue; continue;
} }
if ( ! veto.target ) if ( ! veto )
continue;
/* Veto driver handle */
if ( ( rc = efi_veto_driver ( driver, &image ) ) != 0 )
continue;
/* Record image handle (if still present) as a target */
targets[ count - i - 1 ] = image;
}
/* Veto any remaining image handles */
for ( i = 0 ; i < count ; i++ ) {
/* Consume image handle from target list */
image = targets[ count - i - 1 ];
if ( ! image )
continue;
/* Veto image handle */
if ( ( rc = efi_veto_image ( image ) ) != 0 )
continue; continue;
if ( ( rc = efi_veto_driver ( &veto ) ) != 0 ) {
DBGC ( driver, "EFIVETO %s could not veto: %s\n",
efi_handle_name ( driver ), strerror ( rc ) );
}
} }
/* Free manufacturer name */ /* Free manufacturer name */