* [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.