All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/4] efi_loader: fix disk objects + device-paths
@ 2017-07-21 18:43 Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 1/4] efi: add some more device path structures Rob Clark
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Rob Clark @ 2017-07-21 18:43 UTC (permalink / raw)
  To: u-boot

Currently u-boot completely gets block-io objects (and their associated
device-paths) wrong, which prevents grub2 from figuring out the boot
device+partition, which prevents it from automatically finding it's
grub.cfg.

Currently efi_loader creates a block-io object per disk, for example on
a board with 3 partitions on an sd-card and 4 partitions on a usb disk:

  /File(sdhci at 07864000.blk)/EndEntire
  /File(usb_mass_storage.lun0)/EndEntire

at least grub manages to match up the loaded_image device-path, but it
cannot figure out which partition it was on.  So you end up with
prefix=(hd1)/EFI/fedora instead of prefix=(hd1,msdos1)/EFI/fedora.
With this patchset, you end up with:

  /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,0000000000000000,1,0)/EndEntire

(Note that "UnknownMessaging(1d)" is actually the MMC node in the device-
path, but grub wasn't updated to print out some of the newer device-path
sub-types.)

Since we use DM to generate the device-paths from u-boot's device
hierarchy, legacy devices will still be broken.  I kept them working
as they did previously and tried to minimize the ifdeffery, but things
will get much cleaner when legacy support is removed.

Peter Jones (1):
  efi: add some more device path structures

Rob Clark (3):
  efi_loader: add udevice to EFI device-path mapping
  efi_loader: make disk objects for partitions
  efi_loader: use efi_devpath to get correct boot device-path

 cmd/bootefi.c                |  31 ++++++--
 include/efi_api.h            |  49 +++++++++++-
 include/efi_loader.h         |   9 +++
 lib/efi_loader/Makefile      |   1 +
 lib/efi_loader/efi_devpath.c | 175 +++++++++++++++++++++++++++++++++++++++++++
 lib/efi_loader/efi_disk.c    |  73 +++++++++++++-----
 6 files changed, 311 insertions(+), 27 deletions(-)
 create mode 100644 lib/efi_loader/efi_devpath.c

-- 
2.13.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/4] efi: add some more device path structures
  2017-07-21 18:43 [U-Boot] [PATCH 0/4] efi_loader: fix disk objects + device-paths Rob Clark
@ 2017-07-21 18:43 ` Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping Rob Clark
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Rob Clark @ 2017-07-21 18:43 UTC (permalink / raw)
  To: u-boot

From: Peter Jones <pjones@redhat.com>

Signed-off-by: Peter Jones <pjones@redhat.com>
---
 include/efi_api.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index f071b36b53..e1b3f11c6d 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -275,22 +275,67 @@ struct efi_mac_addr {
 	u8 addr[32];
 };
 
+#define DEVICE_PATH_TYPE_ACPI_DEVICE		0x02
+#define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE	0x01
+
+#define EFI_PNP_ID(ID)				(u32)(((ID) << 16) | 0x41D0)
+#define EISA_PNP_ID(ID)				EFI_PNP_ID(ID)
+
+struct efi_device_path_acpi_path {
+	struct efi_device_path dp;
+	u32 hid;
+	u32 uid;
+} __packed;
+
 #define DEVICE_PATH_TYPE_MESSAGING_DEVICE	0x03
+#  define DEVICE_PATH_SUB_TYPE_MSG_USB		0x05
 #  define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR	0x0b
+#  define DEVICE_PATH_SUB_TYPE_MSG_SD		0x1a
+#  define DEVICE_PATH_SUB_TYPE_MSG_MMC		0x1d
+
+struct efi_device_path_usb {
+	struct efi_device_path dp;
+	u8 parent_port_number;
+	u8 usb_interface;
+} __packed;
 
 struct efi_device_path_mac_addr {
 	struct efi_device_path dp;
 	struct efi_mac_addr mac;
 	u8 if_type;
-};
+} __packed;
+
+struct efi_device_path_sd_mmc_path {
+	struct efi_device_path dp;
+	u8 slot_number;
+} __packed;
 
 #define DEVICE_PATH_TYPE_MEDIA_DEVICE		0x04
+#  define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH	0x01
+#  define DEVICE_PATH_SUB_TYPE_CDROM_PATH	0x02
 #  define DEVICE_PATH_SUB_TYPE_FILE_PATH	0x04
 
+struct efi_device_path_hard_drive_path {
+	struct efi_device_path dp;
+	u32 partition_number;
+	u64 partition_start;
+	u64 partition_end;
+	u8 partition_signature[16];
+	u8 partmap_type;
+	u8 signature_type;
+} __packed;
+
+struct efi_device_path_cdrom_path {
+	struct efi_device_path dp;
+	u32 boot_entry;
+	u64 partition_start;
+	u64 partition_end;
+} __packed;
+
 struct efi_device_path_file_path {
 	struct efi_device_path dp;
 	u16 str[32];
-};
+} __packed;
 
 #define BLOCK_IO_GUID \
 	EFI_GUID(0x964e5b21, 0x6459, 0x11d2, \
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping
  2017-07-21 18:43 [U-Boot] [PATCH 0/4] efi_loader: fix disk objects + device-paths Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 1/4] efi: add some more device path structures Rob Clark
@ 2017-07-21 18:43 ` Rob Clark
  2017-07-25 13:57   ` Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 3/4] efi_loader: make disk objects for partitions Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 4/4] efi_loader: use efi_devpath to get correct boot device-path Rob Clark
  3 siblings, 1 reply; 10+ messages in thread
From: Rob Clark @ 2017-07-21 18:43 UTC (permalink / raw)
  To: u-boot

Initially just supports "disk" type devices, but a real UEFI
implementation would expose input/output/display/etc with device-paths
as well, so we may eventually want to expand this for other uses.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 include/efi_loader.h         |   9 +++
 lib/efi_loader/Makefile      |   1 +
 lib/efi_loader/efi_devpath.c | 175 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+)
 create mode 100644 lib/efi_loader/efi_devpath.c

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 812ec10e37..97d5e3d13d 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -145,6 +145,15 @@ extern void *efi_bounce_buffer;
 #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024)
 #endif
 
+/*
+ * u-boot to EFI device mapping:
+ *
+ * TODO extend this for GOP and various other input/output
+ * devices which should also have an EFI devicepath?
+ */
+struct efi_device_path *efi_dp_from_dev(struct udevice *dev);
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
+
 /* Convert strings from normal C strings to uEFI strings */
 static inline void ascii2unicode(u16 *unicode, const char *ascii)
 {
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 9c67367df4..e191a3280b 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_DM_VIDEO) += efi_gop.o
 obj-$(CONFIG_PARTITIONS) += efi_disk.o
 obj-$(CONFIG_NET) += efi_net.o
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
+obj-$(CONFIG_DM) += efi_devpath.o
diff --git a/lib/efi_loader/efi_devpath.c b/lib/efi_loader/efi_devpath.c
new file mode 100644
index 0000000000..16b8edf899
--- /dev/null
+++ b/lib/efi_loader/efi_devpath.c
@@ -0,0 +1,175 @@
+/*
+ * EFI device path from u-boot device-model mapping
+ *
+ * (C) Copyright 2017 Rob Clark
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <usb.h>
+#include <mmc.h>
+#include <efi_loader.h>
+#include <inttypes.h>
+#include <part.h>
+#include <malloc.h>
+
+/* template END node: */
+const static struct efi_device_path END = {
+	.type     = DEVICE_PATH_TYPE_END,
+	.sub_type = DEVICE_PATH_SUB_TYPE_END,
+	.length   = sizeof(END),
+};
+
+/* template ROOT node, a fictional ACPI PNP device: */
+const static struct efi_device_path_acpi_path ROOT = {
+	.dp = {
+		.type     = DEVICE_PATH_TYPE_ACPI_DEVICE,
+		.sub_type = DEVICE_PATH_SUB_TYPE_ACPI_DEVICE,
+		.length   = sizeof(ROOT),
+	},
+	.hid = EISA_PNP_ID(0x1337),
+	.uid = 0,
+};
+
+
+/* size of device-path not including END node for device and all parents
+ * up to the root device.
+ */
+static unsigned dp_size(struct udevice *dev)
+{
+	if (!dev || !dev->driver)
+		return sizeof(ROOT);
+
+	switch (dev->driver->id) {
+	case UCLASS_ROOT:
+	case UCLASS_SIMPLE_BUS:
+		/* stop traversing parents at this point: */
+		return sizeof(ROOT);
+	case UCLASS_MMC:
+		return dp_size(dev->parent) + sizeof(struct efi_device_path_sd_mmc_path);
+	case UCLASS_MASS_STORAGE:
+	case UCLASS_USB_HUB:
+		return dp_size(dev->parent) + sizeof(struct efi_device_path_usb);
+	default:
+		/* just skip over unknown classes: */
+		return dp_size(dev->parent);
+	}
+}
+
+static void *dp_fill(void *buf, struct udevice *dev)
+{
+	if (!dev || !dev->driver)
+		return buf;
+
+	switch (dev->driver->id) {
+	case UCLASS_ROOT:
+	case UCLASS_SIMPLE_BUS: {
+		/* stop traversing parents at this point: */
+		struct efi_device_path_acpi_path *adp = buf;
+		*adp = ROOT;
+		return &adp[1];
+	}
+	case UCLASS_MMC: {
+		struct efi_device_path_sd_mmc_path *sddp =
+			dp_fill(buf, dev->parent);
+		struct mmc *mmc = mmc_get_mmc_dev(dev);
+		struct blk_desc *desc = mmc_get_blk_desc(mmc);
+
+		sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+		sddp->dp.sub_type = (desc->if_type == IF_TYPE_MMC) ?
+			DEVICE_PATH_SUB_TYPE_MSG_MMC :
+			DEVICE_PATH_SUB_TYPE_MSG_SD;
+		sddp->dp.length   = sizeof(*sddp);
+		sddp->slot_number = 0;  // XXX ???
+
+		return &sddp[1];
+	}
+	case UCLASS_MASS_STORAGE:
+	case UCLASS_USB_HUB: {
+		struct efi_device_path_usb *udp =
+			dp_fill(buf, dev->parent);
+
+		udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+		udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
+		udp->dp.length   = sizeof(*udp);
+		udp->parent_port_number = 0; // XXX ???
+		udp->usb_interface = 0; // XXX ???
+
+		return &udp[1];
+	}
+	default:
+		debug("unhandled device class: %s (%u)\n",
+			dev->name, dev->driver->id);
+		return dp_fill(buf, dev->parent);
+	}
+}
+
+/* Construct a device-path from a device: */
+struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
+{
+	void *buf, *start;
+
+	start = buf = calloc(1, dp_size(dev) + sizeof(END));
+	buf = dp_fill(buf, dev);
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
+
+/* Construct a device-path from a partition on a blk device: */
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
+{
+	disk_partition_t info;
+	unsigned dpsize;
+	void *buf, *start;
+
+	dpsize = dp_size(desc->bdev->parent) + sizeof(END);
+
+	if (desc->part_type == PART_TYPE_ISO) {
+		dpsize += sizeof(struct efi_device_path_cdrom_path);
+	} else {
+		dpsize += sizeof(struct efi_device_path_hard_drive_path);
+	}
+
+	start = buf = calloc(1, dpsize);
+
+	buf = dp_fill(buf, desc->bdev->parent);
+
+	part_get_info(desc, part, &info);
+
+	if (desc->part_type == PART_TYPE_ISO) {
+		struct efi_device_path_cdrom_path *cddp = buf;
+
+		cddp->boot_entry = part - 1;
+		cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+		cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
+		cddp->dp.length = sizeof (*cddp);
+		cddp->partition_start = info.start;
+		cddp->partition_end = info.size;
+
+		buf = &cddp[1];
+	} else {
+		struct efi_device_path_hard_drive_path *hddp = buf;
+
+		hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+		hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
+		hddp->dp.length = sizeof (*hddp);
+		hddp->partition_number = part - 1;
+		hddp->partition_start = info.start;
+		hddp->partition_end = info.size;
+		if (desc->part_type == PART_TYPE_EFI)
+			hddp->partmap_type = 2;
+		else
+			hddp->partmap_type = 1;
+		hddp->signature_type = 0;
+
+		buf = &hddp[1];
+	}
+
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 3/4] efi_loader: make disk objects for partitions
  2017-07-21 18:43 [U-Boot] [PATCH 0/4] efi_loader: fix disk objects + device-paths Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 1/4] efi: add some more device path structures Rob Clark
  2017-07-21 18:43 ` [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping Rob Clark
@ 2017-07-21 18:43 ` Rob Clark
  2017-07-23 10:25   ` [U-Boot] [U-Boot, " Heinrich Schuchardt
  2017-07-21 18:43 ` [U-Boot] [PATCH 4/4] efi_loader: use efi_devpath to get correct boot device-path Rob Clark
  3 siblings, 1 reply; 10+ messages in thread
From: Rob Clark @ 2017-07-21 18:43 UTC (permalink / raw)
  To: u-boot

Normally a EFI application, like grub2, is going to expect to see
block-io devices for both the actual disk and for each partition
(with the disk object being parent of the partition objects).

Now instead of seeing devices like:

  /File(sdhci at 07864000.blk)/EndEntire
  /File(usb_mass_storage.lun0)/EndEntire

You see:

  /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,0000000000000000,1,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,0000000000000000,1,0)/EndEntire

This is on a board with single USB disk and single sd-card.  The
UnknownMessaging(1d) node in the device-path is the MMC device,
but grub_efi_print_device_path() hasn't been updated yet for some
of the newer device-path sub-types.

This patch is somewhat based on a patch originally from Peter Jones,
but re-worked to use efi_devpath, so it doesn't much resemble the
original.

This depends on efi_devpath, which depends on CONFIG_DM, so legacy
devices will still get the old broken behavior.

There are a couple TODOs:
 1) how to find slot # for mmc device
 2) how to find parent port # and interface # for usb device

Also I don't seem to manage to get u-boot to recognize my usb-eth
dongle (config issue?) so I haven't been able to test the net-boot
path.. so it likely needs some work.

Cc: Peter Jones <pjones@redhat.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 lib/efi_loader/efi_disk.c | 73 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 53 insertions(+), 20 deletions(-)

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 09697936b5..44f72c93e2 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -28,7 +28,7 @@ struct efi_disk_obj {
 	/* EFI Interface Media descriptor struct, referenced by ops */
 	struct efi_block_io_media media;
 	/* EFI device path to this block device */
-	struct efi_device_path_file_path *dp;
+	struct efi_device_path *dp;
 	/* Offset into disk for simple partitions */
 	lbaint_t offset;
 	/* Internal block device */
@@ -193,21 +193,47 @@ static const struct efi_block_io block_io_disk_template = {
 	.flush_blocks = &efi_disk_flush_blocks,
 };
 
+static struct efi_device_path *blk2dp(struct blk_desc *desc,
+		const char *name, unsigned part)
+{
+#ifdef CONFIG_DM
+	/* part==0 is the case for parent block device representing
+	 * entire disk, and part>=1 is for child per-partition
+	 * MEDIA_DEVICE objects:
+	 */
+	if (part == 0)
+		return efi_dp_from_dev(desc->bdev->parent);
+	return efi_dp_from_part(desc, part);
+#else
+	struct efi_device_path_file_path *dp = calloc(2, sizeof(*dp));
+
+	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
+	dp[0].dp.length = sizeof(*dp);
+	ascii2unicode(dp[0].str, name);
+
+	dp[1].dp.type = DEVICE_PATH_TYPE_END;
+	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
+	dp[1].dp.length = sizeof(*dp);
+
+	return dp;
+#endif
+}
+
 static void efi_disk_add_dev(const char *name,
 			     const char *if_typename,
-			     const struct blk_desc *desc,
+			     struct blk_desc *desc,
 			     int dev_index,
-			     lbaint_t offset)
+			     lbaint_t offset,
+			     unsigned part)
 {
 	struct efi_disk_obj *diskobj;
-	struct efi_device_path_file_path *dp;
-	int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
 
 	/* Don't add empty devices */
 	if (!desc->lba)
 		return;
 
-	diskobj = calloc(1, objlen);
+	diskobj = calloc(1, sizeof(*diskobj));
 
 	/* Fill in object data */
 	diskobj->parent.protocols[0].guid = &efi_block_io_guid;
@@ -228,18 +254,7 @@ static void efi_disk_add_dev(const char *name,
 	diskobj->media.io_align = desc->blksz;
 	diskobj->media.last_block = desc->lba - offset;
 	diskobj->ops.media = &diskobj->media;
-
-	/* Fill in device path */
-	dp = (void*)&diskobj[1];
-	diskobj->dp = dp;
-	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
-	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
-	dp[0].dp.length = sizeof(*dp);
-	ascii2unicode(dp[0].str, name);
-
-	dp[1].dp.type = DEVICE_PATH_TYPE_END;
-	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
-	dp[1].dp.length = sizeof(*dp);
+	diskobj->dp = blk2dp(desc, name, part);
 
 	/* Hook up to the device list */
 	list_add_tail(&diskobj->parent.link, &efi_obj_list);
@@ -259,11 +274,16 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
 	if (desc->part_type != PART_TYPE_ISO)
 		return 0;
 
+#ifdef CONFIG_DM
+	/* add block device: */
+	efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
+#endif
+	/* ... and devices for each partition: */
 	while (!part_get_info(desc, part, &info)) {
 		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
 			 part);
 		efi_disk_add_dev(devname, if_typename, desc, diskid,
-				 info.start);
+				 info.start, part);
 		part++;
 		disks++;
 	}
@@ -290,9 +310,22 @@ int efi_disk_register(void)
 	     uclass_next_device(&dev)) {
 		struct blk_desc *desc = dev_get_uclass_platdata(dev);
 		const char *if_typename = dev->driver->name;
+		disk_partition_t info;
+		int part = 1;
 
 		printf("Scanning disk %s...\n", dev->name);
-		efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
+
+#ifdef CONFIG_DM
+		/* add block device: */
+		efi_disk_add_dev(dev->name, if_typename, desc,
+				desc->devnum, 0, 0);
+#endif
+		/* ... and devices for each partition: */
+		while (!part_get_info(desc, part, &info)) {
+			efi_disk_add_dev(dev->name, if_typename, desc,
+					desc->devnum, 0, part);
+			part++;
+		}
 		disks++;
 
 		/*
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 4/4] efi_loader: use efi_devpath to get correct boot device-path
  2017-07-21 18:43 [U-Boot] [PATCH 0/4] efi_loader: fix disk objects + device-paths Rob Clark
                   ` (2 preceding siblings ...)
  2017-07-21 18:43 ` [U-Boot] [PATCH 3/4] efi_loader: make disk objects for partitions Rob Clark
@ 2017-07-21 18:43 ` Rob Clark
  3 siblings, 0 replies; 10+ messages in thread
From: Rob Clark @ 2017-07-21 18:43 UTC (permalink / raw)
  To: u-boot

This way grub can properly match up the loaded_image device-path to a
partition device object, so it can locate it's grub.cfg.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 cmd/bootefi.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 5030b7bd86..ea0d5dbc79 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -41,6 +41,11 @@ static struct efi_device_path_file_path bootefi_image_path[] = {
 	}
 };
 
+/* if we have CONFIG_DM we construct a proper device-path from the
+ * boot device, otherwise fallback to using bootefi_device_path.
+ */
+static struct efi_device_path *real_bootefi_device_path;
+
 static struct efi_device_path_file_path bootefi_device_path[] = {
 	{
 		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
@@ -58,13 +63,12 @@ static efi_status_t EFIAPI bootefi_open_dp(void *handle, efi_guid_t *protocol,
 			void **protocol_interface, void *agent_handle,
 			void *controller_handle, uint32_t attributes)
 {
-	*protocol_interface = bootefi_device_path;
+	*protocol_interface = real_bootefi_device_path;
 	return EFI_SUCCESS;
 }
 
 /* The EFI loaded_image interface for the image executed via "bootefi" */
 static struct efi_loaded_image loaded_image_info = {
-	.device_handle = bootefi_device_path,
 	.file_path = bootefi_image_path,
 };
 
@@ -93,7 +97,6 @@ static struct efi_object loaded_image_info_obj = {
 
 /* The EFI object struct for the device the "bootefi" image was loaded from */
 static struct efi_object bootefi_device_obj = {
-	.handle = bootefi_device_path,
 	.protocols = {
 		{
 			/* When asking for the device path interface, return
@@ -239,8 +242,6 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
 
 	if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
 		loaded_image_info.device_handle = nethandle;
-	else
-		loaded_image_info.device_handle = bootefi_device_path;
 #endif
 #ifdef CONFIG_GENERATE_SMBIOS_TABLE
 	efi_smbios_register();
@@ -339,6 +340,18 @@ U_BOOT_CMD(
 	bootefi_help_text
 );
 
+#ifdef CONFIG_DM
+static int parse_partnum(const char *devnr)
+{
+	const char *str = strchr(devnr, ':');
+	if (str) {
+		str++;
+		return simple_strtoul(str, NULL, 16);
+	}
+	return 0;
+}
+#endif
+
 void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 {
 	__maybe_unused struct blk_desc *desc;
@@ -376,9 +389,14 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 	if (colon)
 		*colon = '\0';
 
+#ifdef CONFIG_DM
+	real_bootefi_device_path = efi_dp_from_part(desc, parse_partnum(devnr));
+#else
 	/* Patch bootefi_device_path to the target device */
+	real_bootefi_device_path = bootefi_device_path;
 	memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str));
 	ascii2unicode(bootefi_device_path[0].str, devname);
+#endif
 
 	/* Patch bootefi_image_path to the target file path */
 	memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
@@ -389,4 +407,7 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 		snprintf(devname, sizeof(devname), "%s", path);
 	}
 	ascii2unicode(bootefi_image_path[0].str, devname);
+
+	loaded_image_info.device_handle = real_bootefi_device_path;
+	bootefi_device_obj.handle = real_bootefi_device_path;
 }
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [U-Boot, 3/4] efi_loader: make disk objects for partitions
  2017-07-21 18:43 ` [U-Boot] [PATCH 3/4] efi_loader: make disk objects for partitions Rob Clark
@ 2017-07-23 10:25   ` Heinrich Schuchardt
  2017-07-23 19:48     ` Rob Clark
  0 siblings, 1 reply; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-23 10:25 UTC (permalink / raw)
  To: u-boot

On 07/21/2017 08:43 PM, Rob Clark wrote:
> Normally a EFI application, like grub2, is going to expect to see

%s/a/an/

> block-io devices for both the actual disk and for each partition
> (with the disk object being parent of the partition objects).
> 
> Now instead of seeing devices like:
> 
>   /File(sdhci at 07864000.blk)/EndEntire
>   /File(usb_mass_storage.lun0)/EndEntire
> 
> You see:
> 
>   /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
>   /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,0000000000000000,1,0)/EndEntire
>   /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,0000000000000000,1,0)/EndEntire
>   /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,0000000000000000,1,0)/EndEntire
>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,0000000000000000,1,0)/EndEntire
>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,0000000000000000,1,0)/EndEntire
>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,0000000000000000,1,0)/EndEntire
>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,0000000000000000,1,0)/EndEntire
> 
> This is on a board with single USB disk and single sd-card.  The
> UnknownMessaging(1d) node in the device-path is the MMC device,
> but grub_efi_print_device_path() hasn't been updated yet for some
> of the newer device-path sub-types.
> 
> This patch is somewhat based on a patch originally from Peter Jones,
> but re-worked to use efi_devpath, so it doesn't much resemble the
> original.
> 
> This depends on efi_devpath, which depends on CONFIG_DM, so legacy
> devices will still get the old broken behavior.
> 
> There are a couple TODOs:
>  1) how to find slot # for mmc device
>  2) how to find parent port # and interface # for usb device
> 
> Also I don't seem to manage to get u-boot to recognize my usb-eth
> dongle (config issue?) so I haven't been able to test the net-boot
> path.. so it likely needs some work.
> 
> Cc: Peter Jones <pjones@redhat.com>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
>  lib/efi_loader/efi_disk.c | 73 ++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 53 insertions(+), 20 deletions(-)
> 
> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
> index 09697936b5..44f72c93e2 100644
> --- a/lib/efi_loader/efi_disk.c
> +++ b/lib/efi_loader/efi_disk.c
> @@ -28,7 +28,7 @@ struct efi_disk_obj {
>  	/* EFI Interface Media descriptor struct, referenced by ops */
>  	struct efi_block_io_media media;
>  	/* EFI device path to this block device */
> -	struct efi_device_path_file_path *dp;
> +	struct efi_device_path *dp;
>  	/* Offset into disk for simple partitions */
>  	lbaint_t offset;
>  	/* Internal block device */
> @@ -193,21 +193,47 @@ static const struct efi_block_io block_io_disk_template = {
>  	.flush_blocks = &efi_disk_flush_blocks,
>  };
>  
> +static struct efi_device_path *blk2dp(struct blk_desc *desc,
> +		const char *name, unsigned part)
> +{
> +#ifdef CONFIG_DM
> +	/* part==0 is the case for parent block device representing
> +	 * entire disk, and part>=1 is for child per-partition
> +	 * MEDIA_DEVICE objects:
> +	 */
> +	if (part == 0)
> +		return efi_dp_from_dev(desc->bdev->parent);
> +	return efi_dp_from_part(desc, part);
> +#else
> +	struct efi_device_path_file_path *dp = calloc(2, sizeof(*dp));
> +
> +	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
> +	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
> +	dp[0].dp.length = sizeof(*dp);
> +	ascii2unicode(dp[0].str, name);
> +
> +	dp[1].dp.type = DEVICE_PATH_TYPE_END;
> +	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
> +	dp[1].dp.length = sizeof(*dp);
> +
> +	return dp;
> +#endif
> +}
> +
>  static void efi_disk_add_dev(const char *name,
>  			     const char *if_typename,
> -			     const struct blk_desc *desc,
> +			     struct blk_desc *desc,
>  			     int dev_index,
> -			     lbaint_t offset)
> +			     lbaint_t offset,
> +			     unsigned part)
>  {
>  	struct efi_disk_obj *diskobj;
> -	struct efi_device_path_file_path *dp;
> -	int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
>  
>  	/* Don't add empty devices */
>  	if (!desc->lba)
>  		return;
>  
> -	diskobj = calloc(1, objlen);
> +	diskobj = calloc(1, sizeof(*diskobj));
>  
>  	/* Fill in object data */
>  	diskobj->parent.protocols[0].guid = &efi_block_io_guid;

I am unable to apply this patch to the efi-next branch of
git://github.com/agraf/u-boot.git

Applying: efi_loader: make disk objects for partitions
error: patch failed: lib/efi_loader/efi_disk.c:193
error: lib/efi_loader/efi_disk.c: patch does not apply
Patch failed at 0001 efi_loader: make disk objects for partitions

Could you, please, resubmit your patch series rebased on efi-next.

You somehow forgot to CC the maintainer Alexander Graf in your patch.

Please, always use scripts/get_maintainer.pl to determine whom a patch
should be addressed to.

Best regards

Heinrich Schuchardt

> @@ -228,18 +254,7 @@ static void efi_disk_add_dev(const char *name,
>  	diskobj->media.io_align = desc->blksz;
>  	diskobj->media.last_block = desc->lba - offset;
>  	diskobj->ops.media = &diskobj->media;
> -
> -	/* Fill in device path */
> -	dp = (void*)&diskobj[1];
> -	diskobj->dp = dp;
> -	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
> -	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
> -	dp[0].dp.length = sizeof(*dp);
> -	ascii2unicode(dp[0].str, name);
> -
> -	dp[1].dp.type = DEVICE_PATH_TYPE_END;
> -	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
> -	dp[1].dp.length = sizeof(*dp);
> +	diskobj->dp = blk2dp(desc, name, part);
>  
>  	/* Hook up to the device list */
>  	list_add_tail(&diskobj->parent.link, &efi_obj_list);
> @@ -259,11 +274,16 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
>  	if (desc->part_type != PART_TYPE_ISO)
>  		return 0;
>  
> +#ifdef CONFIG_DM
> +	/* add block device: */
> +	efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
> +#endif
> +	/* ... and devices for each partition: */
>  	while (!part_get_info(desc, part, &info)) {
>  		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
>  			 part);
>  		efi_disk_add_dev(devname, if_typename, desc, diskid,
> -				 info.start);
> +				 info.start, part);
>  		part++;
>  		disks++;
>  	}
> @@ -290,9 +310,22 @@ int efi_disk_register(void)
>  	     uclass_next_device(&dev)) {
>  		struct blk_desc *desc = dev_get_uclass_platdata(dev);
>  		const char *if_typename = dev->driver->name;
> +		disk_partition_t info;
> +		int part = 1;
>  
>  		printf("Scanning disk %s...\n", dev->name);
> -		efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
> +
> +#ifdef CONFIG_DM
> +		/* add block device: */
> +		efi_disk_add_dev(dev->name, if_typename, desc,
> +				desc->devnum, 0, 0);
> +#endif
> +		/* ... and devices for each partition: */
> +		while (!part_get_info(desc, part, &info)) {
> +			efi_disk_add_dev(dev->name, if_typename, desc,
> +					desc->devnum, 0, part);
> +			part++;
> +		}
>  		disks++;
>  
>  		/*
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [U-Boot, 3/4] efi_loader: make disk objects for partitions
  2017-07-23 10:25   ` [U-Boot] [U-Boot, " Heinrich Schuchardt
@ 2017-07-23 19:48     ` Rob Clark
  0 siblings, 0 replies; 10+ messages in thread
From: Rob Clark @ 2017-07-23 19:48 UTC (permalink / raw)
  To: u-boot

On Sun, Jul 23, 2017 at 6:25 AM, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> On 07/21/2017 08:43 PM, Rob Clark wrote:
>> Normally a EFI application, like grub2, is going to expect to see
>
> %s/a/an/
>
>> block-io devices for both the actual disk and for each partition
>> (with the disk object being parent of the partition objects).
>>
>> Now instead of seeing devices like:
>>
>>   /File(sdhci at 07864000.blk)/EndEntire
>>   /File(usb_mass_storage.lun0)/EndEntire
>>
>> You see:
>>
>>   /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
>>   /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,0000000000000000,1,0)/EndEntire
>>   /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,0000000000000000,1,0)/EndEntire
>>   /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,0000000000000000,1,0)/EndEntire
>>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
>>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,0000000000000000,1,0)/EndEntire
>>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,0000000000000000,1,0)/EndEntire
>>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,0000000000000000,1,0)/EndEntire
>>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,0000000000000000,1,0)/EndEntire
>>
>> This is on a board with single USB disk and single sd-card.  The
>> UnknownMessaging(1d) node in the device-path is the MMC device,
>> but grub_efi_print_device_path() hasn't been updated yet for some
>> of the newer device-path sub-types.
>>
>> This patch is somewhat based on a patch originally from Peter Jones,
>> but re-worked to use efi_devpath, so it doesn't much resemble the
>> original.
>>
>> This depends on efi_devpath, which depends on CONFIG_DM, so legacy
>> devices will still get the old broken behavior.
>>
>> There are a couple TODOs:
>>  1) how to find slot # for mmc device
>>  2) how to find parent port # and interface # for usb device
>>
>> Also I don't seem to manage to get u-boot to recognize my usb-eth
>> dongle (config issue?) so I haven't been able to test the net-boot
>> path.. so it likely needs some work.
>>
>> Cc: Peter Jones <pjones@redhat.com>
>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>> ---
>>  lib/efi_loader/efi_disk.c | 73 ++++++++++++++++++++++++++++++++++-------------
>>  1 file changed, 53 insertions(+), 20 deletions(-)
>>
>> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
>> index 09697936b5..44f72c93e2 100644
>> --- a/lib/efi_loader/efi_disk.c
>> +++ b/lib/efi_loader/efi_disk.c
>> @@ -28,7 +28,7 @@ struct efi_disk_obj {
>>       /* EFI Interface Media descriptor struct, referenced by ops */
>>       struct efi_block_io_media media;
>>       /* EFI device path to this block device */
>> -     struct efi_device_path_file_path *dp;
>> +     struct efi_device_path *dp;
>>       /* Offset into disk for simple partitions */
>>       lbaint_t offset;
>>       /* Internal block device */
>> @@ -193,21 +193,47 @@ static const struct efi_block_io block_io_disk_template = {
>>       .flush_blocks = &efi_disk_flush_blocks,
>>  };
>>
>> +static struct efi_device_path *blk2dp(struct blk_desc *desc,
>> +             const char *name, unsigned part)
>> +{
>> +#ifdef CONFIG_DM
>> +     /* part==0 is the case for parent block device representing
>> +      * entire disk, and part>=1 is for child per-partition
>> +      * MEDIA_DEVICE objects:
>> +      */
>> +     if (part == 0)
>> +             return efi_dp_from_dev(desc->bdev->parent);
>> +     return efi_dp_from_part(desc, part);
>> +#else
>> +     struct efi_device_path_file_path *dp = calloc(2, sizeof(*dp));
>> +
>> +     dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
>> +     dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
>> +     dp[0].dp.length = sizeof(*dp);
>> +     ascii2unicode(dp[0].str, name);
>> +
>> +     dp[1].dp.type = DEVICE_PATH_TYPE_END;
>> +     dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
>> +     dp[1].dp.length = sizeof(*dp);
>> +
>> +     return dp;
>> +#endif
>> +}
>> +
>>  static void efi_disk_add_dev(const char *name,
>>                            const char *if_typename,
>> -                          const struct blk_desc *desc,
>> +                          struct blk_desc *desc,
>>                            int dev_index,
>> -                          lbaint_t offset)
>> +                          lbaint_t offset,
>> +                          unsigned part)
>>  {
>>       struct efi_disk_obj *diskobj;
>> -     struct efi_device_path_file_path *dp;
>> -     int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
>>
>>       /* Don't add empty devices */
>>       if (!desc->lba)
>>               return;
>>
>> -     diskobj = calloc(1, objlen);
>> +     diskobj = calloc(1, sizeof(*diskobj));
>>
>>       /* Fill in object data */
>>       diskobj->parent.protocols[0].guid = &efi_block_io_guid;
>
> I am unable to apply this patch to the efi-next branch of
> git://github.com/agraf/u-boot.git
>
> Applying: efi_loader: make disk objects for partitions
> error: patch failed: lib/efi_loader/efi_disk.c:193
> error: lib/efi_loader/efi_disk.c: patch does not apply
> Patch failed at 0001 efi_loader: make disk objects for partitions
>
> Could you, please, resubmit your patch series rebased on efi-next.

sorry, wasn't aware of efi-next tree..  I'll rebase soon.  I have some
more updates[1] (including some parts that I'd like to squash into
this patch) to get shim.efi and fallback.efi working, but I'll send a
new version of these patches when I have that working.

[1] https://github.com/robclark/u-boot/commits/wip-enough-uefi-for-shim
<-- very much work-in-progress

BR,
-R

> You somehow forgot to CC the maintainer Alexander Graf in your patch.
>
> Please, always use scripts/get_maintainer.pl to determine whom a patch
> should be addressed to.
>
> Best regards
>
> Heinrich Schuchardt
>
>> @@ -228,18 +254,7 @@ static void efi_disk_add_dev(const char *name,
>>       diskobj->media.io_align = desc->blksz;
>>       diskobj->media.last_block = desc->lba - offset;
>>       diskobj->ops.media = &diskobj->media;
>> -
>> -     /* Fill in device path */
>> -     dp = (void*)&diskobj[1];
>> -     diskobj->dp = dp;
>> -     dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
>> -     dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
>> -     dp[0].dp.length = sizeof(*dp);
>> -     ascii2unicode(dp[0].str, name);
>> -
>> -     dp[1].dp.type = DEVICE_PATH_TYPE_END;
>> -     dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
>> -     dp[1].dp.length = sizeof(*dp);
>> +     diskobj->dp = blk2dp(desc, name, part);
>>
>>       /* Hook up to the device list */
>>       list_add_tail(&diskobj->parent.link, &efi_obj_list);
>> @@ -259,11 +274,16 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
>>       if (desc->part_type != PART_TYPE_ISO)
>>               return 0;
>>
>> +#ifdef CONFIG_DM
>> +     /* add block device: */
>> +     efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
>> +#endif
>> +     /* ... and devices for each partition: */
>>       while (!part_get_info(desc, part, &info)) {
>>               snprintf(devname, sizeof(devname), "%s:%d", pdevname,
>>                        part);
>>               efi_disk_add_dev(devname, if_typename, desc, diskid,
>> -                              info.start);
>> +                              info.start, part);
>>               part++;
>>               disks++;
>>       }
>> @@ -290,9 +310,22 @@ int efi_disk_register(void)
>>            uclass_next_device(&dev)) {
>>               struct blk_desc *desc = dev_get_uclass_platdata(dev);
>>               const char *if_typename = dev->driver->name;
>> +             disk_partition_t info;
>> +             int part = 1;
>>
>>               printf("Scanning disk %s...\n", dev->name);
>> -             efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
>> +
>> +#ifdef CONFIG_DM
>> +             /* add block device: */
>> +             efi_disk_add_dev(dev->name, if_typename, desc,
>> +                             desc->devnum, 0, 0);
>> +#endif
>> +             /* ... and devices for each partition: */
>> +             while (!part_get_info(desc, part, &info)) {
>> +                     efi_disk_add_dev(dev->name, if_typename, desc,
>> +                                     desc->devnum, 0, part);
>> +                     part++;
>> +             }
>>               disks++;
>>
>>               /*
>>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping
  2017-07-21 18:43 ` [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping Rob Clark
@ 2017-07-25 13:57   ` Rob Clark
  2017-07-25 16:46     ` Alexander Graf
  0 siblings, 1 reply; 10+ messages in thread
From: Rob Clark @ 2017-07-25 13:57 UTC (permalink / raw)
  To: u-boot

So the static bootefi_device_obj is making things slightly awkward for
efi_load_image() from a file-path.  And really it should just go away,
and instead we should plug in the appropriate diskobj (or netobj) to
the loaded_image_obj at boot time.  Also we should nuke
bootefi_device_path.  And since we need to construct a new
loaded_image_obj in efi_load_image(), probably split out a helper to
fill that out properly and plug in the correct boot device-path, etc,
etc, so we don't have too many different places constructing the same
sort of object and forgetting to install some protocols in one place
or another.

And since there are a lot of places we need to map to device-path and
back, I'm starting to thing the sane way to do all this without
breaking legacy (!CONFIG_DM) is to introduce a efi_device_path.c and
efi_device_path_legacy.c.  Move all the hacky stuff of current
devicepath construction into efi_device_path_legacy.c.  Add some
device-path parsing/matching stuff to efi_device_path_util.c (which
probably just be efi_device_path_to_text.c renamed and then spiffed
out with some more device-path helpers), which would be shared in
common in legacy and CONFIG_DM cases.

Sound semi-reasonable?  I'm not sure if this intersects too badly with
other stuff Heinrich is working on?

(Also, small logistical question.. anyone know how to do
"obj-$(!CONFIG_DM) += efi_boot_device_legacy.o"?)

BR,
-R

On Fri, Jul 21, 2017 at 2:43 PM, Rob Clark <robdclark@gmail.com> wrote:
> Initially just supports "disk" type devices, but a real UEFI
> implementation would expose input/output/display/etc with device-paths
> as well, so we may eventually want to expand this for other uses.
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
>  include/efi_loader.h         |   9 +++
>  lib/efi_loader/Makefile      |   1 +
>  lib/efi_loader/efi_devpath.c | 175 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 185 insertions(+)
>  create mode 100644 lib/efi_loader/efi_devpath.c
>
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index 812ec10e37..97d5e3d13d 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -145,6 +145,15 @@ extern void *efi_bounce_buffer;
>  #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024)
>  #endif
>
> +/*
> + * u-boot to EFI device mapping:
> + *
> + * TODO extend this for GOP and various other input/output
> + * devices which should also have an EFI devicepath?
> + */
> +struct efi_device_path *efi_dp_from_dev(struct udevice *dev);
> +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
> +
>  /* Convert strings from normal C strings to uEFI strings */
>  static inline void ascii2unicode(u16 *unicode, const char *ascii)
>  {
> diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> index 9c67367df4..e191a3280b 100644
> --- a/lib/efi_loader/Makefile
> +++ b/lib/efi_loader/Makefile
> @@ -22,3 +22,4 @@ obj-$(CONFIG_DM_VIDEO) += efi_gop.o
>  obj-$(CONFIG_PARTITIONS) += efi_disk.o
>  obj-$(CONFIG_NET) += efi_net.o
>  obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
> +obj-$(CONFIG_DM) += efi_devpath.o
> diff --git a/lib/efi_loader/efi_devpath.c b/lib/efi_loader/efi_devpath.c
> new file mode 100644
> index 0000000000..16b8edf899
> --- /dev/null
> +++ b/lib/efi_loader/efi_devpath.c
> @@ -0,0 +1,175 @@
> +/*
> + * EFI device path from u-boot device-model mapping
> + *
> + * (C) Copyright 2017 Rob Clark
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <blk.h>
> +#include <dm.h>
> +#include <usb.h>
> +#include <mmc.h>
> +#include <efi_loader.h>
> +#include <inttypes.h>
> +#include <part.h>
> +#include <malloc.h>
> +
> +/* template END node: */
> +const static struct efi_device_path END = {
> +       .type     = DEVICE_PATH_TYPE_END,
> +       .sub_type = DEVICE_PATH_SUB_TYPE_END,
> +       .length   = sizeof(END),
> +};
> +
> +/* template ROOT node, a fictional ACPI PNP device: */
> +const static struct efi_device_path_acpi_path ROOT = {
> +       .dp = {
> +               .type     = DEVICE_PATH_TYPE_ACPI_DEVICE,
> +               .sub_type = DEVICE_PATH_SUB_TYPE_ACPI_DEVICE,
> +               .length   = sizeof(ROOT),
> +       },
> +       .hid = EISA_PNP_ID(0x1337),
> +       .uid = 0,
> +};
> +
> +
> +/* size of device-path not including END node for device and all parents
> + * up to the root device.
> + */
> +static unsigned dp_size(struct udevice *dev)
> +{
> +       if (!dev || !dev->driver)
> +               return sizeof(ROOT);
> +
> +       switch (dev->driver->id) {
> +       case UCLASS_ROOT:
> +       case UCLASS_SIMPLE_BUS:
> +               /* stop traversing parents at this point: */
> +               return sizeof(ROOT);
> +       case UCLASS_MMC:
> +               return dp_size(dev->parent) + sizeof(struct efi_device_path_sd_mmc_path);
> +       case UCLASS_MASS_STORAGE:
> +       case UCLASS_USB_HUB:
> +               return dp_size(dev->parent) + sizeof(struct efi_device_path_usb);
> +       default:
> +               /* just skip over unknown classes: */
> +               return dp_size(dev->parent);
> +       }
> +}
> +
> +static void *dp_fill(void *buf, struct udevice *dev)
> +{
> +       if (!dev || !dev->driver)
> +               return buf;
> +
> +       switch (dev->driver->id) {
> +       case UCLASS_ROOT:
> +       case UCLASS_SIMPLE_BUS: {
> +               /* stop traversing parents at this point: */
> +               struct efi_device_path_acpi_path *adp = buf;
> +               *adp = ROOT;
> +               return &adp[1];
> +       }
> +       case UCLASS_MMC: {
> +               struct efi_device_path_sd_mmc_path *sddp =
> +                       dp_fill(buf, dev->parent);
> +               struct mmc *mmc = mmc_get_mmc_dev(dev);
> +               struct blk_desc *desc = mmc_get_blk_desc(mmc);
> +
> +               sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
> +               sddp->dp.sub_type = (desc->if_type == IF_TYPE_MMC) ?
> +                       DEVICE_PATH_SUB_TYPE_MSG_MMC :
> +                       DEVICE_PATH_SUB_TYPE_MSG_SD;
> +               sddp->dp.length   = sizeof(*sddp);
> +               sddp->slot_number = 0;  // XXX ???
> +
> +               return &sddp[1];
> +       }
> +       case UCLASS_MASS_STORAGE:
> +       case UCLASS_USB_HUB: {
> +               struct efi_device_path_usb *udp =
> +                       dp_fill(buf, dev->parent);
> +
> +               udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
> +               udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
> +               udp->dp.length   = sizeof(*udp);
> +               udp->parent_port_number = 0; // XXX ???
> +               udp->usb_interface = 0; // XXX ???
> +
> +               return &udp[1];
> +       }
> +       default:
> +               debug("unhandled device class: %s (%u)\n",
> +                       dev->name, dev->driver->id);
> +               return dp_fill(buf, dev->parent);
> +       }
> +}
> +
> +/* Construct a device-path from a device: */
> +struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
> +{
> +       void *buf, *start;
> +
> +       start = buf = calloc(1, dp_size(dev) + sizeof(END));
> +       buf = dp_fill(buf, dev);
> +       *((struct efi_device_path *)buf) = END;
> +
> +       return start;
> +}
> +
> +/* Construct a device-path from a partition on a blk device: */
> +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
> +{
> +       disk_partition_t info;
> +       unsigned dpsize;
> +       void *buf, *start;
> +
> +       dpsize = dp_size(desc->bdev->parent) + sizeof(END);
> +
> +       if (desc->part_type == PART_TYPE_ISO) {
> +               dpsize += sizeof(struct efi_device_path_cdrom_path);
> +       } else {
> +               dpsize += sizeof(struct efi_device_path_hard_drive_path);
> +       }
> +
> +       start = buf = calloc(1, dpsize);
> +
> +       buf = dp_fill(buf, desc->bdev->parent);
> +
> +       part_get_info(desc, part, &info);
> +
> +       if (desc->part_type == PART_TYPE_ISO) {
> +               struct efi_device_path_cdrom_path *cddp = buf;
> +
> +               cddp->boot_entry = part - 1;
> +               cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
> +               cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
> +               cddp->dp.length = sizeof (*cddp);
> +               cddp->partition_start = info.start;
> +               cddp->partition_end = info.size;
> +
> +               buf = &cddp[1];
> +       } else {
> +               struct efi_device_path_hard_drive_path *hddp = buf;
> +
> +               hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
> +               hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
> +               hddp->dp.length = sizeof (*hddp);
> +               hddp->partition_number = part - 1;
> +               hddp->partition_start = info.start;
> +               hddp->partition_end = info.size;
> +               if (desc->part_type == PART_TYPE_EFI)
> +                       hddp->partmap_type = 2;
> +               else
> +                       hddp->partmap_type = 1;
> +               hddp->signature_type = 0;
> +
> +               buf = &hddp[1];
> +       }
> +
> +       *((struct efi_device_path *)buf) = END;
> +
> +       return start;
> +}
> --
> 2.13.0
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping
  2017-07-25 13:57   ` Rob Clark
@ 2017-07-25 16:46     ` Alexander Graf
  2017-07-25 17:05       ` Heinrich Schuchardt
  0 siblings, 1 reply; 10+ messages in thread
From: Alexander Graf @ 2017-07-25 16:46 UTC (permalink / raw)
  To: u-boot



On 25.07.17 15:57, Rob Clark wrote:
> So the static bootefi_device_obj is making things slightly awkward for
> efi_load_image() from a file-path.  And really it should just go away,
> and instead we should plug in the appropriate diskobj (or netobj) to
> the loaded_image_obj at boot time.  Also we should nuke
> bootefi_device_path.  And since we need to construct a new
> loaded_image_obj in efi_load_image(), probably split out a helper to
> fill that out properly and plug in the correct boot device-path, etc,
> etc, so we don't have too many different places constructing the same
> sort of object and forgetting to install some protocols in one place
> or another.
> 
> And since there are a lot of places we need to map to device-path and
> back, I'm starting to thing the sane way to do all this without
> breaking legacy (!CONFIG_DM) is to introduce a efi_device_path.c and
> efi_device_path_legacy.c.  Move all the hacky stuff of current
> devicepath construction into efi_device_path_legacy.c.  Add some
> device-path parsing/matching stuff to efi_device_path_util.c (which
> probably just be efi_device_path_to_text.c renamed and then spiffed
> out with some more device-path helpers), which would be shared in
> common in legacy and CONFIG_DM cases.
> 
> Sound semi-reasonable?  I'm not sure if this intersects too badly with

Sounds reasonable to me :).

> other stuff Heinrich is working on?

I don't know - I'll let him comment.

> 
> (Also, small logistical question.. anyone know how to do
> "obj-$(!CONFIG_DM) += efi_boot_device_legacy.o"?)

I would do

ifeq ($(CONFIG_DM),y)
   obj-y += efi_boot_device_dm.o
else
   obj-y += efi_boot_device_nodm.o
endif


Alex

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping
  2017-07-25 16:46     ` Alexander Graf
@ 2017-07-25 17:05       ` Heinrich Schuchardt
  0 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-25 17:05 UTC (permalink / raw)
  To: u-boot

On 07/25/2017 06:46 PM, Alexander Graf wrote:
> 
> 
> On 25.07.17 15:57, Rob Clark wrote:
>> So the static bootefi_device_obj is making things slightly awkward for
>> efi_load_image() from a file-path.  And really it should just go away,
>> and instead we should plug in the appropriate diskobj (or netobj) to
>> the loaded_image_obj at boot time.  Also we should nuke
>> bootefi_device_path.  And since we need to construct a new
>> loaded_image_obj in efi_load_image(), probably split out a helper to
>> fill that out properly and plug in the correct boot device-path, etc,
>> etc, so we don't have too many different places constructing the same
>> sort of object and forgetting to install some protocols in one place
>> or another.
>>
>> And since there are a lot of places we need to map to device-path and
>> back, I'm starting to thing the sane way to do all this without
>> breaking legacy (!CONFIG_DM) is to introduce a efi_device_path.c and
>> efi_device_path_legacy.c.  Move all the hacky stuff of current
>> devicepath construction into efi_device_path_legacy.c.  Add some
>> device-path parsing/matching stuff to efi_device_path_util.c (which
>> probably just be efi_device_path_to_text.c renamed and then spiffed
>> out with some more device-path helpers), which would be shared in
>> common in legacy and CONFIG_DM cases.
>>
>> Sound semi-reasonable?  I'm not sure if this intersects too badly with
> 
> Sounds reasonable to me :).
> 
>> other stuff Heinrich is working on?
> 
> I don't know - I'll let him comment.
> 

OpenProtocol should manage a lock table of type
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY[] per protocol.
I am trying to implement this table which is also
needed by OpenProtocolInformation, CloseProtocol,
ConnectController, and DisconnectConntroller.

Best regards

Heinrich

>>
>> (Also, small logistical question.. anyone know how to do
>> "obj-$(!CONFIG_DM) += efi_boot_device_legacy.o"?)
> 
> I would do
> 
> ifeq ($(CONFIG_DM),y)
>   obj-y += efi_boot_device_dm.o
> else
>   obj-y += efi_boot_device_nodm.o
> endif
> 
> 
> Alex
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-07-25 17:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-21 18:43 [U-Boot] [PATCH 0/4] efi_loader: fix disk objects + device-paths Rob Clark
2017-07-21 18:43 ` [U-Boot] [PATCH 1/4] efi: add some more device path structures Rob Clark
2017-07-21 18:43 ` [U-Boot] [PATCH 2/4] efi_loader: add udevice to EFI device-path mapping Rob Clark
2017-07-25 13:57   ` Rob Clark
2017-07-25 16:46     ` Alexander Graf
2017-07-25 17:05       ` Heinrich Schuchardt
2017-07-21 18:43 ` [U-Boot] [PATCH 3/4] efi_loader: make disk objects for partitions Rob Clark
2017-07-23 10:25   ` [U-Boot] [U-Boot, " Heinrich Schuchardt
2017-07-23 19:48     ` Rob Clark
2017-07-21 18:43 ` [U-Boot] [PATCH 4/4] efi_loader: use efi_devpath to get correct boot device-path Rob Clark

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.