1
2
3
4
5
6
7
8#include <common.h>
9#include <blk.h>
10#include <dm.h>
11#include <log.h>
12#include <net.h>
13#include <usb.h>
14#include <mmc.h>
15#include <nvme.h>
16#include <efi_loader.h>
17#include <part.h>
18#include <sandboxblockdev.h>
19#include <asm-generic/unaligned.h>
20#include <linux/compat.h>
21
22#ifdef CONFIG_SANDBOX
23const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
24#endif
25#ifdef CONFIG_VIRTIO_BLK
26const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID;
27#endif
28
29
30static const struct efi_device_path END = {
31 .type = DEVICE_PATH_TYPE_END,
32 .sub_type = DEVICE_PATH_SUB_TYPE_END,
33 .length = sizeof(END),
34};
35
36
37static const struct efi_device_path_vendor ROOT = {
38 .dp = {
39 .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
40 .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
41 .length = sizeof(ROOT),
42 },
43 .guid = U_BOOT_GUID,
44};
45
46#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
47
48
49
50
51
52
53static bool is_sd(struct blk_desc *desc)
54{
55 struct mmc *mmc = find_mmc_device(desc->devnum);
56
57 if (!mmc)
58 return false;
59
60 return IS_SD(mmc) != 0U;
61}
62#endif
63
64static void *dp_alloc(size_t sz)
65{
66 void *buf;
67
68 if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
69 EFI_SUCCESS) {
70 debug("EFI: ERROR: out of memory in %s\n", __func__);
71 return NULL;
72 }
73
74 memset(buf, 0, sz);
75 return buf;
76}
77
78
79
80
81
82struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
83{
84 if (dp == NULL)
85 return NULL;
86 if (dp->type == DEVICE_PATH_TYPE_END)
87 return NULL;
88 dp = ((void *)dp) + dp->length;
89 if (dp->type == DEVICE_PATH_TYPE_END)
90 return NULL;
91 return (struct efi_device_path *)dp;
92}
93
94
95
96
97
98
99
100int efi_dp_match(const struct efi_device_path *a,
101 const struct efi_device_path *b)
102{
103 while (1) {
104 int ret;
105
106 ret = memcmp(&a->length, &b->length, sizeof(a->length));
107 if (ret)
108 return ret;
109
110 ret = memcmp(a, b, a->length);
111 if (ret)
112 return ret;
113
114 a = efi_dp_next(a);
115 b = efi_dp_next(b);
116
117 if (!a || !b)
118 return 0;
119 }
120}
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135static struct efi_device_path *shorten_path(struct efi_device_path *dp)
136{
137 while (dp) {
138
139
140
141
142
143 if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
144 EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
145 EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
146 return dp;
147
148 dp = efi_dp_next(dp);
149 }
150
151 return dp;
152}
153
154static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
155 struct efi_device_path **rem)
156{
157 struct efi_object *efiobj;
158 efi_uintn_t dp_size = efi_dp_instance_size(dp);
159
160 list_for_each_entry(efiobj, &efi_obj_list, link) {
161 struct efi_handler *handler;
162 struct efi_device_path *obj_dp;
163 efi_status_t ret;
164
165 ret = efi_search_protocol(efiobj,
166 &efi_guid_device_path, &handler);
167 if (ret != EFI_SUCCESS)
168 continue;
169 obj_dp = handler->protocol_interface;
170
171 do {
172 if (efi_dp_match(dp, obj_dp) == 0) {
173 if (rem) {
174
175
176
177
178 *rem = ((void *)dp) +
179 efi_dp_instance_size(obj_dp);
180 return efiobj;
181 } else {
182
183 if (efi_dp_instance_size(obj_dp) ==
184 dp_size)
185 return efiobj;
186 }
187 }
188
189 obj_dp = shorten_path(efi_dp_next(obj_dp));
190 } while (short_path && obj_dp);
191 }
192
193 return NULL;
194}
195
196
197
198
199
200struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
201 struct efi_device_path **rem)
202{
203 struct efi_object *efiobj;
204
205
206 efiobj = find_obj(dp, false, NULL);
207
208
209 if (!efiobj)
210 efiobj = find_obj(dp, false, rem);
211
212
213 if (!efiobj)
214 efiobj = find_obj(dp, true, rem);
215
216 return efiobj;
217}
218
219
220
221
222
223
224
225
226const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
227{
228 struct efi_device_path *ret;
229
230 if (!dp || dp->type == DEVICE_PATH_TYPE_END)
231 return NULL;
232 while (dp) {
233 ret = (struct efi_device_path *)dp;
234 dp = efi_dp_next(dp);
235 }
236 return ret;
237}
238
239
240efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
241{
242 efi_uintn_t sz = 0;
243
244 if (!dp || dp->type == DEVICE_PATH_TYPE_END)
245 return 0;
246 while (dp) {
247 sz += dp->length;
248 dp = efi_dp_next(dp);
249 }
250
251 return sz;
252}
253
254
255efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
256{
257 const struct efi_device_path *p = dp;
258
259 if (!p)
260 return 0;
261 while (p->type != DEVICE_PATH_TYPE_END ||
262 p->sub_type != DEVICE_PATH_SUB_TYPE_END)
263 p = (void *)p + p->length;
264
265 return (void *)p - (void *)dp;
266}
267
268
269struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
270{
271 struct efi_device_path *ndp;
272 size_t sz = efi_dp_size(dp) + sizeof(END);
273
274 if (!dp)
275 return NULL;
276
277 ndp = dp_alloc(sz);
278 if (!ndp)
279 return NULL;
280 memcpy(ndp, dp, sz);
281
282 return ndp;
283}
284
285struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
286 const struct efi_device_path *dp2)
287{
288 struct efi_device_path *ret;
289
290 if (!dp1 && !dp2) {
291
292 ret = efi_dp_dup(&END);
293 } else if (!dp1) {
294 ret = efi_dp_dup(dp2);
295 } else if (!dp2) {
296 ret = efi_dp_dup(dp1);
297 } else {
298
299 unsigned sz1 = efi_dp_size(dp1);
300 unsigned sz2 = efi_dp_size(dp2);
301 void *p = dp_alloc(sz1 + sz2 + sizeof(END));
302 if (!p)
303 return NULL;
304 memcpy(p, dp1, sz1);
305
306 memcpy(p + sz1, dp2, sz2 + sizeof(END));
307 ret = p;
308 }
309
310 return ret;
311}
312
313struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
314 const struct efi_device_path *node)
315{
316 struct efi_device_path *ret;
317
318 if (!node && !dp) {
319 ret = efi_dp_dup(&END);
320 } else if (!node) {
321 ret = efi_dp_dup(dp);
322 } else if (!dp) {
323 size_t sz = node->length;
324 void *p = dp_alloc(sz + sizeof(END));
325 if (!p)
326 return NULL;
327 memcpy(p, node, sz);
328 memcpy(p + sz, &END, sizeof(END));
329 ret = p;
330 } else {
331
332 size_t sz = efi_dp_size(dp);
333 void *p = dp_alloc(sz + node->length + sizeof(END));
334 if (!p)
335 return NULL;
336 memcpy(p, dp, sz);
337 memcpy(p + sz, node, node->length);
338 memcpy(p + sz + node->length, &END, sizeof(END));
339 ret = p;
340 }
341
342 return ret;
343}
344
345struct efi_device_path *efi_dp_create_device_node(const u8 type,
346 const u8 sub_type,
347 const u16 length)
348{
349 struct efi_device_path *ret;
350
351 if (length < sizeof(struct efi_device_path))
352 return NULL;
353
354 ret = dp_alloc(length);
355 if (!ret)
356 return ret;
357 ret->type = type;
358 ret->sub_type = sub_type;
359 ret->length = length;
360 return ret;
361}
362
363struct efi_device_path *efi_dp_append_instance(
364 const struct efi_device_path *dp,
365 const struct efi_device_path *dpi)
366{
367 size_t sz, szi;
368 struct efi_device_path *p, *ret;
369
370 if (!dpi)
371 return NULL;
372 if (!dp)
373 return efi_dp_dup(dpi);
374 sz = efi_dp_size(dp);
375 szi = efi_dp_instance_size(dpi);
376 p = dp_alloc(sz + szi + 2 * sizeof(END));
377 if (!p)
378 return NULL;
379 ret = p;
380 memcpy(p, dp, sz + sizeof(END));
381 p = (void *)p + sz;
382 p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END;
383 p = (void *)p + sizeof(END);
384 memcpy(p, dpi, szi);
385 p = (void *)p + szi;
386 memcpy(p, &END, sizeof(END));
387 return ret;
388}
389
390struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
391 efi_uintn_t *size)
392{
393 size_t sz;
394 struct efi_device_path *p;
395
396 if (size)
397 *size = 0;
398 if (!dp || !*dp)
399 return NULL;
400 sz = efi_dp_instance_size(*dp);
401 p = dp_alloc(sz + sizeof(END));
402 if (!p)
403 return NULL;
404 memcpy(p, *dp, sz + sizeof(END));
405 *dp = (void *)*dp + sz;
406 if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END)
407 *dp = (void *)*dp + sizeof(END);
408 else
409 *dp = NULL;
410 if (size)
411 *size = sz + sizeof(END);
412 return p;
413}
414
415bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
416{
417 const struct efi_device_path *p = dp;
418
419 if (!p)
420 return false;
421 while (p->type != DEVICE_PATH_TYPE_END)
422 p = (void *)p + p->length;
423 return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END;
424}
425
426#ifdef CONFIG_DM
427
428
429
430__maybe_unused static unsigned int dp_size(struct udevice *dev)
431{
432 if (!dev || !dev->driver)
433 return sizeof(ROOT);
434
435 switch (dev->driver->id) {
436 case UCLASS_ROOT:
437 case UCLASS_SIMPLE_BUS:
438
439 return sizeof(ROOT);
440 case UCLASS_ETH:
441 return dp_size(dev->parent) +
442 sizeof(struct efi_device_path_mac_addr);
443#ifdef CONFIG_BLK
444 case UCLASS_BLK:
445 switch (dev->parent->uclass->uc_drv->id) {
446#ifdef CONFIG_IDE
447 case UCLASS_IDE:
448 return dp_size(dev->parent) +
449 sizeof(struct efi_device_path_atapi);
450#endif
451#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
452 case UCLASS_SCSI:
453 return dp_size(dev->parent) +
454 sizeof(struct efi_device_path_scsi);
455#endif
456#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
457 case UCLASS_MMC:
458 return dp_size(dev->parent) +
459 sizeof(struct efi_device_path_sd_mmc_path);
460#endif
461#if defined(CONFIG_AHCI) || defined(CONFIG_SATA)
462 case UCLASS_AHCI:
463 return dp_size(dev->parent) +
464 sizeof(struct efi_device_path_sata);
465#endif
466#if defined(CONFIG_NVME)
467 case UCLASS_NVME:
468 return dp_size(dev->parent) +
469 sizeof(struct efi_device_path_nvme);
470#endif
471#ifdef CONFIG_SANDBOX
472 case UCLASS_ROOT:
473
474
475
476
477
478 return dp_size(dev->parent)
479 + sizeof(struct efi_device_path_vendor) + 1;
480#endif
481#ifdef CONFIG_VIRTIO_BLK
482 case UCLASS_VIRTIO:
483
484
485
486
487
488 return dp_size(dev->parent)
489 + sizeof(struct efi_device_path_vendor) + 1;
490#endif
491 default:
492 return dp_size(dev->parent);
493 }
494#endif
495#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
496 case UCLASS_MMC:
497 return dp_size(dev->parent) +
498 sizeof(struct efi_device_path_sd_mmc_path);
499#endif
500 case UCLASS_MASS_STORAGE:
501 case UCLASS_USB_HUB:
502 return dp_size(dev->parent) +
503 sizeof(struct efi_device_path_usb_class);
504 default:
505
506 return dp_size(dev->parent);
507 }
508}
509
510
511
512
513
514
515
516
517__maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
518{
519 if (!dev || !dev->driver)
520 return buf;
521
522 switch (dev->driver->id) {
523 case UCLASS_ROOT:
524 case UCLASS_SIMPLE_BUS: {
525
526 struct efi_device_path_vendor *vdp = buf;
527 *vdp = ROOT;
528 return &vdp[1];
529 }
530#ifdef CONFIG_DM_ETH
531 case UCLASS_ETH: {
532 struct efi_device_path_mac_addr *dp =
533 dp_fill(buf, dev->parent);
534 struct eth_pdata *pdata = dev_get_plat(dev);
535
536 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
537 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
538 dp->dp.length = sizeof(*dp);
539 memset(&dp->mac, 0, sizeof(dp->mac));
540
541 memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
542
543 dp->if_type = 1;
544 return &dp[1];
545 }
546#endif
547#ifdef CONFIG_BLK
548 case UCLASS_BLK:
549 switch (dev->parent->uclass->uc_drv->id) {
550#ifdef CONFIG_SANDBOX
551 case UCLASS_ROOT: {
552
553 struct efi_device_path_vendor *dp;
554 struct blk_desc *desc = dev_get_uclass_plat(dev);
555
556 dp_fill(buf, dev->parent);
557 dp = buf;
558 ++dp;
559 dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
560 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
561 dp->dp.length = sizeof(*dp) + 1;
562 memcpy(&dp->guid, &efi_guid_host_dev,
563 sizeof(efi_guid_t));
564 dp->vendor_data[0] = desc->devnum;
565 return &dp->vendor_data[1];
566 }
567#endif
568#ifdef CONFIG_VIRTIO_BLK
569 case UCLASS_VIRTIO: {
570 struct efi_device_path_vendor *dp;
571 struct blk_desc *desc = dev_get_uclass_plat(dev);
572
573 dp_fill(buf, dev->parent);
574 dp = buf;
575 ++dp;
576 dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
577 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
578 dp->dp.length = sizeof(*dp) + 1;
579 memcpy(&dp->guid, &efi_guid_virtio_dev,
580 sizeof(efi_guid_t));
581 dp->vendor_data[0] = desc->devnum;
582 return &dp->vendor_data[1];
583 }
584#endif
585#ifdef CONFIG_IDE
586 case UCLASS_IDE: {
587 struct efi_device_path_atapi *dp =
588 dp_fill(buf, dev->parent);
589 struct blk_desc *desc = dev_get_uclass_plat(dev);
590
591 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
592 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
593 dp->dp.length = sizeof(*dp);
594 dp->logical_unit_number = desc->devnum;
595 dp->primary_secondary = IDE_BUS(desc->devnum);
596 dp->slave_master = desc->devnum %
597 (CONFIG_SYS_IDE_MAXDEVICE /
598 CONFIG_SYS_IDE_MAXBUS);
599 return &dp[1];
600 }
601#endif
602#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
603 case UCLASS_SCSI: {
604 struct efi_device_path_scsi *dp =
605 dp_fill(buf, dev->parent);
606 struct blk_desc *desc = dev_get_uclass_plat(dev);
607
608 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
609 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
610 dp->dp.length = sizeof(*dp);
611 dp->logical_unit_number = desc->lun;
612 dp->target_id = desc->target;
613 return &dp[1];
614 }
615#endif
616#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
617 case UCLASS_MMC: {
618 struct efi_device_path_sd_mmc_path *sddp =
619 dp_fill(buf, dev->parent);
620 struct blk_desc *desc = dev_get_uclass_plat(dev);
621
622 sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
623 sddp->dp.sub_type = is_sd(desc) ?
624 DEVICE_PATH_SUB_TYPE_MSG_SD :
625 DEVICE_PATH_SUB_TYPE_MSG_MMC;
626 sddp->dp.length = sizeof(*sddp);
627 sddp->slot_number = dev_seq(dev);
628 return &sddp[1];
629 }
630#endif
631#if defined(CONFIG_AHCI) || defined(CONFIG_SATA)
632 case UCLASS_AHCI: {
633 struct efi_device_path_sata *dp =
634 dp_fill(buf, dev->parent);
635 struct blk_desc *desc = dev_get_uclass_plat(dev);
636
637 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
638 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SATA;
639 dp->dp.length = sizeof(*dp);
640 dp->hba_port = desc->devnum;
641
642 dp->port_multiplier_port = 0xffff;
643 dp->logical_unit_number = desc->lun;
644 return &dp[1];
645 }
646#endif
647#if defined(CONFIG_NVME)
648 case UCLASS_NVME: {
649 struct efi_device_path_nvme *dp =
650 dp_fill(buf, dev->parent);
651 u32 ns_id;
652
653 dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
654 dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_NVME;
655 dp->dp.length = sizeof(*dp);
656 nvme_get_namespace_id(dev, &ns_id, dp->eui64);
657 memcpy(&dp->ns_id, &ns_id, sizeof(ns_id));
658 return &dp[1];
659 }
660#endif
661 default:
662 debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
663 __FILE__, __LINE__, __func__,
664 dev->name, dev->parent->uclass->uc_drv->id);
665 return dp_fill(buf, dev->parent);
666 }
667#endif
668#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
669 case UCLASS_MMC: {
670 struct efi_device_path_sd_mmc_path *sddp =
671 dp_fill(buf, dev->parent);
672 struct mmc *mmc = mmc_get_mmc_dev(dev);
673 struct blk_desc *desc = mmc_get_blk_desc(mmc);
674
675 sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
676 sddp->dp.sub_type = is_sd(desc) ?
677 DEVICE_PATH_SUB_TYPE_MSG_SD :
678 DEVICE_PATH_SUB_TYPE_MSG_MMC;
679 sddp->dp.length = sizeof(*sddp);
680 sddp->slot_number = dev_seq(dev);
681
682 return &sddp[1];
683 }
684#endif
685 case UCLASS_MASS_STORAGE:
686 case UCLASS_USB_HUB: {
687 struct efi_device_path_usb_class *udp =
688 dp_fill(buf, dev->parent);
689 struct usb_device *udev = dev_get_parent_priv(dev);
690 struct usb_device_descriptor *desc = &udev->descriptor;
691
692 udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
693 udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
694 udp->dp.length = sizeof(*udp);
695 udp->vendor_id = desc->idVendor;
696 udp->product_id = desc->idProduct;
697 udp->device_class = desc->bDeviceClass;
698 udp->device_subclass = desc->bDeviceSubClass;
699 udp->device_protocol = desc->bDeviceProtocol;
700
701 return &udp[1];
702 }
703 default:
704 debug("%s(%u) %s: unhandled device class: %s (%u)\n",
705 __FILE__, __LINE__, __func__,
706 dev->name, dev->driver->id);
707 return dp_fill(buf, dev->parent);
708 }
709}
710#endif
711
712static unsigned dp_part_size(struct blk_desc *desc, int part)
713{
714 unsigned dpsize;
715
716#ifdef CONFIG_BLK
717 {
718 struct udevice *dev;
719 int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
720
721 if (ret)
722 dev = desc->bdev->parent;
723 dpsize = dp_size(dev);
724 }
725#else
726 dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
727#endif
728
729 if (part == 0)
730 return dpsize;
731
732 if (desc->part_type == PART_TYPE_ISO)
733 dpsize += sizeof(struct efi_device_path_cdrom_path);
734 else
735 dpsize += sizeof(struct efi_device_path_hard_drive_path);
736
737 return dpsize;
738}
739
740
741
742
743
744
745
746
747static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
748{
749 struct disk_partition info;
750
751 part_get_info(desc, part, &info);
752
753 if (desc->part_type == PART_TYPE_ISO) {
754 struct efi_device_path_cdrom_path *cddp = buf;
755
756 cddp->boot_entry = part;
757 cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
758 cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
759 cddp->dp.length = sizeof(*cddp);
760 cddp->partition_start = info.start;
761 cddp->partition_size = info.size;
762
763 buf = &cddp[1];
764 } else {
765 struct efi_device_path_hard_drive_path *hddp = buf;
766
767 hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
768 hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
769 hddp->dp.length = sizeof(*hddp);
770 hddp->partition_number = part;
771 hddp->partition_start = info.start;
772 hddp->partition_end = info.size;
773 if (desc->part_type == PART_TYPE_EFI)
774 hddp->partmap_type = 2;
775 else
776 hddp->partmap_type = 1;
777
778 switch (desc->sig_type) {
779 case SIG_TYPE_NONE:
780 default:
781 hddp->signature_type = 0;
782 memset(hddp->partition_signature, 0,
783 sizeof(hddp->partition_signature));
784 break;
785 case SIG_TYPE_MBR:
786 hddp->signature_type = 1;
787 memset(hddp->partition_signature, 0,
788 sizeof(hddp->partition_signature));
789 memcpy(hddp->partition_signature, &desc->mbr_sig,
790 sizeof(desc->mbr_sig));
791 break;
792 case SIG_TYPE_GUID:
793 hddp->signature_type = 2;
794 memcpy(hddp->partition_signature, &desc->guid_sig,
795 sizeof(hddp->partition_signature));
796 break;
797 }
798
799 buf = &hddp[1];
800 }
801
802 return buf;
803}
804
805
806
807
808
809
810
811
812static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
813{
814#ifdef CONFIG_BLK
815 {
816 struct udevice *dev;
817 int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
818
819 if (ret)
820 dev = desc->bdev->parent;
821 buf = dp_fill(buf, dev);
822 }
823#else
824
825
826
827
828
829
830
831 struct efi_device_path_usb *udp;
832
833 memcpy(buf, &ROOT, sizeof(ROOT));
834 buf += sizeof(ROOT);
835
836 udp = buf;
837 udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
838 udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
839 udp->dp.length = sizeof(*udp);
840 udp->parent_port_number = desc->if_type;
841 udp->usb_interface = desc->devnum;
842 buf = &udp[1];
843#endif
844
845 if (part == 0)
846 return buf;
847
848 return dp_part_node(buf, desc, part);
849}
850
851
852struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
853{
854 void *buf, *start;
855
856 start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
857 if (!buf)
858 return NULL;
859
860 buf = dp_part_fill(buf, desc, part);
861
862 *((struct efi_device_path *)buf) = END;
863
864 return start;
865}
866
867
868
869
870
871
872
873
874struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
875{
876 efi_uintn_t dpsize;
877 void *buf;
878
879 if (desc->part_type == PART_TYPE_ISO)
880 dpsize = sizeof(struct efi_device_path_cdrom_path);
881 else
882 dpsize = sizeof(struct efi_device_path_hard_drive_path);
883 buf = dp_alloc(dpsize);
884
885 dp_part_node(buf, desc, part);
886
887 return buf;
888}
889
890
891
892
893
894
895
896
897
898
899static void path_to_uefi(void *uefi, const char *src)
900{
901 u16 *pos = uefi;
902
903
904
905
906
907
908 allow_unaligned();
909
910 while (*src) {
911 s32 code = utf8_get(&src);
912
913 if (code < 0)
914 code = '?';
915 else if (code == '/')
916 code = '\\';
917 utf16_put(code, &pos);
918 }
919 *pos = 0;
920}
921
922
923
924
925
926struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
927 const char *path)
928{
929 struct efi_device_path_file_path *fp;
930 void *buf, *start;
931 size_t dpsize = 0, fpsize;
932
933 if (desc)
934 dpsize = dp_part_size(desc, part);
935
936 fpsize = sizeof(struct efi_device_path) +
937 2 * (utf8_utf16_strlen(path) + 1);
938 if (fpsize > U16_MAX)
939 return NULL;
940
941 dpsize += fpsize;
942
943 start = buf = dp_alloc(dpsize + sizeof(END));
944 if (!buf)
945 return NULL;
946
947 if (desc)
948 buf = dp_part_fill(buf, desc, part);
949
950
951 fp = buf;
952 fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
953 fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
954 fp->dp.length = (u16)fpsize;
955 path_to_uefi(fp->str, path);
956 buf += fpsize;
957
958 *((struct efi_device_path *)buf) = END;
959
960 return start;
961}
962
963struct efi_device_path *efi_dp_from_uart(void)
964{
965 void *buf, *pos;
966 struct efi_device_path_uart *uart;
967 size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END);
968
969 buf = dp_alloc(dpsize);
970 if (!buf)
971 return NULL;
972 pos = buf;
973 memcpy(pos, &ROOT, sizeof(ROOT));
974 pos += sizeof(ROOT);
975 uart = pos;
976 uart->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
977 uart->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_UART;
978 uart->dp.length = sizeof(*uart);
979 pos += sizeof(*uart);
980 memcpy(pos, &END, sizeof(END));
981
982 return buf;
983}
984
985#ifdef CONFIG_NET
986struct efi_device_path *efi_dp_from_eth(void)
987{
988#ifndef CONFIG_DM_ETH
989 struct efi_device_path_mac_addr *ndp;
990#endif
991 void *buf, *start;
992 unsigned dpsize = 0;
993
994 assert(eth_get_dev());
995
996#ifdef CONFIG_DM_ETH
997 dpsize += dp_size(eth_get_dev());
998#else
999 dpsize += sizeof(ROOT);
1000 dpsize += sizeof(*ndp);
1001#endif
1002
1003 start = buf = dp_alloc(dpsize + sizeof(END));
1004 if (!buf)
1005 return NULL;
1006
1007#ifdef CONFIG_DM_ETH
1008 buf = dp_fill(buf, eth_get_dev());
1009#else
1010 memcpy(buf, &ROOT, sizeof(ROOT));
1011 buf += sizeof(ROOT);
1012
1013 ndp = buf;
1014 ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
1015 ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
1016 ndp->dp.length = sizeof(*ndp);
1017 ndp->if_type = 1;
1018 memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
1019 buf = &ndp[1];
1020#endif
1021
1022 *((struct efi_device_path *)buf) = END;
1023
1024 return start;
1025}
1026#endif
1027
1028
1029struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
1030 uint64_t start_address,
1031 uint64_t end_address)
1032{
1033 struct efi_device_path_memory *mdp;
1034 void *buf, *start;
1035
1036 start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
1037 if (!buf)
1038 return NULL;
1039
1040 mdp = buf;
1041 mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
1042 mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
1043 mdp->dp.length = sizeof(*mdp);
1044 mdp->memory_type = memory_type;
1045 mdp->start_address = start_address;
1046 mdp->end_address = end_address;
1047 buf = &mdp[1];
1048
1049 *((struct efi_device_path *)buf) = END;
1050
1051 return start;
1052}
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
1067 struct efi_device_path **device_path,
1068 struct efi_device_path **file_path)
1069{
1070 struct efi_device_path *p, *dp, *fp = NULL;
1071
1072 *device_path = NULL;
1073 *file_path = NULL;
1074 dp = efi_dp_dup(full_path);
1075 if (!dp)
1076 return EFI_OUT_OF_RESOURCES;
1077 p = dp;
1078 while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
1079 p = efi_dp_next(p);
1080 if (!p)
1081 goto out;
1082 }
1083 fp = efi_dp_dup(p);
1084 if (!fp)
1085 return EFI_OUT_OF_RESOURCES;
1086 p->type = DEVICE_PATH_TYPE_END;
1087 p->sub_type = DEVICE_PATH_SUB_TYPE_END;
1088 p->length = sizeof(*p);
1089
1090out:
1091 *device_path = dp;
1092 *file_path = fp;
1093 return EFI_SUCCESS;
1094}
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
1107 const char *path,
1108 struct efi_device_path **device,
1109 struct efi_device_path **file)
1110{
1111 struct blk_desc *desc = NULL;
1112 struct disk_partition fs_partition;
1113 int part = 0;
1114 char filename[32] = { 0 };
1115 char *s;
1116
1117 if (path && !file)
1118 return EFI_INVALID_PARAMETER;
1119
1120 if (!strcmp(dev, "Net")) {
1121#ifdef CONFIG_NET
1122 if (device)
1123 *device = efi_dp_from_eth();
1124#endif
1125 } else if (!strcmp(dev, "Uart")) {
1126 if (device)
1127 *device = efi_dp_from_uart();
1128 } else {
1129 part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
1130 1);
1131 if (part < 0 || !desc)
1132 return EFI_INVALID_PARAMETER;
1133
1134 if (device)
1135 *device = efi_dp_from_part(desc, part);
1136 }
1137
1138 if (!path)
1139 return EFI_SUCCESS;
1140
1141 snprintf(filename, sizeof(filename), "%s", path);
1142
1143 s = filename;
1144 while ((s = strchr(s, '/')))
1145 *s++ = '\\';
1146 *file = efi_dp_from_file(desc, part, filename);
1147
1148 if (!*file)
1149 return EFI_INVALID_PARAMETER;
1150
1151 return EFI_SUCCESS;
1152}
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165ssize_t efi_dp_check_length(const struct efi_device_path *dp,
1166 const size_t maxlen)
1167{
1168 ssize_t ret = 0;
1169 u16 len;
1170
1171 if (maxlen > SSIZE_MAX)
1172 return -EINVAL;
1173 for (;;) {
1174 len = dp->length;
1175 if (len < 4)
1176 return -1;
1177 ret += len;
1178 if (ret > maxlen)
1179 return -1;
1180 if (dp->type == DEVICE_PATH_TYPE_END &&
1181 dp->sub_type == DEVICE_PATH_SUB_TYPE_END)
1182 return ret;
1183 dp = (const struct efi_device_path *)((const u8 *)dp + len);
1184 }
1185}
1186