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>
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 7bd1cce..496ef29 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -376,6 +376,23 @@
 	/* 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 @@
 		}
 	}
 	return EFI_SUCCESS;
+error:
+	efi_delete_handle(&diskobj->header);
+	return ret;
 }
 
 /**