1 // SPDX-License-Identifier: GPL-2.0+
3 * EFI device path from u-boot device-model mapping
5 * (C) Copyright 2017 Rob Clark
15 #include <efi_loader.h>
17 #include <sandboxblockdev.h>
18 #include <asm-generic/unaligned.h>
19 #include <linux/compat.h> /* U16_MAX */
22 const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
25 /* template END node: */
26 static const struct efi_device_path END = {
27 .type = DEVICE_PATH_TYPE_END,
28 .sub_type = DEVICE_PATH_SUB_TYPE_END,
29 .length = sizeof(END),
32 /* template ROOT node: */
33 static const struct efi_device_path_vendor ROOT = {
35 .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
36 .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
37 .length = sizeof(ROOT),
42 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
44 * Determine if an MMC device is an SD card.
46 * @desc block device descriptor
47 * @return true if the device is an SD card
49 static bool is_sd(struct blk_desc *desc)
51 struct mmc *mmc = find_mmc_device(desc->devnum);
56 return IS_SD(mmc) != 0U;
60 static void *dp_alloc(size_t sz)
64 if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
66 debug("EFI: ERROR: out of memory in %s\n", __func__);
75 * Iterate to next block in device-path, terminating (returning NULL)
78 struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
82 if (dp->type == DEVICE_PATH_TYPE_END)
84 dp = ((void *)dp) + dp->length;
85 if (dp->type == DEVICE_PATH_TYPE_END)
87 return (struct efi_device_path *)dp;
91 * Compare two device-paths, stopping when the shorter of the two hits
92 * an End* node. This is useful to, for example, compare a device-path
93 * representing a device with one representing a file on the device, or
94 * a device with a parent device.
96 int efi_dp_match(const struct efi_device_path *a,
97 const struct efi_device_path *b)
102 ret = memcmp(&a->length, &b->length, sizeof(a->length));
106 ret = memcmp(a, b, a->length);
119 * We can have device paths that start with a USB WWID or a USB Class node,
120 * and a few other cases which don't encode the full device path with bus
123 * - MESSAGING:USB_WWID
124 * - MESSAGING:USB_CLASS
129 * See UEFI spec (section 3.1.2, about short-form device-paths)
131 static struct efi_device_path *shorten_path(struct efi_device_path *dp)
135 * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI..
136 * in practice fallback.efi just uses MEDIA:HARD_DRIVE
137 * so not sure when we would see these other cases.
139 if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
140 EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
141 EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
144 dp = efi_dp_next(dp);
150 static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
151 struct efi_device_path **rem)
153 struct efi_object *efiobj;
154 efi_uintn_t dp_size = efi_dp_instance_size(dp);
156 list_for_each_entry(efiobj, &efi_obj_list, link) {
157 struct efi_handler *handler;
158 struct efi_device_path *obj_dp;
161 ret = efi_search_protocol(efiobj,
162 &efi_guid_device_path, &handler);
163 if (ret != EFI_SUCCESS)
165 obj_dp = handler->protocol_interface;
168 if (efi_dp_match(dp, obj_dp) == 0) {
171 * Allow partial matches, but inform
174 *rem = ((void *)dp) +
175 efi_dp_instance_size(obj_dp);
178 /* Only return on exact matches */
179 if (efi_dp_instance_size(obj_dp) ==
185 obj_dp = shorten_path(efi_dp_next(obj_dp));
186 } while (short_path && obj_dp);
193 * Find an efiobj from device-path, if 'rem' is not NULL, returns the
194 * remaining part of the device path after the matched object.
196 struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
197 struct efi_device_path **rem)
199 struct efi_object *efiobj;
201 /* Search for an exact match first */
202 efiobj = find_obj(dp, false, NULL);
204 /* Then for a fuzzy match */
206 efiobj = find_obj(dp, false, rem);
208 /* And now for a fuzzy short match */
210 efiobj = find_obj(dp, true, rem);
216 * Determine the last device path node that is not the end node.
219 * @return last node before the end node if it exists
222 const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
224 struct efi_device_path *ret;
226 if (!dp || dp->type == DEVICE_PATH_TYPE_END)
229 ret = (struct efi_device_path *)dp;
230 dp = efi_dp_next(dp);
235 /* get size of the first device path instance excluding end node */
236 efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
240 if (!dp || dp->type == DEVICE_PATH_TYPE_END)
244 dp = efi_dp_next(dp);
250 /* get size of multi-instance device path excluding end node */
251 efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
253 const struct efi_device_path *p = dp;
257 while (p->type != DEVICE_PATH_TYPE_END ||
258 p->sub_type != DEVICE_PATH_SUB_TYPE_END)
259 p = (void *)p + p->length;
261 return (void *)p - (void *)dp;
264 /* copy multi-instance device path */
265 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
267 struct efi_device_path *ndp;
268 size_t sz = efi_dp_size(dp) + sizeof(END);
281 struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
282 const struct efi_device_path *dp2)
284 struct efi_device_path *ret;
287 /* return an end node */
288 ret = efi_dp_dup(&END);
290 ret = efi_dp_dup(dp2);
292 ret = efi_dp_dup(dp1);
294 /* both dp1 and dp2 are non-null */
295 unsigned sz1 = efi_dp_size(dp1);
296 unsigned sz2 = efi_dp_size(dp2);
297 void *p = dp_alloc(sz1 + sz2 + sizeof(END));
301 /* the end node of the second device path has to be retained */
302 memcpy(p + sz1, dp2, sz2 + sizeof(END));
309 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
310 const struct efi_device_path *node)
312 struct efi_device_path *ret;
315 ret = efi_dp_dup(&END);
317 ret = efi_dp_dup(dp);
319 size_t sz = node->length;
320 void *p = dp_alloc(sz + sizeof(END));
324 memcpy(p + sz, &END, sizeof(END));
327 /* both dp and node are non-null */
328 size_t sz = efi_dp_size(dp);
329 void *p = dp_alloc(sz + node->length + sizeof(END));
333 memcpy(p + sz, node, node->length);
334 memcpy(p + sz + node->length, &END, sizeof(END));
341 struct efi_device_path *efi_dp_create_device_node(const u8 type,
345 struct efi_device_path *ret;
347 if (length < sizeof(struct efi_device_path))
350 ret = dp_alloc(length);
354 ret->sub_type = sub_type;
355 ret->length = length;
359 struct efi_device_path *efi_dp_append_instance(
360 const struct efi_device_path *dp,
361 const struct efi_device_path *dpi)
364 struct efi_device_path *p, *ret;
369 return efi_dp_dup(dpi);
370 sz = efi_dp_size(dp);
371 szi = efi_dp_instance_size(dpi);
372 p = dp_alloc(sz + szi + 2 * sizeof(END));
376 memcpy(p, dp, sz + sizeof(END));
378 p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END;
379 p = (void *)p + sizeof(END);
382 memcpy(p, &END, sizeof(END));
386 struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
390 struct efi_device_path *p;
396 sz = efi_dp_instance_size(*dp);
397 p = dp_alloc(sz + sizeof(END));
400 memcpy(p, *dp, sz + sizeof(END));
401 *dp = (void *)*dp + sz;
402 if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END)
403 *dp = (void *)*dp + sizeof(END);
407 *size = sz + sizeof(END);
411 bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
413 const struct efi_device_path *p = dp;
417 while (p->type != DEVICE_PATH_TYPE_END)
418 p = (void *)p + p->length;
419 return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END;
423 /* size of device-path not including END node for device and all parents
424 * up to the root device.
426 __maybe_unused static unsigned int dp_size(struct udevice *dev)
428 if (!dev || !dev->driver)
431 switch (dev->driver->id) {
433 case UCLASS_SIMPLE_BUS:
434 /* stop traversing parents at this point: */
437 return dp_size(dev->parent) +
438 sizeof(struct efi_device_path_mac_addr);
441 switch (dev->parent->uclass->uc_drv->id) {
444 return dp_size(dev->parent) +
445 sizeof(struct efi_device_path_atapi);
447 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
449 return dp_size(dev->parent) +
450 sizeof(struct efi_device_path_scsi);
452 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
454 return dp_size(dev->parent) +
455 sizeof(struct efi_device_path_sd_mmc_path);
457 #if defined(CONFIG_NVME)
459 return dp_size(dev->parent) +
460 sizeof(struct efi_device_path_nvme);
462 #ifdef CONFIG_SANDBOX
465 * Sandbox's host device will be represented
466 * as vendor device with extra one byte for
469 return dp_size(dev->parent)
470 + sizeof(struct efi_device_path_vendor) + 1;
473 return dp_size(dev->parent);
476 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
478 return dp_size(dev->parent) +
479 sizeof(struct efi_device_path_sd_mmc_path);
481 case UCLASS_MASS_STORAGE:
483 return dp_size(dev->parent) +
484 sizeof(struct efi_device_path_usb_class);
486 /* just skip over unknown classes: */
487 return dp_size(dev->parent);
492 * Recursively build a device path.
494 * @buf pointer to the end of the device path
496 * @return pointer to the end of the device path
498 __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
500 if (!dev || !dev->driver)
503 switch (dev->driver->id) {
505 case UCLASS_SIMPLE_BUS: {
506 /* stop traversing parents at this point: */
507 struct efi_device_path_vendor *vdp = buf;
513 struct efi_device_path_mac_addr *dp =
514 dp_fill(buf, dev->parent);
515 struct eth_pdata *pdata = dev->platdata;
517 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
518 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
519 dp->dp.length = sizeof(*dp);
520 memset(&dp->mac, 0, sizeof(dp->mac));
521 /* We only support IPv4 */
522 memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
530 switch (dev->parent->uclass->uc_drv->id) {
531 #ifdef CONFIG_SANDBOX
533 /* stop traversing parents at this point: */
534 struct efi_device_path_vendor *dp;
535 struct blk_desc *desc = dev_get_uclass_platdata(dev);
537 dp_fill(buf, dev->parent);
540 dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
541 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
542 dp->dp.length = sizeof(*dp) + 1;
543 memcpy(&dp->guid, &efi_guid_host_dev,
545 dp->vendor_data[0] = desc->devnum;
546 return &dp->vendor_data[1];
551 struct efi_device_path_atapi *dp =
552 dp_fill(buf, dev->parent);
553 struct blk_desc *desc = dev_get_uclass_platdata(dev);
555 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
556 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
557 dp->dp.length = sizeof(*dp);
558 dp->logical_unit_number = desc->devnum;
559 dp->primary_secondary = IDE_BUS(desc->devnum);
560 dp->slave_master = desc->devnum %
561 (CONFIG_SYS_IDE_MAXDEVICE /
562 CONFIG_SYS_IDE_MAXBUS);
566 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
568 struct efi_device_path_scsi *dp =
569 dp_fill(buf, dev->parent);
570 struct blk_desc *desc = dev_get_uclass_platdata(dev);
572 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
573 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
574 dp->dp.length = sizeof(*dp);
575 dp->logical_unit_number = desc->lun;
576 dp->target_id = desc->target;
580 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
582 struct efi_device_path_sd_mmc_path *sddp =
583 dp_fill(buf, dev->parent);
584 struct blk_desc *desc = dev_get_uclass_platdata(dev);
586 sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
587 sddp->dp.sub_type = is_sd(desc) ?
588 DEVICE_PATH_SUB_TYPE_MSG_SD :
589 DEVICE_PATH_SUB_TYPE_MSG_MMC;
590 sddp->dp.length = sizeof(*sddp);
591 sddp->slot_number = dev->seq;
595 #if defined(CONFIG_NVME)
597 struct efi_device_path_nvme *dp =
598 dp_fill(buf, dev->parent);
601 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
602 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_NVME;
603 dp->dp.length = sizeof(*dp);
604 nvme_get_namespace_id(dev, &ns_id, dp->eui64);
605 memcpy(&dp->ns_id, &ns_id, sizeof(ns_id));
610 debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
611 __FILE__, __LINE__, __func__,
612 dev->name, dev->parent->uclass->uc_drv->id);
613 return dp_fill(buf, dev->parent);
616 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
618 struct efi_device_path_sd_mmc_path *sddp =
619 dp_fill(buf, dev->parent);
620 struct mmc *mmc = mmc_get_mmc_dev(dev);
621 struct blk_desc *desc = mmc_get_blk_desc(mmc);
623 sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
624 sddp->dp.sub_type = is_sd(desc) ?
625 DEVICE_PATH_SUB_TYPE_MSG_SD :
626 DEVICE_PATH_SUB_TYPE_MSG_MMC;
627 sddp->dp.length = sizeof(*sddp);
628 sddp->slot_number = dev->seq;
633 case UCLASS_MASS_STORAGE:
634 case UCLASS_USB_HUB: {
635 struct efi_device_path_usb_class *udp =
636 dp_fill(buf, dev->parent);
637 struct usb_device *udev = dev_get_parent_priv(dev);
638 struct usb_device_descriptor *desc = &udev->descriptor;
640 udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
641 udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
642 udp->dp.length = sizeof(*udp);
643 udp->vendor_id = desc->idVendor;
644 udp->product_id = desc->idProduct;
645 udp->device_class = desc->bDeviceClass;
646 udp->device_subclass = desc->bDeviceSubClass;
647 udp->device_protocol = desc->bDeviceProtocol;
652 debug("%s(%u) %s: unhandled device class: %s (%u)\n",
653 __FILE__, __LINE__, __func__,
654 dev->name, dev->driver->id);
655 return dp_fill(buf, dev->parent);
660 static unsigned dp_part_size(struct blk_desc *desc, int part)
667 int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
670 dev = desc->bdev->parent;
671 dpsize = dp_size(dev);
674 dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
677 if (part == 0) /* the actual disk, not a partition */
680 if (desc->part_type == PART_TYPE_ISO)
681 dpsize += sizeof(struct efi_device_path_cdrom_path);
683 dpsize += sizeof(struct efi_device_path_hard_drive_path);
689 * Create a device node for a block device partition.
691 * @buf buffer to which the device path is written
692 * @desc block device descriptor
693 * @part partition number, 0 identifies a block device
695 static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
697 struct disk_partition info;
699 part_get_info(desc, part, &info);
701 if (desc->part_type == PART_TYPE_ISO) {
702 struct efi_device_path_cdrom_path *cddp = buf;
704 cddp->boot_entry = part;
705 cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
706 cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
707 cddp->dp.length = sizeof(*cddp);
708 cddp->partition_start = info.start;
709 cddp->partition_size = info.size;
713 struct efi_device_path_hard_drive_path *hddp = buf;
715 hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
716 hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
717 hddp->dp.length = sizeof(*hddp);
718 hddp->partition_number = part;
719 hddp->partition_start = info.start;
720 hddp->partition_end = info.size;
721 if (desc->part_type == PART_TYPE_EFI)
722 hddp->partmap_type = 2;
724 hddp->partmap_type = 1;
726 switch (desc->sig_type) {
729 hddp->signature_type = 0;
730 memset(hddp->partition_signature, 0,
731 sizeof(hddp->partition_signature));
734 hddp->signature_type = 1;
735 memset(hddp->partition_signature, 0,
736 sizeof(hddp->partition_signature));
737 memcpy(hddp->partition_signature, &desc->mbr_sig,
738 sizeof(desc->mbr_sig));
741 hddp->signature_type = 2;
742 memcpy(hddp->partition_signature, &desc->guid_sig,
743 sizeof(hddp->partition_signature));
754 * Create a device path for a block device or one of its partitions.
756 * @buf buffer to which the device path is written
757 * @desc block device descriptor
758 * @part partition number, 0 identifies a block device
760 static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
765 int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
768 dev = desc->bdev->parent;
769 buf = dp_fill(buf, dev);
773 * We *could* make a more accurate path, by looking at if_type
774 * and handling all the different cases like we do for non-
775 * legacy (i.e. CONFIG_BLK=y) case. But most important thing
776 * is just to have a unique device-path for if_type+devnum.
777 * So map things to a fictitious USB device.
779 struct efi_device_path_usb *udp;
781 memcpy(buf, &ROOT, sizeof(ROOT));
785 udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
786 udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
787 udp->dp.length = sizeof(*udp);
788 udp->parent_port_number = desc->if_type;
789 udp->usb_interface = desc->devnum;
793 if (part == 0) /* the actual disk, not a partition */
796 return dp_part_node(buf, desc, part);
799 /* Construct a device-path from a partition on a block device: */
800 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
804 start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
808 buf = dp_part_fill(buf, desc, part);
810 *((struct efi_device_path *)buf) = END;
816 * Create a device node for a block device partition.
818 * @buf buffer to which the device path is written
819 * @desc block device descriptor
820 * @part partition number, 0 identifies a block device
822 struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
827 if (desc->part_type == PART_TYPE_ISO)
828 dpsize = sizeof(struct efi_device_path_cdrom_path);
830 dpsize = sizeof(struct efi_device_path_hard_drive_path);
831 buf = dp_alloc(dpsize);
833 dp_part_node(buf, desc, part);
839 * path_to_uefi() - convert UTF-8 path to an UEFI style path
841 * Convert UTF-8 path to a UEFI style path (i.e. with backslashes as path
842 * separators and UTF-16).
844 * @src: source buffer
845 * @uefi: target buffer, possibly unaligned
847 static void path_to_uefi(void *uefi, const char *src)
852 * efi_set_bootdev() calls this routine indirectly before the UEFI
853 * subsystem is initialized. So we cannot assume unaligned access to be
859 s32 code = utf8_get(&src);
863 else if (code == '/')
865 utf16_put(code, &pos);
871 * If desc is NULL, this creates a path with only the file component,
872 * otherwise it creates a full path with both device and file components
874 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
877 struct efi_device_path_file_path *fp;
879 size_t dpsize = 0, fpsize;
882 dpsize = dp_part_size(desc, part);
884 fpsize = sizeof(struct efi_device_path) +
885 2 * (utf8_utf16_strlen(path) + 1);
886 if (fpsize > U16_MAX)
891 start = buf = dp_alloc(dpsize + sizeof(END));
896 buf = dp_part_fill(buf, desc, part);
900 fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
901 fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
902 fp->dp.length = (u16)fpsize;
903 path_to_uefi(fp->str, path);
906 *((struct efi_device_path *)buf) = END;
912 struct efi_device_path *efi_dp_from_eth(void)
914 #ifndef CONFIG_DM_ETH
915 struct efi_device_path_mac_addr *ndp;
920 assert(eth_get_dev());
923 dpsize += dp_size(eth_get_dev());
925 dpsize += sizeof(ROOT);
926 dpsize += sizeof(*ndp);
929 start = buf = dp_alloc(dpsize + sizeof(END));
934 buf = dp_fill(buf, eth_get_dev());
936 memcpy(buf, &ROOT, sizeof(ROOT));
940 ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
941 ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
942 ndp->dp.length = sizeof(*ndp);
943 ndp->if_type = 1; /* Ethernet */
944 memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
948 *((struct efi_device_path *)buf) = END;
954 /* Construct a device-path for memory-mapped image */
955 struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
956 uint64_t start_address,
957 uint64_t end_address)
959 struct efi_device_path_memory *mdp;
962 start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
967 mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
968 mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
969 mdp->dp.length = sizeof(*mdp);
970 mdp->memory_type = memory_type;
971 mdp->start_address = start_address;
972 mdp->end_address = end_address;
975 *((struct efi_device_path *)buf) = END;
981 * efi_dp_split_file_path() - split of relative file path from device path
983 * Given a device path indicating a file on a device, separate the device
984 * path in two: the device path of the actual device and the file path
985 * relative to this device.
987 * @full_path: device path including device and file path
988 * @device_path: path of the device
989 * @file_path: relative path of the file or NULL if there is none
990 * Return: status code
992 efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
993 struct efi_device_path **device_path,
994 struct efi_device_path **file_path)
996 struct efi_device_path *p, *dp, *fp = NULL;
1000 dp = efi_dp_dup(full_path);
1002 return EFI_OUT_OF_RESOURCES;
1004 while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
1011 return EFI_OUT_OF_RESOURCES;
1012 p->type = DEVICE_PATH_TYPE_END;
1013 p->sub_type = DEVICE_PATH_SUB_TYPE_END;
1014 p->length = sizeof(*p);
1023 * efi_dp_from_name() - convert U-Boot device and file path to device path
1025 * @dev: U-Boot device, e.g. 'mmc'
1026 * @devnr: U-Boot device number, e.g. 1 for 'mmc:1'
1027 * @path: file path relative to U-Boot device, may be NULL
1028 * @device: pointer to receive device path of the device
1029 * @file: pointer to receive device path for the file
1030 * Return: status code
1032 efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
1034 struct efi_device_path **device,
1035 struct efi_device_path **file)
1038 struct blk_desc *desc = NULL;
1039 struct disk_partition fs_partition;
1041 char filename[32] = { 0 }; /* dp->str is u16[32] long */
1045 return EFI_INVALID_PARAMETER;
1047 is_net = !strcmp(dev, "Net");
1049 part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
1051 if (part < 0 || !desc)
1052 return EFI_INVALID_PARAMETER;
1055 *device = efi_dp_from_part(desc, part);
1059 *device = efi_dp_from_eth();
1066 snprintf(filename, sizeof(filename), "%s", path);
1067 /* DOS style file path: */
1069 while ((s = strchr(s, '/')))
1071 *file = efi_dp_from_file(is_net ? NULL : desc, part, filename);
1074 return EFI_INVALID_PARAMETER;