aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-06-23 15:03:30 +0100
committerMichael Brown <mcb30@ipxe.org>2023-06-23 16:51:10 +0100
commita029f4e13b54cfe87a04af7209a0d9744f3b7613 (patch)
tree5f615a8059e4009058179d9b6d11c35370ae7314
parentae435cb4cc78183814f867686d278885db2988f8 (diff)
downloadipxe-a029f4e13b54cfe87a04af7209a0d9744f3b7613.zip
ipxe-a029f4e13b54cfe87a04af7209a0d9744f3b7613.tar.gz
ipxe-a029f4e13b54cfe87a04af7209a0d9744f3b7613.tar.bz2
[efi] Veto the VirtualBox E1kNetDxe driver
The VirtualBox E1kNetDxe driver has a Stop() method that relies on being passed its own child device handle. Unfortunately, the same driver's Start() method never opens the parent device handle with BY_CHILD_CONTROLLER attributes on behalf of the newly installed child device handle, with the result that the UEFI device model is completely unaware of the nominal parent-child relationship. This omission can be observed via the UEFI shell "devtree" command, which will show the child SNP device handle as a standalone top-level device handle, with no relationship to its underlying parent PCI device handle. The upshot of this omission is that the VirtualBox E1kNetDxe driver's Stop() method is a pure no-op. Calling DisconnectController() on the PCI device handle will return successfully, but will not have actually disconnected anything. A subsequent attempt to open the handle on behalf of iPXE's native Intel driver will get stuck in an infinite loop inside OpenProtocol(), as the firmware repeatedly calls DisconnectController() in an attempt to disconnect the E1kNetDxe driver from the PCI device handle. Work around this problem by adding the buggy VirtualBox E1kNetDxe driver to the veto list. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/interface/efi/efi_veto.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/interface/efi/efi_veto.c b/src/interface/efi/efi_veto.c
index a3b60d6..40dce9d 100644
--- a/src/interface/efi/efi_veto.c
+++ b/src/interface/efi/efi_veto.c
@@ -494,6 +494,37 @@ efi_veto_vmware_uefipxebc ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
return 1;
}
+/**
+ * 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 name Driver name, if present
+ * @ret vetoed Driver is to be vetoed
+ */
+static int
+efi_veto_vbox_e1knet ( 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 e1knet[] = L"E1000 network interface card Driver";
+ static const char *vbox = "innotek GmbH";
+
+ /* Check manufacturer and driver name */
+ if ( ! manufacturer )
+ return 0;
+ if ( ! name )
+ return 0;
+ if ( strcmp ( manufacturer, vbox ) != 0 )
+ return 0;
+ if ( memcmp ( name, e1knet, sizeof ( e1knet ) ) != 0 )
+ return 0;
+
+ return 1;
+}
+
/** Driver vetoes */
static struct efi_veto_candidate efi_vetoes[] = {
{
@@ -508,6 +539,10 @@ static struct efi_veto_candidate efi_vetoes[] = {
.name = "VMware UefiPxeBc",
.veto = efi_veto_vmware_uefipxebc,
},
+ {
+ .name = "VirtualBox E1kNetDxe",
+ .veto = efi_veto_vbox_e1knet,
+ },
};
/**