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 #define LOG_CATEGORY LOGL_ERR
9 
10 #include <common.h>
11 #include <blk.h>
12 #include <dm.h>
13 #include <usb.h>
14 #include <mmc.h>
15 #include <efi_loader.h>
16 #include <part.h>
17 
18 /* template END node: */
19 static const struct efi_device_path END = {
20 	.type     = DEVICE_PATH_TYPE_END,
21 	.sub_type = DEVICE_PATH_SUB_TYPE_END,
22 	.length   = sizeof(END),
23 };
24 
25 /* template ROOT node: */
26 static const struct efi_device_path_vendor ROOT = {
27 	.dp = {
28 		.type     = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
29 		.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
30 		.length   = sizeof(ROOT),
31 	},
32 	.guid = U_BOOT_GUID,
33 };
34 
35 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
36 /*
37  * Determine if an MMC device is an SD card.
38  *
39  * @desc	block device descriptor
40  * @return	true if the device is an SD card
41  */
42 static bool is_sd(struct blk_desc *desc)
43 {
44 	struct mmc *mmc = find_mmc_device(desc->devnum);
45 
46 	if (!mmc)
47 		return false;
48 
49 	return IS_SD(mmc) != 0U;
50 }
51 #endif
52 
53 static void *dp_alloc(size_t sz)
54 {
55 	void *buf;
56 
57 	if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
58 	    EFI_SUCCESS) {
59 		debug("EFI: ERROR: out of memory in %s\n", __func__);
60 		return NULL;
61 	}
62 
63 	memset(buf, 0, sz);
64 	return buf;
65 }
66 
67 /*
68  * Iterate to next block in device-path, terminating (returning NULL)
69  * at /End* node.
70  */
71 struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
72 {
73 	if (dp == NULL)
74 		return NULL;
75 	if (dp->type == DEVICE_PATH_TYPE_END)
76 		return NULL;
77 	dp = ((void *)dp) + dp->length;
78 	if (dp->type == DEVICE_PATH_TYPE_END)
79 		return NULL;
80 	return (struct efi_device_path *)dp;
81 }
82 
83 /*
84  * Compare two device-paths, stopping when the shorter of the two hits
85  * an End* node.  This is useful to, for example, compare a device-path
86  * representing a device with one representing a file on the device, or
87  * a device with a parent device.
88  */
89 int efi_dp_match(const struct efi_device_path *a,
90 		 const struct efi_device_path *b)
91 {
92 	while (1) {
93 		int ret;
94 
95 		ret = memcmp(&a->length, &b->length, sizeof(a->length));
96 		if (ret)
97 			return ret;
98 
99 		ret = memcmp(a, b, a->length);
100 		if (ret)
101 			return ret;
102 
103 		a = efi_dp_next(a);
104 		b = efi_dp_next(b);
105 
106 		if (!a || !b)
107 			return 0;
108 	}
109 }
110 
111 /*
112  * See UEFI spec (section 3.1.2, about short-form device-paths..
113  * tl;dr: we can have a device-path that starts with a USB WWID
114  * or USB Class node, and a few other cases which don't encode
115  * the full device path with bus hierarchy:
116  *
117  *   - MESSAGING:USB_WWID
118  *   - MESSAGING:USB_CLASS
119  *   - MEDIA:FILE_PATH
120  *   - MEDIA:HARD_DRIVE
121  *   - MESSAGING:URI
122  */
123 static struct efi_device_path *shorten_path(struct efi_device_path *dp)
124 {
125 	while (dp) {
126 		/*
127 		 * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI..
128 		 * in practice fallback.efi just uses MEDIA:HARD_DRIVE
129 		 * so not sure when we would see these other cases.
130 		 */
131 		if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
132 		    EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
133 		    EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
134 			return dp;
135 
136 		dp = efi_dp_next(dp);
137 	}
138 
139 	return dp;
140 }
141 
142 static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
143 				   struct efi_device_path **rem)
144 {
145 	struct efi_object *efiobj;
146 	efi_uintn_t dp_size = efi_dp_instance_size(dp);
147 
148 	list_for_each_entry(efiobj, &efi_obj_list, link) {
149 		struct efi_handler *handler;
150 		struct efi_device_path *obj_dp;
151 		efi_status_t ret;
152 
153 		ret = efi_search_protocol(efiobj->handle,
154 					  &efi_guid_device_path, &handler);
155 		if (ret != EFI_SUCCESS)
156 			continue;
157 		obj_dp = handler->protocol_interface;
158 
159 		do {
160 			if (efi_dp_match(dp, obj_dp) == 0) {
161 				if (rem) {
162 					/*
163 					 * Allow partial matches, but inform
164 					 * the caller.
165 					 */
166 					*rem = ((void *)dp) +
167 						efi_dp_instance_size(obj_dp);
168 					return efiobj;
169 				} else {
170 					/* Only return on exact matches */
171 					if (efi_dp_instance_size(obj_dp) ==
172 					    dp_size)
173 						return efiobj;
174 				}
175 			}
176 
177 			obj_dp = shorten_path(efi_dp_next(obj_dp));
178 		} while (short_path && obj_dp);
179 	}
180 
181 	return NULL;
182 }
183 
184 /*
185  * Find an efiobj from device-path, if 'rem' is not NULL, returns the
186  * remaining part of the device path after the matched object.
187  */
188 struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
189 				   struct efi_device_path **rem)
190 {
191 	struct efi_object *efiobj;
192 
193 	/* Search for an exact match first */
194 	efiobj = find_obj(dp, false, NULL);
195 
196 	/* Then for a fuzzy match */
197 	if (!efiobj)
198 		efiobj = find_obj(dp, false, rem);
199 
200 	/* And now for a fuzzy short match */
201 	if (!efiobj)
202 		efiobj = find_obj(dp, true, rem);
203 
204 	return efiobj;
205 }
206 
207 /*
208  * Determine the last device path node that is not the end node.
209  *
210  * @dp		device path
211  * @return	last node before the end node if it exists
212  *		otherwise NULL
213  */
214 const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
215 {
216 	struct efi_device_path *ret;
217 
218 	if (!dp || dp->type == DEVICE_PATH_TYPE_END)
219 		return NULL;
220 	while (dp) {
221 		ret = (struct efi_device_path *)dp;
222 		dp = efi_dp_next(dp);
223 	}
224 	return ret;
225 }
226 
227 /* get size of the first device path instance excluding end node */
228 efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
229 {
230 	efi_uintn_t sz = 0;
231 
232 	if (!dp || dp->type == DEVICE_PATH_TYPE_END)
233 		return 0;
234 	while (dp) {
235 		sz += dp->length;
236 		dp = efi_dp_next(dp);
237 	}
238 
239 	return sz;
240 }
241 
242 /* get size of multi-instance device path excluding end node */
243 efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
244 {
245 	const struct efi_device_path *p = dp;
246 
247 	if (!p)
248 		return 0;
249 	while (p->type != DEVICE_PATH_TYPE_END ||
250 	       p->sub_type != DEVICE_PATH_SUB_TYPE_END)
251 		p = (void *)p + p->length;
252 
253 	return (void *)p - (void *)dp;
254 }
255 
256 /* copy multi-instance device path */
257 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
258 {
259 	struct efi_device_path *ndp;
260 	size_t sz = efi_dp_size(dp) + sizeof(END);
261 
262 	if (!dp)
263 		return NULL;
264 
265 	ndp = dp_alloc(sz);
266 	if (!ndp)
267 		return NULL;
268 	memcpy(ndp, dp, sz);
269 
270 	return ndp;
271 }
272 
273 struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
274 				      const struct efi_device_path *dp2)
275 {
276 	struct efi_device_path *ret;
277 
278 	if (!dp1 && !dp2) {
279 		/* return an end node */
280 		ret = efi_dp_dup(&END);
281 	} else if (!dp1) {
282 		ret = efi_dp_dup(dp2);
283 	} else if (!dp2) {
284 		ret = efi_dp_dup(dp1);
285 	} else {
286 		/* both dp1 and dp2 are non-null */
287 		unsigned sz1 = efi_dp_size(dp1);
288 		unsigned sz2 = efi_dp_size(dp2);
289 		void *p = dp_alloc(sz1 + sz2 + sizeof(END));
290 		if (!p)
291 			return NULL;
292 		memcpy(p, dp1, sz1);
293 		/* the end node of the second device path has to be retained */
294 		memcpy(p + sz1, dp2, sz2 + sizeof(END));
295 		ret = p;
296 	}
297 
298 	return ret;
299 }
300 
301 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
302 					   const struct efi_device_path *node)
303 {
304 	struct efi_device_path *ret;
305 
306 	if (!node && !dp) {
307 		ret = efi_dp_dup(&END);
308 	} else if (!node) {
309 		ret = efi_dp_dup(dp);
310 	} else if (!dp) {
311 		size_t sz = node->length;
312 		void *p = dp_alloc(sz + sizeof(END));
313 		if (!p)
314 			return NULL;
315 		memcpy(p, node, sz);
316 		memcpy(p + sz, &END, sizeof(END));
317 		ret = p;
318 	} else {
319 		/* both dp and node are non-null */
320 		size_t sz = efi_dp_size(dp);
321 		void *p = dp_alloc(sz + node->length + sizeof(END));
322 		if (!p)
323 			return NULL;
324 		memcpy(p, dp, sz);
325 		memcpy(p + sz, node, node->length);
326 		memcpy(p + sz + node->length, &END, sizeof(END));
327 		ret = p;
328 	}
329 
330 	return ret;
331 }
332 
333 struct efi_device_path *efi_dp_create_device_node(const u8 type,
334 						  const u8 sub_type,
335 						  const u16 length)
336 {
337 	struct efi_device_path *ret;
338 
339 	ret = dp_alloc(length);
340 	if (!ret)
341 		return ret;
342 	ret->type = type;
343 	ret->sub_type = sub_type;
344 	ret->length = length;
345 	return ret;
346 }
347 
348 struct efi_device_path *efi_dp_append_instance(
349 		const struct efi_device_path *dp,
350 		const struct efi_device_path *dpi)
351 {
352 	size_t sz, szi;
353 	struct efi_device_path *p, *ret;
354 
355 	if (!dpi)
356 		return NULL;
357 	if (!dp)
358 		return efi_dp_dup(dpi);
359 	sz = efi_dp_size(dp);
360 	szi = efi_dp_instance_size(dpi);
361 	p = dp_alloc(sz + szi + 2 * sizeof(END));
362 	if (!p)
363 		return NULL;
364 	ret = p;
365 	memcpy(p, dp, sz + sizeof(END));
366 	p = (void *)p + sz;
367 	p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END;
368 	p = (void *)p + sizeof(END);
369 	memcpy(p, dpi, szi);
370 	p = (void *)p + szi;
371 	memcpy(p, &END, sizeof(END));
372 	return ret;
373 }
374 
375 struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
376 						 efi_uintn_t *size)
377 {
378 	size_t sz;
379 	struct efi_device_path *p;
380 
381 	if (size)
382 		*size = 0;
383 	if (!dp || !*dp)
384 		return NULL;
385 	p = *dp;
386 	sz = efi_dp_instance_size(*dp);
387 	p = dp_alloc(sz + sizeof(END));
388 	if (!p)
389 		return NULL;
390 	memcpy(p, *dp, sz + sizeof(END));
391 	*dp = (void *)*dp + sz;
392 	if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END)
393 		*dp = (void *)*dp + sizeof(END);
394 	else
395 		*dp = NULL;
396 	if (size)
397 		*size = sz + sizeof(END);
398 	return p;
399 }
400 
401 bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
402 {
403 	const struct efi_device_path *p = dp;
404 
405 	if (!p)
406 		return false;
407 	while (p->type != DEVICE_PATH_TYPE_END)
408 		p = (void *)p + p->length;
409 	return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END;
410 }
411 
412 #ifdef CONFIG_DM
413 /* size of device-path not including END node for device and all parents
414  * up to the root device.
415  */
416 static unsigned dp_size(struct udevice *dev)
417 {
418 	if (!dev || !dev->driver)
419 		return sizeof(ROOT);
420 
421 	switch (dev->driver->id) {
422 	case UCLASS_ROOT:
423 	case UCLASS_SIMPLE_BUS:
424 		/* stop traversing parents at this point: */
425 		return sizeof(ROOT);
426 	case UCLASS_ETH:
427 		return dp_size(dev->parent) +
428 			sizeof(struct efi_device_path_mac_addr);
429 #ifdef CONFIG_BLK
430 	case UCLASS_BLK:
431 		switch (dev->parent->uclass->uc_drv->id) {
432 #ifdef CONFIG_IDE
433 		case UCLASS_IDE:
434 			return dp_size(dev->parent) +
435 				sizeof(struct efi_device_path_atapi);
436 #endif
437 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
438 		case UCLASS_SCSI:
439 			return dp_size(dev->parent) +
440 				sizeof(struct efi_device_path_scsi);
441 #endif
442 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
443 		case UCLASS_MMC:
444 			return dp_size(dev->parent) +
445 				sizeof(struct efi_device_path_sd_mmc_path);
446 #endif
447 		default:
448 			return dp_size(dev->parent);
449 		}
450 #endif
451 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
452 	case UCLASS_MMC:
453 		return dp_size(dev->parent) +
454 			sizeof(struct efi_device_path_sd_mmc_path);
455 #endif
456 	case UCLASS_MASS_STORAGE:
457 	case UCLASS_USB_HUB:
458 		return dp_size(dev->parent) +
459 			sizeof(struct efi_device_path_usb_class);
460 	default:
461 		/* just skip over unknown classes: */
462 		return dp_size(dev->parent);
463 	}
464 }
465 
466 /*
467  * Recursively build a device path.
468  *
469  * @buf		pointer to the end of the device path
470  * @dev		device
471  * @return	pointer to the end of the device path
472  */
473 static void *dp_fill(void *buf, struct udevice *dev)
474 {
475 	if (!dev || !dev->driver)
476 		return buf;
477 
478 	switch (dev->driver->id) {
479 	case UCLASS_ROOT:
480 	case UCLASS_SIMPLE_BUS: {
481 		/* stop traversing parents at this point: */
482 		struct efi_device_path_vendor *vdp = buf;
483 		*vdp = ROOT;
484 		return &vdp[1];
485 	}
486 #ifdef CONFIG_DM_ETH
487 	case UCLASS_ETH: {
488 		struct efi_device_path_mac_addr *dp =
489 			dp_fill(buf, dev->parent);
490 		struct eth_pdata *pdata = dev->platdata;
491 
492 		dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
493 		dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
494 		dp->dp.length = sizeof(*dp);
495 		memset(&dp->mac, 0, sizeof(dp->mac));
496 		/* We only support IPv4 */
497 		memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
498 		/* Ethernet */
499 		dp->if_type = 1;
500 		return &dp[1];
501 	}
502 #endif
503 #ifdef CONFIG_BLK
504 	case UCLASS_BLK:
505 		switch (dev->parent->uclass->uc_drv->id) {
506 #ifdef CONFIG_IDE
507 		case UCLASS_IDE: {
508 			struct efi_device_path_atapi *dp =
509 			dp_fill(buf, dev->parent);
510 			struct blk_desc *desc = dev_get_uclass_platdata(dev);
511 
512 			dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
513 			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
514 			dp->dp.length = sizeof(*dp);
515 			dp->logical_unit_number = desc->devnum;
516 			dp->primary_secondary = IDE_BUS(desc->devnum);
517 			dp->slave_master = desc->devnum %
518 				(CONFIG_SYS_IDE_MAXDEVICE /
519 				 CONFIG_SYS_IDE_MAXBUS);
520 			return &dp[1];
521 			}
522 #endif
523 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
524 		case UCLASS_SCSI: {
525 			struct efi_device_path_scsi *dp =
526 				dp_fill(buf, dev->parent);
527 			struct blk_desc *desc = dev_get_uclass_platdata(dev);
528 
529 			dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
530 			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
531 			dp->dp.length = sizeof(*dp);
532 			dp->logical_unit_number = desc->lun;
533 			dp->target_id = desc->target;
534 			return &dp[1];
535 			}
536 #endif
537 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
538 		case UCLASS_MMC: {
539 			struct efi_device_path_sd_mmc_path *sddp =
540 				dp_fill(buf, dev->parent);
541 			struct blk_desc *desc = dev_get_uclass_platdata(dev);
542 
543 			sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
544 			sddp->dp.sub_type = is_sd(desc) ?
545 				DEVICE_PATH_SUB_TYPE_MSG_SD :
546 				DEVICE_PATH_SUB_TYPE_MSG_MMC;
547 			sddp->dp.length   = sizeof(*sddp);
548 			sddp->slot_number = dev->seq;
549 			return &sddp[1];
550 			}
551 #endif
552 		default:
553 			debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
554 			      __FILE__, __LINE__, __func__,
555 			      dev->name, dev->parent->uclass->uc_drv->id);
556 			return dp_fill(buf, dev->parent);
557 		}
558 #endif
559 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
560 	case UCLASS_MMC: {
561 		struct efi_device_path_sd_mmc_path *sddp =
562 			dp_fill(buf, dev->parent);
563 		struct mmc *mmc = mmc_get_mmc_dev(dev);
564 		struct blk_desc *desc = mmc_get_blk_desc(mmc);
565 
566 		sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
567 		sddp->dp.sub_type = is_sd(desc) ?
568 			DEVICE_PATH_SUB_TYPE_MSG_SD :
569 			DEVICE_PATH_SUB_TYPE_MSG_MMC;
570 		sddp->dp.length   = sizeof(*sddp);
571 		sddp->slot_number = dev->seq;
572 
573 		return &sddp[1];
574 	}
575 #endif
576 	case UCLASS_MASS_STORAGE:
577 	case UCLASS_USB_HUB: {
578 		struct efi_device_path_usb_class *udp =
579 			dp_fill(buf, dev->parent);
580 		struct usb_device *udev = dev_get_parent_priv(dev);
581 		struct usb_device_descriptor *desc = &udev->descriptor;
582 
583 		udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
584 		udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
585 		udp->dp.length   = sizeof(*udp);
586 		udp->vendor_id   = desc->idVendor;
587 		udp->product_id  = desc->idProduct;
588 		udp->device_class    = desc->bDeviceClass;
589 		udp->device_subclass = desc->bDeviceSubClass;
590 		udp->device_protocol = desc->bDeviceProtocol;
591 
592 		return &udp[1];
593 	}
594 	default:
595 		debug("%s(%u) %s: unhandled device class: %s (%u)\n",
596 		      __FILE__, __LINE__, __func__,
597 		      dev->name, dev->driver->id);
598 		return dp_fill(buf, dev->parent);
599 	}
600 }
601 
602 /* Construct a device-path from a device: */
603 struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
604 {
605 	void *buf, *start;
606 
607 	start = buf = dp_alloc(dp_size(dev) + sizeof(END));
608 	if (!buf)
609 		return NULL;
610 	buf = dp_fill(buf, dev);
611 	*((struct efi_device_path *)buf) = END;
612 
613 	return start;
614 }
615 #endif
616 
617 static unsigned dp_part_size(struct blk_desc *desc, int part)
618 {
619 	unsigned dpsize;
620 
621 #ifdef CONFIG_BLK
622 	{
623 		struct udevice *dev;
624 		int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
625 
626 		if (ret)
627 			dev = desc->bdev->parent;
628 		dpsize = dp_size(dev);
629 	}
630 #else
631 	dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
632 #endif
633 
634 	if (part == 0) /* the actual disk, not a partition */
635 		return dpsize;
636 
637 	if (desc->part_type == PART_TYPE_ISO)
638 		dpsize += sizeof(struct efi_device_path_cdrom_path);
639 	else
640 		dpsize += sizeof(struct efi_device_path_hard_drive_path);
641 
642 	return dpsize;
643 }
644 
645 /*
646  * Create a device node for a block device partition.
647  *
648  * @buf		buffer to which the device path is wirtten
649  * @desc	block device descriptor
650  * @part	partition number, 0 identifies a block device
651  */
652 static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
653 {
654 	disk_partition_t info;
655 
656 	part_get_info(desc, part, &info);
657 
658 	if (desc->part_type == PART_TYPE_ISO) {
659 		struct efi_device_path_cdrom_path *cddp = buf;
660 
661 		cddp->boot_entry = part;
662 		cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
663 		cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
664 		cddp->dp.length = sizeof(*cddp);
665 		cddp->partition_start = info.start;
666 		cddp->partition_end = info.size;
667 
668 		buf = &cddp[1];
669 	} else {
670 		struct efi_device_path_hard_drive_path *hddp = buf;
671 
672 		hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
673 		hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
674 		hddp->dp.length = sizeof(*hddp);
675 		hddp->partition_number = part;
676 		hddp->partition_start = info.start;
677 		hddp->partition_end = info.size;
678 		if (desc->part_type == PART_TYPE_EFI)
679 			hddp->partmap_type = 2;
680 		else
681 			hddp->partmap_type = 1;
682 
683 		switch (desc->sig_type) {
684 		case SIG_TYPE_NONE:
685 		default:
686 			hddp->signature_type = 0;
687 			memset(hddp->partition_signature, 0,
688 			       sizeof(hddp->partition_signature));
689 			break;
690 		case SIG_TYPE_MBR:
691 			hddp->signature_type = 1;
692 			memset(hddp->partition_signature, 0,
693 			       sizeof(hddp->partition_signature));
694 			memcpy(hddp->partition_signature, &desc->mbr_sig,
695 			       sizeof(desc->mbr_sig));
696 			break;
697 		case SIG_TYPE_GUID:
698 			hddp->signature_type = 2;
699 			memcpy(hddp->partition_signature, &desc->guid_sig,
700 			       sizeof(hddp->partition_signature));
701 			break;
702 		}
703 
704 		buf = &hddp[1];
705 	}
706 
707 	return buf;
708 }
709 
710 /*
711  * Create a device path for a block device or one of its partitions.
712  *
713  * @buf		buffer to which the device path is wirtten
714  * @desc	block device descriptor
715  * @part	partition number, 0 identifies a block device
716  */
717 static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
718 {
719 #ifdef CONFIG_BLK
720 	{
721 		struct udevice *dev;
722 		int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
723 
724 		if (ret)
725 			dev = desc->bdev->parent;
726 		buf = dp_fill(buf, dev);
727 	}
728 #else
729 	/*
730 	 * We *could* make a more accurate path, by looking at if_type
731 	 * and handling all the different cases like we do for non-
732 	 * legacy (ie CONFIG_BLK=y) case.  But most important thing
733 	 * is just to have a unique device-path for if_type+devnum.
734 	 * So map things to a fictitious USB device.
735 	 */
736 	struct efi_device_path_usb *udp;
737 
738 	memcpy(buf, &ROOT, sizeof(ROOT));
739 	buf += sizeof(ROOT);
740 
741 	udp = buf;
742 	udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
743 	udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
744 	udp->dp.length = sizeof(*udp);
745 	udp->parent_port_number = desc->if_type;
746 	udp->usb_interface = desc->devnum;
747 	buf = &udp[1];
748 #endif
749 
750 	if (part == 0) /* the actual disk, not a partition */
751 		return buf;
752 
753 	return dp_part_node(buf, desc, part);
754 }
755 
756 /* Construct a device-path from a partition on a blk device: */
757 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
758 {
759 	void *buf, *start;
760 
761 	start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
762 	if (!buf)
763 		return NULL;
764 
765 	buf = dp_part_fill(buf, desc, part);
766 
767 	*((struct efi_device_path *)buf) = END;
768 
769 	return start;
770 }
771 
772 /*
773  * Create a device node for a block device partition.
774  *
775  * @buf		buffer to which the device path is wirtten
776  * @desc	block device descriptor
777  * @part	partition number, 0 identifies a block device
778  */
779 struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
780 {
781 	efi_uintn_t dpsize;
782 	void *buf;
783 
784 	if (desc->part_type == PART_TYPE_ISO)
785 		dpsize = sizeof(struct efi_device_path_cdrom_path);
786 	else
787 		dpsize = sizeof(struct efi_device_path_hard_drive_path);
788 	buf = dp_alloc(dpsize);
789 
790 	dp_part_node(buf, desc, part);
791 
792 	return buf;
793 }
794 
795 /* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
796 static void path_to_uefi(u16 *uefi, const char *path)
797 {
798 	while (*path) {
799 		char c = *(path++);
800 		if (c == '/')
801 			c = '\\';
802 		*(uefi++) = c;
803 	}
804 	*uefi = '\0';
805 }
806 
807 /*
808  * If desc is NULL, this creates a path with only the file component,
809  * otherwise it creates a full path with both device and file components
810  */
811 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
812 		const char *path)
813 {
814 	struct efi_device_path_file_path *fp;
815 	void *buf, *start;
816 	unsigned dpsize = 0, fpsize;
817 
818 	if (desc)
819 		dpsize = dp_part_size(desc, part);
820 
821 	fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1);
822 	dpsize += fpsize;
823 
824 	start = buf = dp_alloc(dpsize + sizeof(END));
825 	if (!buf)
826 		return NULL;
827 
828 	if (desc)
829 		buf = dp_part_fill(buf, desc, part);
830 
831 	/* add file-path: */
832 	fp = buf;
833 	fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
834 	fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
835 	fp->dp.length = fpsize;
836 	path_to_uefi(fp->str, path);
837 	buf += fpsize;
838 
839 	*((struct efi_device_path *)buf) = END;
840 
841 	return start;
842 }
843 
844 #ifdef CONFIG_NET
845 struct efi_device_path *efi_dp_from_eth(void)
846 {
847 #ifndef CONFIG_DM_ETH
848 	struct efi_device_path_mac_addr *ndp;
849 #endif
850 	void *buf, *start;
851 	unsigned dpsize = 0;
852 
853 	assert(eth_get_dev());
854 
855 #ifdef CONFIG_DM_ETH
856 	dpsize += dp_size(eth_get_dev());
857 #else
858 	dpsize += sizeof(ROOT);
859 	dpsize += sizeof(*ndp);
860 #endif
861 
862 	start = buf = dp_alloc(dpsize + sizeof(END));
863 	if (!buf)
864 		return NULL;
865 
866 #ifdef CONFIG_DM_ETH
867 	buf = dp_fill(buf, eth_get_dev());
868 #else
869 	memcpy(buf, &ROOT, sizeof(ROOT));
870 	buf += sizeof(ROOT);
871 
872 	ndp = buf;
873 	ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
874 	ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
875 	ndp->dp.length = sizeof(*ndp);
876 	ndp->if_type = 1; /* Ethernet */
877 	memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
878 	buf = &ndp[1];
879 #endif
880 
881 	*((struct efi_device_path *)buf) = END;
882 
883 	return start;
884 }
885 #endif
886 
887 /* Construct a device-path for memory-mapped image */
888 struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
889 					uint64_t start_address,
890 					uint64_t end_address)
891 {
892 	struct efi_device_path_memory *mdp;
893 	void *buf, *start;
894 
895 	start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
896 	if (!buf)
897 		return NULL;
898 
899 	mdp = buf;
900 	mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
901 	mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
902 	mdp->dp.length = sizeof(*mdp);
903 	mdp->memory_type = memory_type;
904 	mdp->start_address = start_address;
905 	mdp->end_address = end_address;
906 	buf = &mdp[1];
907 
908 	*((struct efi_device_path *)buf) = END;
909 
910 	return start;
911 }
912 
913 /*
914  * Helper to split a full device path (containing both device and file
915  * parts) into it's constituent parts.
916  */
917 efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
918 				    struct efi_device_path **device_path,
919 				    struct efi_device_path **file_path)
920 {
921 	struct efi_device_path *p, *dp, *fp;
922 
923 	*device_path = NULL;
924 	*file_path = NULL;
925 	dp = efi_dp_dup(full_path);
926 	if (!dp)
927 		return EFI_OUT_OF_RESOURCES;
928 	p = dp;
929 	while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
930 		p = efi_dp_next(p);
931 		if (!p)
932 			return EFI_OUT_OF_RESOURCES;
933 	}
934 	fp = efi_dp_dup(p);
935 	if (!fp)
936 		return EFI_OUT_OF_RESOURCES;
937 	p->type = DEVICE_PATH_TYPE_END;
938 	p->sub_type = DEVICE_PATH_SUB_TYPE_END;
939 	p->length = sizeof(*p);
940 
941 	*device_path = dp;
942 	*file_path = fp;
943 	return EFI_SUCCESS;
944 }
945