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 <robdcl...@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 <robdcl...@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 > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot