5b2ff813191cb2e27e9920433b93cfb363b3e103
[oweals/u-boot.git] / lib / efi_loader / efi_device_path.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * EFI device path from u-boot device-model mapping
4  *
5  * (C) Copyright 2017 Rob Clark
6  */
7
8 #include <common.h>
9 #include <blk.h>
10 #include <dm.h>
11 #include <net.h>
12 #include <usb.h>
13 #include <mmc.h>
14 #include <nvme.h>
15 #include <efi_loader.h>
16 #include <part.h>
17 #include <sandboxblockdev.h>
18 #include <asm-generic/unaligned.h>
19 #include <linux/compat.h> /* U16_MAX */
20
21 #ifdef CONFIG_SANDBOX
22 const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
23 #endif
24
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),
30 };
31
32 /* template ROOT node: */
33 static const struct efi_device_path_vendor ROOT = {
34         .dp = {
35                 .type     = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
36                 .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
37                 .length   = sizeof(ROOT),
38         },
39         .guid = U_BOOT_GUID,
40 };
41
42 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
43 /*
44  * Determine if an MMC device is an SD card.
45  *
46  * @desc        block device descriptor
47  * @return      true if the device is an SD card
48  */
49 static bool is_sd(struct blk_desc *desc)
50 {
51         struct mmc *mmc = find_mmc_device(desc->devnum);
52
53         if (!mmc)
54                 return false;
55
56         return IS_SD(mmc) != 0U;
57 }
58 #endif
59
60 static void *dp_alloc(size_t sz)
61 {
62         void *buf;
63
64         if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
65             EFI_SUCCESS) {
66                 debug("EFI: ERROR: out of memory in %s\n", __func__);
67                 return NULL;
68         }
69
70         memset(buf, 0, sz);
71         return buf;
72 }
73
74 /*
75  * Iterate to next block in device-path, terminating (returning NULL)
76  * at /End* node.
77  */
78 struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
79 {
80         if (dp == NULL)
81                 return NULL;
82         if (dp->type == DEVICE_PATH_TYPE_END)
83                 return NULL;
84         dp = ((void *)dp) + dp->length;
85         if (dp->type == DEVICE_PATH_TYPE_END)
86                 return NULL;
87         return (struct efi_device_path *)dp;
88 }
89
90 /*
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.
95  */
96 int efi_dp_match(const struct efi_device_path *a,
97                  const struct efi_device_path *b)
98 {
99         while (1) {
100                 int ret;
101
102                 ret = memcmp(&a->length, &b->length, sizeof(a->length));
103                 if (ret)
104                         return ret;
105
106                 ret = memcmp(a, b, a->length);
107                 if (ret)
108                         return ret;
109
110                 a = efi_dp_next(a);
111                 b = efi_dp_next(b);
112
113                 if (!a || !b)
114                         return 0;
115         }
116 }
117
118 /*
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
121  * hierarchy:
122  *
123  *   - MESSAGING:USB_WWID
124  *   - MESSAGING:USB_CLASS
125  *   - MEDIA:FILE_PATH
126  *   - MEDIA:HARD_DRIVE
127  *   - MESSAGING:URI
128  *
129  * See UEFI spec (section 3.1.2, about short-form device-paths)
130  */
131 static struct efi_device_path *shorten_path(struct efi_device_path *dp)
132 {
133         while (dp) {
134                 /*
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.
138                  */
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))
142                         return dp;
143
144                 dp = efi_dp_next(dp);
145         }
146
147         return dp;
148 }
149
150 static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
151                                    struct efi_device_path **rem)
152 {
153         struct efi_object *efiobj;
154         efi_uintn_t dp_size = efi_dp_instance_size(dp);
155
156         list_for_each_entry(efiobj, &efi_obj_list, link) {
157                 struct efi_handler *handler;
158                 struct efi_device_path *obj_dp;
159                 efi_status_t ret;
160
161                 ret = efi_search_protocol(efiobj,
162                                           &efi_guid_device_path, &handler);
163                 if (ret != EFI_SUCCESS)
164                         continue;
165                 obj_dp = handler->protocol_interface;
166
167                 do {
168                         if (efi_dp_match(dp, obj_dp) == 0) {
169                                 if (rem) {
170                                         /*
171                                          * Allow partial matches, but inform
172                                          * the caller.
173                                          */
174                                         *rem = ((void *)dp) +
175                                                 efi_dp_instance_size(obj_dp);
176                                         return efiobj;
177                                 } else {
178                                         /* Only return on exact matches */
179                                         if (efi_dp_instance_size(obj_dp) ==
180                                             dp_size)
181                                                 return efiobj;
182                                 }
183                         }
184
185                         obj_dp = shorten_path(efi_dp_next(obj_dp));
186                 } while (short_path && obj_dp);
187         }
188
189         return NULL;
190 }
191
192 /*
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.
195  */
196 struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
197                                    struct efi_device_path **rem)
198 {
199         struct efi_object *efiobj;
200
201         /* Search for an exact match first */
202         efiobj = find_obj(dp, false, NULL);
203
204         /* Then for a fuzzy match */
205         if (!efiobj)
206                 efiobj = find_obj(dp, false, rem);
207
208         /* And now for a fuzzy short match */
209         if (!efiobj)
210                 efiobj = find_obj(dp, true, rem);
211
212         return efiobj;
213 }
214
215 /*
216  * Determine the last device path node that is not the end node.
217  *
218  * @dp          device path
219  * @return      last node before the end node if it exists
220  *              otherwise NULL
221  */
222 const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
223 {
224         struct efi_device_path *ret;
225
226         if (!dp || dp->type == DEVICE_PATH_TYPE_END)
227                 return NULL;
228         while (dp) {
229                 ret = (struct efi_device_path *)dp;
230                 dp = efi_dp_next(dp);
231         }
232         return ret;
233 }
234
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)
237 {
238         efi_uintn_t sz = 0;
239
240         if (!dp || dp->type == DEVICE_PATH_TYPE_END)
241                 return 0;
242         while (dp) {
243                 sz += dp->length;
244                 dp = efi_dp_next(dp);
245         }
246
247         return sz;
248 }
249
250 /* get size of multi-instance device path excluding end node */
251 efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
252 {
253         const struct efi_device_path *p = dp;
254
255         if (!p)
256                 return 0;
257         while (p->type != DEVICE_PATH_TYPE_END ||
258                p->sub_type != DEVICE_PATH_SUB_TYPE_END)
259                 p = (void *)p + p->length;
260
261         return (void *)p - (void *)dp;
262 }
263
264 /* copy multi-instance device path */
265 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
266 {
267         struct efi_device_path *ndp;
268         size_t sz = efi_dp_size(dp) + sizeof(END);
269
270         if (!dp)
271                 return NULL;
272
273         ndp = dp_alloc(sz);
274         if (!ndp)
275                 return NULL;
276         memcpy(ndp, dp, sz);
277
278         return ndp;
279 }
280
281 struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
282                                       const struct efi_device_path *dp2)
283 {
284         struct efi_device_path *ret;
285
286         if (!dp1 && !dp2) {
287                 /* return an end node */
288                 ret = efi_dp_dup(&END);
289         } else if (!dp1) {
290                 ret = efi_dp_dup(dp2);
291         } else if (!dp2) {
292                 ret = efi_dp_dup(dp1);
293         } else {
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));
298                 if (!p)
299                         return NULL;
300                 memcpy(p, dp1, sz1);
301                 /* the end node of the second device path has to be retained */
302                 memcpy(p + sz1, dp2, sz2 + sizeof(END));
303                 ret = p;
304         }
305
306         return ret;
307 }
308
309 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
310                                            const struct efi_device_path *node)
311 {
312         struct efi_device_path *ret;
313
314         if (!node && !dp) {
315                 ret = efi_dp_dup(&END);
316         } else if (!node) {
317                 ret = efi_dp_dup(dp);
318         } else if (!dp) {
319                 size_t sz = node->length;
320                 void *p = dp_alloc(sz + sizeof(END));
321                 if (!p)
322                         return NULL;
323                 memcpy(p, node, sz);
324                 memcpy(p + sz, &END, sizeof(END));
325                 ret = p;
326         } else {
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));
330                 if (!p)
331                         return NULL;
332                 memcpy(p, dp, sz);
333                 memcpy(p + sz, node, node->length);
334                 memcpy(p + sz + node->length, &END, sizeof(END));
335                 ret = p;
336         }
337
338         return ret;
339 }
340
341 struct efi_device_path *efi_dp_create_device_node(const u8 type,
342                                                   const u8 sub_type,
343                                                   const u16 length)
344 {
345         struct efi_device_path *ret;
346
347         if (length < sizeof(struct efi_device_path))
348                 return NULL;
349
350         ret = dp_alloc(length);
351         if (!ret)
352                 return ret;
353         ret->type = type;
354         ret->sub_type = sub_type;
355         ret->length = length;
356         return ret;
357 }
358
359 struct efi_device_path *efi_dp_append_instance(
360                 const struct efi_device_path *dp,
361                 const struct efi_device_path *dpi)
362 {
363         size_t sz, szi;
364         struct efi_device_path *p, *ret;
365
366         if (!dpi)
367                 return NULL;
368         if (!dp)
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));
373         if (!p)
374                 return NULL;
375         ret = p;
376         memcpy(p, dp, sz + sizeof(END));
377         p = (void *)p + sz;
378         p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END;
379         p = (void *)p + sizeof(END);
380         memcpy(p, dpi, szi);
381         p = (void *)p + szi;
382         memcpy(p, &END, sizeof(END));
383         return ret;
384 }
385
386 struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
387                                                  efi_uintn_t *size)
388 {
389         size_t sz;
390         struct efi_device_path *p;
391
392         if (size)
393                 *size = 0;
394         if (!dp || !*dp)
395                 return NULL;
396         sz = efi_dp_instance_size(*dp);
397         p = dp_alloc(sz + sizeof(END));
398         if (!p)
399                 return NULL;
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);
404         else
405                 *dp = NULL;
406         if (size)
407                 *size = sz + sizeof(END);
408         return p;
409 }
410
411 bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
412 {
413         const struct efi_device_path *p = dp;
414
415         if (!p)
416                 return false;
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;
420 }
421
422 #ifdef CONFIG_DM
423 /* size of device-path not including END node for device and all parents
424  * up to the root device.
425  */
426 __maybe_unused static unsigned int dp_size(struct udevice *dev)
427 {
428         if (!dev || !dev->driver)
429                 return sizeof(ROOT);
430
431         switch (dev->driver->id) {
432         case UCLASS_ROOT:
433         case UCLASS_SIMPLE_BUS:
434                 /* stop traversing parents at this point: */
435                 return sizeof(ROOT);
436         case UCLASS_ETH:
437                 return dp_size(dev->parent) +
438                         sizeof(struct efi_device_path_mac_addr);
439 #ifdef CONFIG_BLK
440         case UCLASS_BLK:
441                 switch (dev->parent->uclass->uc_drv->id) {
442 #ifdef CONFIG_IDE
443                 case UCLASS_IDE:
444                         return dp_size(dev->parent) +
445                                 sizeof(struct efi_device_path_atapi);
446 #endif
447 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
448                 case UCLASS_SCSI:
449                         return dp_size(dev->parent) +
450                                 sizeof(struct efi_device_path_scsi);
451 #endif
452 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
453                 case UCLASS_MMC:
454                         return dp_size(dev->parent) +
455                                 sizeof(struct efi_device_path_sd_mmc_path);
456 #endif
457 #if defined(CONFIG_NVME)
458                 case UCLASS_NVME:
459                         return dp_size(dev->parent) +
460                                 sizeof(struct efi_device_path_nvme);
461 #endif
462 #ifdef CONFIG_SANDBOX
463                 case UCLASS_ROOT:
464                          /*
465                           * Sandbox's host device will be represented
466                           * as vendor device with extra one byte for
467                           * device number
468                           */
469                         return dp_size(dev->parent)
470                                 + sizeof(struct efi_device_path_vendor) + 1;
471 #endif
472                 default:
473                         return dp_size(dev->parent);
474                 }
475 #endif
476 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
477         case UCLASS_MMC:
478                 return dp_size(dev->parent) +
479                         sizeof(struct efi_device_path_sd_mmc_path);
480 #endif
481         case UCLASS_MASS_STORAGE:
482         case UCLASS_USB_HUB:
483                 return dp_size(dev->parent) +
484                         sizeof(struct efi_device_path_usb_class);
485         default:
486                 /* just skip over unknown classes: */
487                 return dp_size(dev->parent);
488         }
489 }
490
491 /*
492  * Recursively build a device path.
493  *
494  * @buf         pointer to the end of the device path
495  * @dev         device
496  * @return      pointer to the end of the device path
497  */
498 __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
499 {
500         if (!dev || !dev->driver)
501                 return buf;
502
503         switch (dev->driver->id) {
504         case UCLASS_ROOT:
505         case UCLASS_SIMPLE_BUS: {
506                 /* stop traversing parents at this point: */
507                 struct efi_device_path_vendor *vdp = buf;
508                 *vdp = ROOT;
509                 return &vdp[1];
510         }
511 #ifdef CONFIG_DM_ETH
512         case UCLASS_ETH: {
513                 struct efi_device_path_mac_addr *dp =
514                         dp_fill(buf, dev->parent);
515                 struct eth_pdata *pdata = dev->platdata;
516
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);
523                 /* Ethernet */
524                 dp->if_type = 1;
525                 return &dp[1];
526         }
527 #endif
528 #ifdef CONFIG_BLK
529         case UCLASS_BLK:
530                 switch (dev->parent->uclass->uc_drv->id) {
531 #ifdef CONFIG_SANDBOX
532                 case UCLASS_ROOT: {
533                         /* stop traversing parents at this point: */
534                         struct efi_device_path_vendor *dp;
535                         struct blk_desc *desc = dev_get_uclass_platdata(dev);
536
537                         dp_fill(buf, dev->parent);
538                         dp = buf;
539                         ++dp;
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,
544                                sizeof(efi_guid_t));
545                         dp->vendor_data[0] = desc->devnum;
546                         return &dp->vendor_data[1];
547                         }
548 #endif
549 #ifdef CONFIG_IDE
550                 case UCLASS_IDE: {
551                         struct efi_device_path_atapi *dp =
552                         dp_fill(buf, dev->parent);
553                         struct blk_desc *desc = dev_get_uclass_platdata(dev);
554
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);
563                         return &dp[1];
564                         }
565 #endif
566 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
567                 case UCLASS_SCSI: {
568                         struct efi_device_path_scsi *dp =
569                                 dp_fill(buf, dev->parent);
570                         struct blk_desc *desc = dev_get_uclass_platdata(dev);
571
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;
577                         return &dp[1];
578                         }
579 #endif
580 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
581                 case UCLASS_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);
585
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;
592                         return &sddp[1];
593                         }
594 #endif
595 #if defined(CONFIG_NVME)
596                 case UCLASS_NVME: {
597                         struct efi_device_path_nvme *dp =
598                                 dp_fill(buf, dev->parent);
599                         u32 ns_id;
600
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));
606                         return &dp[1];
607                         }
608 #endif
609                 default:
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);
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 mmc *mmc = mmc_get_mmc_dev(dev);
621                 struct blk_desc *desc = mmc_get_blk_desc(mmc);
622
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;
629
630                 return &sddp[1];
631         }
632 #endif
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;
639
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;
648
649                 return &udp[1];
650         }
651         default:
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);
656         }
657 }
658 #endif
659
660 static unsigned dp_part_size(struct blk_desc *desc, int part)
661 {
662         unsigned dpsize;
663
664 #ifdef CONFIG_BLK
665         {
666                 struct udevice *dev;
667                 int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
668
669                 if (ret)
670                         dev = desc->bdev->parent;
671                 dpsize = dp_size(dev);
672         }
673 #else
674         dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
675 #endif
676
677         if (part == 0) /* the actual disk, not a partition */
678                 return dpsize;
679
680         if (desc->part_type == PART_TYPE_ISO)
681                 dpsize += sizeof(struct efi_device_path_cdrom_path);
682         else
683                 dpsize += sizeof(struct efi_device_path_hard_drive_path);
684
685         return dpsize;
686 }
687
688 /*
689  * Create a device node for a block device partition.
690  *
691  * @buf         buffer to which the device path is written
692  * @desc        block device descriptor
693  * @part        partition number, 0 identifies a block device
694  */
695 static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
696 {
697         disk_partition_t info;
698
699         part_get_info(desc, part, &info);
700
701         if (desc->part_type == PART_TYPE_ISO) {
702                 struct efi_device_path_cdrom_path *cddp = buf;
703
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;
710
711                 buf = &cddp[1];
712         } else {
713                 struct efi_device_path_hard_drive_path *hddp = buf;
714
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;
723                 else
724                         hddp->partmap_type = 1;
725
726                 switch (desc->sig_type) {
727                 case SIG_TYPE_NONE:
728                 default:
729                         hddp->signature_type = 0;
730                         memset(hddp->partition_signature, 0,
731                                sizeof(hddp->partition_signature));
732                         break;
733                 case SIG_TYPE_MBR:
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));
739                         break;
740                 case SIG_TYPE_GUID:
741                         hddp->signature_type = 2;
742                         memcpy(hddp->partition_signature, &desc->guid_sig,
743                                sizeof(hddp->partition_signature));
744                         break;
745                 }
746
747                 buf = &hddp[1];
748         }
749
750         return buf;
751 }
752
753 /*
754  * Create a device path for a block device or one of its partitions.
755  *
756  * @buf         buffer to which the device path is written
757  * @desc        block device descriptor
758  * @part        partition number, 0 identifies a block device
759  */
760 static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
761 {
762 #ifdef CONFIG_BLK
763         {
764                 struct udevice *dev;
765                 int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
766
767                 if (ret)
768                         dev = desc->bdev->parent;
769                 buf = dp_fill(buf, dev);
770         }
771 #else
772         /*
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.
778          */
779         struct efi_device_path_usb *udp;
780
781         memcpy(buf, &ROOT, sizeof(ROOT));
782         buf += sizeof(ROOT);
783
784         udp = buf;
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;
790         buf = &udp[1];
791 #endif
792
793         if (part == 0) /* the actual disk, not a partition */
794                 return buf;
795
796         return dp_part_node(buf, desc, part);
797 }
798
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)
801 {
802         void *buf, *start;
803
804         start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
805         if (!buf)
806                 return NULL;
807
808         buf = dp_part_fill(buf, desc, part);
809
810         *((struct efi_device_path *)buf) = END;
811
812         return start;
813 }
814
815 /*
816  * Create a device node for a block device partition.
817  *
818  * @buf         buffer to which the device path is written
819  * @desc        block device descriptor
820  * @part        partition number, 0 identifies a block device
821  */
822 struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
823 {
824         efi_uintn_t dpsize;
825         void *buf;
826
827         if (desc->part_type == PART_TYPE_ISO)
828                 dpsize = sizeof(struct efi_device_path_cdrom_path);
829         else
830                 dpsize = sizeof(struct efi_device_path_hard_drive_path);
831         buf = dp_alloc(dpsize);
832
833         dp_part_node(buf, desc, part);
834
835         return buf;
836 }
837
838 /**
839  * path_to_uefi() - convert UTF-8 path to an UEFI style path
840  *
841  * Convert UTF-8 path to a UEFI style path (i.e. with backslashes as path
842  * separators and UTF-16).
843  *
844  * @src:        source buffer
845  * @uefi:       target buffer, possibly unaligned
846  */
847 static void path_to_uefi(void *uefi, const char *src)
848 {
849         u16 *pos = uefi;
850
851         /*
852          * efi_set_bootdev() calls this routine indirectly before the UEFI
853          * subsystem is initialized. So we cannot assume unaligned access to be
854          * enabled.
855          */
856         allow_unaligned();
857
858         while (*src) {
859                 s32 code = utf8_get(&src);
860
861                 if (code < 0)
862                         code = '?';
863                 else if (code == '/')
864                         code = '\\';
865                 utf16_put(code, &pos);
866         }
867         *pos = 0;
868 }
869
870 /*
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
873  */
874 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
875                 const char *path)
876 {
877         struct efi_device_path_file_path *fp;
878         void *buf, *start;
879         size_t dpsize = 0, fpsize;
880
881         if (desc)
882                 dpsize = dp_part_size(desc, part);
883
884         fpsize = sizeof(struct efi_device_path) +
885                  2 * (utf8_utf16_strlen(path) + 1);
886         if (fpsize > U16_MAX)
887                 return NULL;
888
889         dpsize += fpsize;
890
891         start = buf = dp_alloc(dpsize + sizeof(END));
892         if (!buf)
893                 return NULL;
894
895         if (desc)
896                 buf = dp_part_fill(buf, desc, part);
897
898         /* add file-path: */
899         fp = buf;
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);
904         buf += fpsize;
905
906         *((struct efi_device_path *)buf) = END;
907
908         return start;
909 }
910
911 #ifdef CONFIG_NET
912 struct efi_device_path *efi_dp_from_eth(void)
913 {
914 #ifndef CONFIG_DM_ETH
915         struct efi_device_path_mac_addr *ndp;
916 #endif
917         void *buf, *start;
918         unsigned dpsize = 0;
919
920         assert(eth_get_dev());
921
922 #ifdef CONFIG_DM_ETH
923         dpsize += dp_size(eth_get_dev());
924 #else
925         dpsize += sizeof(ROOT);
926         dpsize += sizeof(*ndp);
927 #endif
928
929         start = buf = dp_alloc(dpsize + sizeof(END));
930         if (!buf)
931                 return NULL;
932
933 #ifdef CONFIG_DM_ETH
934         buf = dp_fill(buf, eth_get_dev());
935 #else
936         memcpy(buf, &ROOT, sizeof(ROOT));
937         buf += sizeof(ROOT);
938
939         ndp = buf;
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);
945         buf = &ndp[1];
946 #endif
947
948         *((struct efi_device_path *)buf) = END;
949
950         return start;
951 }
952 #endif
953
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)
958 {
959         struct efi_device_path_memory *mdp;
960         void *buf, *start;
961
962         start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
963         if (!buf)
964                 return NULL;
965
966         mdp = buf;
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;
973         buf = &mdp[1];
974
975         *((struct efi_device_path *)buf) = END;
976
977         return start;
978 }
979
980 /**
981  * efi_dp_split_file_path() - split of relative file path from device path
982  *
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.
986  *
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
991  */
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)
995 {
996         struct efi_device_path *p, *dp, *fp = NULL;
997
998         *device_path = NULL;
999         *file_path = NULL;
1000         dp = efi_dp_dup(full_path);
1001         if (!dp)
1002                 return EFI_OUT_OF_RESOURCES;
1003         p = dp;
1004         while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
1005                 p = efi_dp_next(p);
1006                 if (!p)
1007                         goto out;
1008         }
1009         fp = efi_dp_dup(p);
1010         if (!fp)
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);
1015
1016 out:
1017         *device_path = dp;
1018         *file_path = fp;
1019         return EFI_SUCCESS;
1020 }
1021
1022 /**
1023  * efi_dp_from_name() - convert U-Boot device and file path to device path
1024  *
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
1031  */
1032 efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
1033                               const char *path,
1034                               struct efi_device_path **device,
1035                               struct efi_device_path **file)
1036 {
1037         int is_net;
1038         struct blk_desc *desc = NULL;
1039         disk_partition_t fs_partition;
1040         int part = 0;
1041         char filename[32] = { 0 }; /* dp->str is u16[32] long */
1042         char *s;
1043
1044         if (path && !file)
1045                 return EFI_INVALID_PARAMETER;
1046
1047         is_net = !strcmp(dev, "Net");
1048         if (!is_net) {
1049                 part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
1050                                                1);
1051                 if (part < 0 || !desc)
1052                         return EFI_INVALID_PARAMETER;
1053
1054                 if (device)
1055                         *device = efi_dp_from_part(desc, part);
1056         } else {
1057 #ifdef CONFIG_NET
1058                 if (device)
1059                         *device = efi_dp_from_eth();
1060 #endif
1061         }
1062
1063         if (!path)
1064                 return EFI_SUCCESS;
1065
1066         snprintf(filename, sizeof(filename), "%s", path);
1067         /* DOS style file path: */
1068         s = filename;
1069         while ((s = strchr(s, '/')))
1070                 *s++ = '\\';
1071         *file = efi_dp_from_file(is_net ? NULL : desc, part, filename);
1072
1073         if (!*file)
1074                 return EFI_INVALID_PARAMETER;
1075
1076         return EFI_SUCCESS;
1077 }