diff mbox series

[U-Boot,11/17] efi_loader: make efi_disk_create_partitions a global symbol

Message ID 20180111080708.18367-12-xypron.debian@gmx.de
State Superseded, archived
Delegated to: Alexander Graf
Headers show
Series efi_loader: enable EFI driver provided block device | expand

Commit Message

Heinrich Schuchardt Jan. 11, 2018, 8:07 a.m. UTC
From: Heinrich Schuchardt <xypron.glpk@gmx.de>

Up to now we have been using efi_disk_create_partitions() to create
partions for block device that existed before starting an EFI
application.

We need to to call it for for block devices created by EFI
applications at run time. The EFI application will define the
handle for the block device and install a device path protocol
on it. We have to use this device path as stem for the partition
device paths.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_loader.h      |  4 +++
 lib/efi_loader/efi_disk.c | 84 +++++++++++++++++++++++++++++++++--------------
 2 files changed, 64 insertions(+), 24 deletions(-)
diff mbox series

Patch

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 456763e83a..0ba7badb15 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -174,6 +174,10 @@  extern struct list_head efi_obj_list;
 int efi_console_register(void);
 /* Called by bootefi to make all disk storage accessible as EFI objects */
 int efi_disk_register(void);
+/* Create handles and protocols for the partions of a block device */
+int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
+			       const char *if_typename, int diskid,
+			       const char *pdevname);
 /* Called by bootefi to make GOP (graphical) interface available */
 int efi_gop_register(void);
 /* Called by bootefi to make the network interface available */
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index cccfc6dac5..92c3f45ca5 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -216,27 +216,31 @@  efi_fs_from_path(struct efi_device_path *full_path)
 }
 
 /*
- * Create a device for a disk
+ * Create a handle for a partition or disk
  *
- * @name	not used
+ * @parent	parent handle
+ * @dp_parent	parent device path
  * @if_typename interface name for block device
  * @desc	internal block device
  * @dev_index   device index for block device
  * @offset	offset into disk for simple partitions
+ * @return	disk object
  */
-static void efi_disk_add_dev(const char *name,
-			     const char *if_typename,
-			     struct blk_desc *desc,
-			     int dev_index,
-			     lbaint_t offset,
-			     unsigned int part)
+static struct efi_disk_obj *efi_disk_add_dev(
+				efi_handle_t parent,
+				struct efi_device_path *dp_parent,
+				const char *if_typename,
+				struct blk_desc *desc,
+				int dev_index,
+				lbaint_t offset,
+				unsigned int part)
 {
 	struct efi_disk_obj *diskobj;
 	efi_status_t ret;
 
 	/* Don't add empty devices */
 	if (!desc->lba)
-		return;
+		return NULL;
 
 	diskobj = calloc(1, sizeof(*diskobj));
 	if (!diskobj)
@@ -246,7 +250,14 @@  static void efi_disk_add_dev(const char *name,
 	efi_add_handle(&diskobj->parent);
 
 	/* Fill in object data */
-	diskobj->dp = efi_dp_from_part(desc, part);
+	if (part) {
+		struct efi_device_path *node = efi_dp_part_node(desc, part);
+
+		diskobj->dp = efi_dp_append_node(dp_parent, node);
+		efi_free_pool(node);
+	} else {
+		diskobj->dp = efi_dp_from_part(desc, part);
+	}
 	diskobj->part = part;
 	ret = efi_add_protocol(diskobj->parent.handle, &efi_block_io_guid,
 			       &diskobj->ops);
@@ -280,20 +291,38 @@  static void efi_disk_add_dev(const char *name,
 	if (part != 0)
 		diskobj->media.logical_partition = 1;
 	diskobj->ops.media = &diskobj->media;
-	return;
+	return diskobj;
 out_of_memory:
 	printf("ERROR: Out of memory\n");
+	return NULL;
 }
 
-static int efi_disk_create_partitions(struct blk_desc *desc,
-				      const char *if_typename,
-				      int diskid,
-				      const char *pdevname)
+/*
+ * Create handles and protocols for the partions of a block device
+ *
+ * @parent		handle of the parent disk
+ * @blk_desc		block device
+ * @if_typename		interface type
+ * @diskid		device number
+ * @pdevname		device name
+ * @return		number of partions created
+ */
+int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
+			       const char *if_typename, int diskid,
+			       const char *pdevname)
 {
 	int disks = 0;
 	char devname[32] = { 0 }; /* dp->str is u16[32] long */
 	disk_partition_t info;
 	int part;
+	struct efi_device_path *dp = NULL;
+	efi_status_t ret;
+	struct efi_handler *handler;
+
+	/* Get the device path of the parent */
+	ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
+	if (ret == EFI_SUCCESS)
+		dp = handler->protocol_interface;
 
 	/* Add devices for each partition */
 	for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
@@ -301,7 +330,7 @@  static int efi_disk_create_partitions(struct blk_desc *desc,
 			continue;
 		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
 			 part);
-		efi_disk_add_dev(devname, if_typename, desc, diskid,
+		efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
 				 info.start, part);
 		disks++;
 	}
@@ -322,6 +351,7 @@  static int efi_disk_create_partitions(struct blk_desc *desc,
  */
 int efi_disk_register(void)
 {
+	struct efi_disk_obj *disk;
 	int disks = 0;
 #ifdef CONFIG_BLK
 	struct udevice *dev;
@@ -335,14 +365,16 @@  int efi_disk_register(void)
 		printf("Scanning disk %s...\n", dev->name);
 
 		/* Add block device for the full device */
-		efi_disk_add_dev(dev->name, if_typename, desc,
-				 desc->devnum, 0, 0);
-
+		disk = efi_disk_add_dev(NULL, NULL, if_typename,
+					desc, desc->devnum, 0, 0);
+		if (!disk)
+			return -ENOMEM;
 		disks++;
 
 		/* Partitions show up as block devices in EFI */
-		disks += efi_disk_create_partitions(desc, if_typename,
-						    desc->devnum, dev->name);
+		disks += efi_disk_create_partitions(
+					disk->parent.handle, desc, if_typename,
+					desc->devnum, dev->name);
 	}
 #else
 	int i, if_type;
@@ -372,12 +404,16 @@  int efi_disk_register(void)
 				 if_typename, i);
 
 			/* Add block device for the full device */
-			efi_disk_add_dev(devname, if_typename, desc, i, 0, 0);
+			disk = efi_disk_add_dev(NULL, NULL, if_typename, desc,
+						i, 0, 0);
+			if (!disk)
+				return -ENOMEM;
 			disks++;
 
 			/* Partitions show up as block devices in EFI */
-			disks += efi_disk_create_partitions(desc, if_typename,
-							    i, devname);
+			disks += efi_disk_create_partitions(
+						disk->parent.handle, desc,
+						if_typename, i, devname);
 		}
 	}
 #endif