summaryrefslogtreecommitdiff
path: root/lib/efi_loader/efi_disk.c
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2020-01-10 12:36:01 +0100
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2020-12-10 09:15:33 +0100
commit264485131c59c1c8fa17fe742bbca65cef868d94 (patch)
tree10a493992781507bcd885b3cb8d747935f0fa93e /lib/efi_loader/efi_disk.c
parentf9ad240e65ac2f45d7b0acd770b5d79e50c3d92f (diff)
efi_loader: link partition to block device
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 <xypron.glpk@gmx.de>
Diffstat (limited to 'lib/efi_loader/efi_disk.c')
-rw-r--r--lib/efi_loader/efi_disk.c20
1 files changed, 20 insertions, 0 deletions
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;
}
/**