We provide a UEFI driver for block devices. When ConnectController() is
called for a handle with the EFI_BLOCK_IO_PROTOCOL this driver creates the
partitions. When DisconnectController() is called the handles for the
partitions have to be deleted. This requires that the child controllers
(partitions) open the EFI_BLOCK_IO_PROTOCOL of the controller (block IO
device) with attribute EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.

Signed-off-by: Heinrich Schuchardt <[email protected]>
---
 lib/efi_loader/efi_disk.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 7bd1ccec45..496ef29dd8 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -376,6 +376,23 @@ static efi_status_t efi_disk_add_dev(
        /* Fill in object data */
        if (part) {
                struct efi_device_path *node = efi_dp_part_node(desc, part);
+               struct efi_handler *handler;
+               void *protocol_interface;
+
+               /* Parent must expose EFI_BLOCK_IO_PROTOCOL */
+               ret = efi_search_protocol(parent, &efi_block_io_guid, &handler);
+               if (ret != EFI_SUCCESS)
+                       goto error;
+
+               /*
+                * Link the partition (child controller) to the block device
+                * (controller).
+                */
+               ret = efi_protocol_open(handler, &protocol_interface, NULL,
+                                       &diskobj->header,
+                                       EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+               if (ret != EFI_SUCCESS)
+                               goto error;

                diskobj->dp = efi_dp_append_node(dp_parent, node);
                efi_free_pool(node);
@@ -453,6 +470,9 @@ static efi_status_t efi_disk_add_dev(
                }
        }
        return EFI_SUCCESS;
+error:
+       efi_delete_handle(&diskobj->header);
+       return ret;
 }

 /**
--
2.29.2

Reply via email to