diff options
author | Michael Brown <mcb30@ipxe.org> | 2024-03-22 16:50:13 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2024-03-25 17:58:33 +0000 |
commit | da5188f3ea73900f1c6a4e44a8345b48320d396f (patch) | |
tree | d9adcce6a6b91145a2b34f91132d7bfe9d521d1b | |
parent | ca483a196c091c16ea0a426ce5f915b184a34412 (diff) | |
download | ipxe-da5188f3ea73900f1c6a4e44a8345b48320d396f.tar.gz |
[efi] Allow for drivers to be located via child handles
When using a service binding protocol, CreateChild() will create a new
protocol instance (and optionally a new handle). The caller will then
typically open this new protocol instance with BY_DRIVER attributes,
since the service binding mechanism has no equivalent of the driver
binding protocol's Stop() method, and there is therefore no other way
for the caller to be informed if the protocol instance is about to
become invalid (e.g. because the service driver wants to remove the
child).
The caller cannot ask CreateChild() to install the new protocol
instance on the original handle (i.e. the service binding handle),
since the whole point of the service binding protocol is to allow for
the existence of multiple children, and UEFI does not permit multiple
instances of the same protocol to be installed on a handle.
Our current drivers all open the original handle (as passed to our
driver binding's Start() method) with BY_DRIVER attributes, and so the
same handle will be passed to our Stop() method. This changes when
our driver must use a separate handle, as described above.
Add an optional "child handle" field to struct efi_device (on the
assumption that we will not have any drivers that need to create
multiple children), and generalise efidev_find() to match on either
the original handle or the child handle.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/include/ipxe/efi/efi_driver.h | 2 | ||||
-rw-r--r-- | src/interface/efi/efi_driver.c | 10 |
2 files changed, 10 insertions, 2 deletions
diff --git a/src/include/ipxe/efi/efi_driver.h b/src/include/ipxe/efi/efi_driver.h index 74ece90db..411e93642 100644 --- a/src/include/ipxe/efi/efi_driver.h +++ b/src/include/ipxe/efi/efi_driver.h @@ -19,6 +19,8 @@ struct efi_device { struct device dev; /** EFI device handle */ EFI_HANDLE device; + /** EFI child device handle (if present) */ + EFI_HANDLE child; /** EFI device path copy */ EFI_DEVICE_PATH_PROTOCOL *path; /** Driver for this device */ diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c index 8e537d535..8f8c9f3da 100644 --- a/src/interface/efi/efi_driver.c +++ b/src/interface/efi/efi_driver.c @@ -64,16 +64,22 @@ static int efi_driver_disconnecting; /** * Find EFI device * - * @v device EFI device handle + * @v device EFI device handle (or child handle) * @ret efidev EFI device, or NULL if not found */ static struct efi_device * efidev_find ( EFI_HANDLE device ) { struct efi_device *efidev; + /* Avoid false positive matches against NULL children */ + if ( ! device ) + return NULL; + /* Look for an existing EFI device */ list_for_each_entry ( efidev, &efi_devices, dev.siblings ) { - if ( efidev->device == device ) + if ( ( device == efidev->device ) || + ( device == efidev->child ) ) { return efidev; + } } return NULL; |