On 10/04/15 20:53, Laszlo Ersek wrote:
In efi_init() [src/interface/efi/efi_init.c], iPXE registers the
efi_shutdown_hook() function as a callback for the
EVT_SIGNAL_EXIT_BOOT_SERVICES event. This event is emitted under UEFI when
the OS loader (including the Linux EFI stub) calls ExitBootServices().

Currently, that event results in the following call chain:

efi_shutdown_hook()                         [src/interface/efi/efi_init.c]
   shutdown_boot()                           [src/include/ipxe/init.h]
     shutdown(1)                             [src/core/init.c]
       /* Call registered shutdown functions (in reverse order) */
       forall startup_fn:
         startup_fn->shutdown(1)

This infrastructure is fine. However, the virtio-net driver does not
register such a shutdown function at the moment.

Consequently, virtio-net devices remain configured (active) after
ExitBootServices().

Individual iPXE drivers are not expected to have to register shutdown functions. All drivers should have their remove() method called for all open devices already. Registering custom shutdown functions is intended for code which needs to do something unusual at shutdown time (e.g. the EHCI/xHCI USB bus drivers, which need to decide whether or not to attempt to hand control back to the BIOS).

Looking at the code, I think there might be a missing piece:

- Under our (very) old EFI driver model, we enumerated the PCI bus directly and basically ignored EFI's concept of devices. The efi_shutdown_hook() would therefore result in devices being closed via remove_devices() in core/device.c. This no longer happens, because we now attach to devices only as requested by EFI.

- When built as an EFI application, the efi_root_device in efiprefix.c means that the call to remove_devices() will end up calling efi_remove() and hence efi_driver_disconnect_all().

- From a quick look, there seems to be no equivalent functionality for when built as an EFI driver.

I don't have time to look at it properly right now, but could you try the attached (totally untested) patch?

Thanks,

Michael
diff --git a/src/arch/x86/prefix/efidrvprefix.c b/src/arch/x86/prefix/efidrvprefix.c
index 3daefd0..4fbb19f 100644
--- a/src/arch/x86/prefix/efidrvprefix.c
+++ b/src/arch/x86/prefix/efidrvprefix.c
@@ -21,7 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <stdlib.h>
 #include <ipxe/init.h>
+#include <ipxe/device.h>
 #include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_driver.h>
 
 /**
  * EFI entry point
@@ -44,3 +46,36 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
 
 	return 0;
 }
+
+/**
+ * Probe EFI root bus
+ *
+ * @v rootdev		EFI root device
+ */
+static int efi_probe ( struct root_device *rootdev __unused ) {
+
+	/* Do nothing */
+	return 0;
+}
+
+/**
+ * Remove EFI root bus
+ *
+ * @v rootdev		EFI root device
+ */
+static void efi_remove ( struct root_device *rootdev __unused ) {
+
+	efi_driver_disconnect_all();
+}
+
+/** EFI root device driver */
+static struct root_driver efi_root_driver = {
+	.probe = efi_probe,
+	.remove = efi_remove,
+};
+
+/** EFI root device */
+struct root_device efi_root_device __root_device = {
+	.dev = { .name = "EFI" },
+	.driver = &efi_root_driver,
+};
_______________________________________________
ipxe-devel mailing list
[email protected]
https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel

Reply via email to