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 	sz = efi_dp_instance_size(*dp);
386 	p = dp_alloc(sz + sizeof(END));
387 	if (!p)
388 		return NULL;
389 	memcpy(p, *dp, sz + sizeof(END));
390 	*dp = (void *)*dp + sz;
391 	if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END)
392 		*dp = (void *)*dp + sizeof(END);
393 	else
394 		*dp = NULL;
395 	if (size)
396 		*size = sz + sizeof(END);
397 	return p;
398 }
399 
400 bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
401 {
402 	const struct efi_device_path *p = dp;
403 
404 	if (!p)
405 		return false;
406 	while (p->type != DEVICE_PATH_TYPE_END)
407 		p = (void *)p + p->length;
408 	return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END;
409 }
410 
411 #ifdef CONFIG_DM
412 /* size of device-path not including END node for device and all parents
413  * up to the root device.
414  */
415 static unsigned dp_size(struct udevice *dev)
416 {
417 	if (!dev || !dev->driver)
418 		return sizeof(ROOT);
419 
420 	switch (dev->driver->id) {
421 	case UCLASS_ROOT:
422 	case UCLASS_SIMPLE_BUS:
423 		/* stop traversing parents at this point: */
424 		return sizeof(ROOT);
425 	case UCLASS_ETH:
426 		return dp_size(dev->parent) +
427 			sizeof(struct efi_device_path_mac_addr);
428 #ifdef CONFIG_BLK
429 	case UCLASS_BLK:
430 		switch (dev->parent->uclass->uc_drv->id) {
431 #ifdef CONFIG_IDE
432 		case UCLASS_IDE:
433 			return dp_size(dev->parent) +
434 				sizeof(struct efi_device_path_atapi);
435 #endif
436 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
437 		case UCLASS_SCSI:
438 			return dp_size(dev->parent) +
439 				sizeof(struct efi_device_path_scsi);
440 #endif
441 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
442 		case UCLASS_MMC:
443 			return dp_size(dev->parent) +
444 				sizeof(struct efi_device_path_sd_mmc_path);
445 #endif
446 		default:
447 			return dp_size(dev->parent);
448 		}
449 #endif
450 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
451 	case UCLASS_MMC:
452 		return dp_size(dev->parent) +
453 			sizeof(struct efi_device_path_sd_mmc_path);
454 #endif
455 	case UCLASS_MASS_STORAGE:
456 	case UCLASS_USB_HUB:
457 		return dp_size(dev->parent) +
458 			sizeof(struct efi_device_path_usb_class);
459 	default:
460 		/* just skip over unknown classes: */
461 		return dp_size(dev->parent);
462 	}
463 }
464 
465 /*
466  * Recursively build a device path.
467  *
468  * @buf		pointer to the end of the device path
469  * @dev		device
470  * @return	pointer to the end of the device path
471  */
472 static void *dp_fill(void *buf, struct udevice *dev)
473 {
474 	if (!dev || !dev->driver)
475 		return buf;
476 
477 	switch (dev->driver->id) {
478 	case UCLASS_ROOT:
479 	case UCLASS_SIMPLE_BUS: {
480 		/* stop traversing parents at this point: */
481 		struct efi_device_path_vendor *vdp = buf;
482 		*vdp = ROOT;
483 		return &vdp[1];
484 	}
485 #ifdef CONFIG_DM_ETH
486 	case UCLASS_ETH: {
487 		struct efi_device_path_mac_addr *dp =
488 			dp_fill(buf, dev->parent);
489 		struct eth_pdata *pdata = dev->platdata;
490 
491 		dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
492 		dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
493 		dp->dp.length = sizeof(*dp);
494 		memset(&dp->mac, 0, sizeof(dp->mac));
495 		/* We only support IPv4 */
496 		memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
497 		/* Ethernet */
498 		dp->if_type = 1;
499 		return &dp[1];
500 	}
501 #endif
502 #ifdef CONFIG_BLK
503 	case UCLASS_BLK:
504 		switch (dev->parent->uclass->uc_drv->id) {
505 #ifdef CONFIG_IDE
506 		case UCLASS_IDE: {
507 			struct efi_device_path_atapi *dp =
508 			dp_fill(buf, dev->parent);
509 			struct blk_desc *desc = dev_get_uclass_platdata(dev);
510 
511 			dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
512 			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
513 			dp->dp.length = sizeof(*dp);
514 			dp->logical_unit_number = desc->devnum;
515 			dp->primary_secondary = IDE_BUS(desc->devnum);
516 			dp->slave_master = desc->devnum %
517 				(CONFIG_SYS_IDE_MAXDEVICE /
518 				 CONFIG_SYS_IDE_MAXBUS);
519 			return &dp[1];
520 			}
521 #endif
522 #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
523 		case UCLASS_SCSI: {
524 			struct efi_device_path_scsi *dp =
525 				dp_fill(buf, dev->parent);
526 			struct blk_desc *desc = dev_get_uclass_platdata(dev);
527 
528 			dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
529 			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
530 			dp->dp.length = sizeof(*dp);
531 			dp->logical_unit_number = desc->lun;
532 			dp->target_id = desc->target;
533 			return &dp[1];
534 			}
535 #endif
536 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
537 		case UCLASS_MMC: {
538 			struct efi_device_path_sd_mmc_path *sddp =
539 				dp_fill(buf, dev->parent);
540 			struct blk_desc *desc = dev_get_uclass_platdata(dev);
541 
542 			sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
543 			sddp->dp.sub_type = is_sd(desc) ?
544 				DEVICE_PATH_SUB_TYPE_MSG_SD :
545 				DEVICE_PATH_SUB_TYPE_MSG_MMC;
546 			sddp->dp.length   = sizeof(*sddp);
547 			sddp->slot_number = dev->seq;
548 			return &sddp[1];
549 			}
550 #endif
551 		default:
552 			debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
553 			      __FILE__, __LINE__, __func__,
554 			      dev->name, dev->parent->uclass->uc_drv->id);
555 			return dp_fill(buf, dev->parent);
556 		}
557 #endif
558 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
559 	case UCLASS_MMC: {
560 		struct efi_device_path_sd_mmc_path *sddp =
561 			dp_fill(buf, dev->parent);
562 		struct mmc *mmc = mmc_get_mmc_dev(dev);
563 		struct blk_desc *desc = mmc_get_blk_desc(mmc);
564 
565 		sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
566 		sddp->dp.sub_type = is_sd(desc) ?
567 			DEVICE_PATH_SUB_TYPE_MSG_SD :
568 			DEVICE_PATH_SUB_TYPE_MSG_MMC;
569 		sddp->dp.length   = sizeof(*sddp);
570 		sddp->slot_number = dev->seq;
571 
572 		return &sddp[1];
573 	}
574 #endif
575 	case UCLASS_MASS_STORAGE:
576 	case UCLASS_USB_HUB: {
577 		struct efi_device_path_usb_class *udp =
578 			dp_fill(buf, dev->parent);
579 		struct usb_device *udev = dev_get_parent_priv(dev);
580 		struct usb_device_descriptor *desc = &udev->descriptor;
581 
582 		udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
583 		udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
584 		udp->dp.length   = sizeof(*udp);
585 		udp->vendor_id   = desc->idVendor;
586 		udp->product_id  = desc->idProduct;
587 		udp->device_class    = desc->bDeviceClass;
588 		udp->device_subclass = desc->bDeviceSubClass;
589 		udp->device_protocol = desc->bDeviceProtocol;
590 
591 		return &udp[1];
592 	}
593 	default:
594 		debug("%s(%u) %s: unhandled device class: %s (%u)\n",
595 		      __FILE__, __LINE__, __func__,
596 		      dev->name, dev->driver->id);
597 		return dp_fill(buf, dev->parent);
598 	}
599 }
600 
601 /* Construct a device-path from a device: */
602 struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
603 {
604 	void *buf, *start;
605 
606 	start = buf = dp_alloc(dp_size(dev) + sizeof(END));
607 	if (!buf)
608 		return NULL;
609 	buf = dp_fill(buf, dev);
610 	*((struct efi_device_path *)buf) = END;
611 
612 	return start;
613 }
614 #endif
615 
616 static unsigned dp_part_size(struct blk_desc *desc, int part)
617 {
618 	unsigned dpsize;
619 
620 #ifdef CONFIG_BLK
621 	{
622 		struct udevice *dev;
623 		int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
624 
625 		if (ret)
626 			dev = desc->bdev->parent;
627 		dpsize = dp_size(dev);
628 	}
629 #else
630 	dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
631 #endif
632 
633 	if (part == 0) /* the actual disk, not a partition */
634 		return dpsize;
635 
636 	if (desc->part_type == PART_TYPE_ISO)
637 		dpsize += sizeof(struct efi_device_path_cdrom_path);
638 	else
639 		dpsize += sizeof(struct efi_device_path_hard_drive_path);
640 
641 	return dpsize;
642 }
643 
644 /*
645  * Create a device node for a block device partition.
646  *
647  * @buf		buffer to which the device path is wirtten
648  * @desc	block device descriptor
649  * @part	partition number, 0 identifies a block device
650  */
651 static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
652 {
653 	disk_partition_t info;
654 
655 	part_get_info(desc, part, &info);
656 
657 	if (desc->part_type == PART_TYPE_ISO) {
658 		struct efi_device_path_cdrom_path *cddp = buf;
659 
660 		cddp->boot_entry = part;
661 		cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
662 		cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
663 		cddp->dp.length = sizeof(*cddp);
664 		cddp->partition_start = info.start;
665 		cddp->partition_end = info.size;
666 
667 		buf = &cddp[1];
668 	} else {
669 		struct efi_device_path_hard_drive_path *hddp = buf;
670 
671 		hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
672 		hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
673 		hddp->dp.length = sizeof(*hddp);
674 		hddp->partition_number = part;
675 		hddp->partition_start = info.start;
676 		hddp->partition_end = info.size;
677 		if (desc->part_type == PART_TYPE_EFI)
678 			hddp->partmap_type = 2;
679 		else
680 			hddp->partmap_type = 1;
681 
682 		switch (desc->sig_type) {
683 		case SIG_TYPE_NONE:
684 		default:
685 			hddp->signature_type = 0;
686 			memset(hddp->partition_signature, 0,
687 			       sizeof(hddp->partition_signature));
688 			break;
689 		case SIG_TYPE_MBR:
690 			hddp->signature_type = 1;
691 			memset(hddp->partition_signature, 0,
692 			       sizeof(hddp->partition_signature));
693 			memcpy(hddp->partition_signature, &desc->mbr_sig,
694 			       sizeof(desc->mbr_sig));
695 			break;
696 		case SIG_TYPE_GUID:
697 			hddp->signature_type = 2;
698 			memcpy(hddp->partition_signature, &desc->guid_sig,
699 			       sizeof(hddp->partition_signature));
700 			break;
701 		}
702 
703 		buf = &hddp[1];
704 	}
705 
706 	return buf;
707 }
708 
709 /*
710  * Create a device path for a block device or one of its partitions.
711  *
712  * @buf		buffer to which the device path is wirtten
713  * @desc	block device descriptor
714  * @part	partition number, 0 identifies a block device
715  */
716 static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
717 {
718 #ifdef CONFIG_BLK
719 	{
720 		struct udevice *dev;
721 		int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
722 
723 		if (ret)
724 			dev = desc->bdev->parent;
725 		buf = dp_fill(buf, dev);
726 	}
727 #else
728 	/*
729 	 * We *could* make a more accurate path, by looking at if_type
730 	 * and handling all the different cases like we do for non-
731 	 * legacy (ie CONFIG_BLK=y) case.  But most important thing
732 	 * is just to have a unique device-path for if_type+devnum.
733 	 * So map things to a fictitious USB device.
734 	 */
735 	struct efi_device_path_usb *udp;
736 
737 	memcpy(buf, &ROOT, sizeof(ROOT));
738 	buf += sizeof(ROOT);
739 
740 	udp = buf;
741 	udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
742 	udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
743 	udp->dp.length = sizeof(*udp);
744 	udp->parent_port_number = desc->if_type;
745 	udp->usb_interface = desc->devnum;
746 	buf = &udp[1];
747 #endif
748 
749 	if (part == 0) /* the actual disk, not a partition */
750 		return buf;
751 
752 	return dp_part_node(buf, desc, part);
753 }
754 
755 /* Construct a device-path from a partition on a blk device: */
756 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
757 {
758 	void *buf, *start;
759 
760 	start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
761 	if (!buf)
762 		return NULL;
763 
764 	buf = dp_part_fill(buf, desc, part);
765 
766 	*((struct efi_device_path *)buf) = END;
767 
768 	return start;
769 }
770 
771 /*
772  * Create a device node for a block device partition.
773  *
774  * @buf		buffer to which the device path is wirtten
775  * @desc	block device descriptor
776  * @part	partition number, 0 identifies a block device
777  */
778 struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
779 {
780 	efi_uintn_t dpsize;
781 	void *buf;
782 
783 	if (desc->part_type == PART_TYPE_ISO)
784 		dpsize = sizeof(struct efi_device_path_cdrom_path);
785 	else
786 		dpsize = sizeof(struct efi_device_path_hard_drive_path);
787 	buf = dp_alloc(dpsize);
788 
789 	dp_part_node(buf, desc, part);
790 
791 	return buf;
792 }
793 
794 /* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
795 static void path_to_uefi(u16 *uefi, const char *path)
796 {
797 	while (*path) {
798 		char c = *(path++);
799 		if (c == '/')
800 			c = '\\';
801 		*(uefi++) = c;
802 	}
803 	*uefi = '\0';
804 }
805 
806 /*
807  * If desc is NULL, this creates a path with only the file component,
808  * otherwise it creates a full path with both device and file components
809  */
810 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
811 		const char *path)
812 {
813 	struct efi_device_path_file_path *fp;
814 	void *buf, *start;
815 	unsigned dpsize = 0, fpsize;
816 
817 	if (desc)
818 		dpsize = dp_part_size(desc, part);
819 
820 	fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1);
821 	dpsize += fpsize;
822 
823 	start = buf = dp_alloc(dpsize + sizeof(END));
824 	if (!buf)
825 		return NULL;
826 
827 	if (desc)
828 		buf = dp_part_fill(buf, desc, part);
829 
830 	/* add file-path: */
831 	fp = buf;
832 	fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
833 	fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
834 	fp->dp.length = fpsize;
835 	path_to_uefi(fp->str, path);
836 	buf += fpsize;
837 
838 	*((struct efi_device_path *)buf) = END;
839 
840 	return start;
841 }
842 
843 #ifdef CONFIG_NET
844 struct efi_device_path *efi_dp_from_eth(void)
845 {
846 #ifndef CONFIG_DM_ETH
847 	struct efi_device_path_mac_addr *ndp;
848 #endif
849 	void *buf, *start;
850 	unsigned dpsize = 0;
851 
852 	assert(eth_get_dev());
853 
854 #ifdef CONFIG_DM_ETH
855 	dpsize += dp_size(eth_get_dev());
856 #else
857 	dpsize += sizeof(ROOT);
858 	dpsize += sizeof(*ndp);
859 #endif
860 
861 	start = buf = dp_alloc(dpsize + sizeof(END));
862 	if (!buf)
863 		return NULL;
864 
865 #ifdef CONFIG_DM_ETH
866 	buf = dp_fill(buf, eth_get_dev());
867 #else
868 	memcpy(buf, &ROOT, sizeof(ROOT));
869 	buf += sizeof(ROOT);
870 
871 	ndp = buf;
872 	ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
873 	ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
874 	ndp->dp.length = sizeof(*ndp);
875 	ndp->if_type = 1; /* Ethernet */
876 	memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
877 	buf = &ndp[1];
878 #endif
879 
880 	*((struct efi_device_path *)buf) = END;
881 
882 	return start;
883 }
884 #endif
885 
886 /* Construct a device-path for memory-mapped image */
887 struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
888 					uint64_t start_address,
889 					uint64_t end_address)
890 {
891 	struct efi_device_path_memory *mdp;
892 	void *buf, *start;
893 
894 	start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
895 	if (!buf)
896 		return NULL;
897 
898 	mdp = buf;
899 	mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
900 	mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
901 	mdp->dp.length = sizeof(*mdp);
902 	mdp->memory_type = memory_type;
903 	mdp->start_address = start_address;
904 	mdp->end_address = end_address;
905 	buf = &mdp[1];
906 
907 	*((struct efi_device_path *)buf) = END;
908 
909 	return start;
910 }
911 
912 /*
913  * Helper to split a full device path (containing both device and file
914  * parts) into it's constituent parts.
915  */
916 efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
917 				    struct efi_device_path **device_path,
918 				    struct efi_device_path **file_path)
919 {
920 	struct efi_device_path *p, *dp, *fp;
921 
922 	*device_path = NULL;
923 	*file_path = NULL;
924 	dp = efi_dp_dup(full_path);
925 	if (!dp)
926 		return EFI_OUT_OF_RESOURCES;
927 	p = dp;
928 	while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
929 		p = efi_dp_next(p);
930 		if (!p)
931 			return EFI_OUT_OF_RESOURCES;
932 	}
933 	fp = efi_dp_dup(p);
934 	if (!fp)
935 		return EFI_OUT_OF_RESOURCES;
936 	p->type = DEVICE_PATH_TYPE_END;
937 	p->sub_type = DEVICE_PATH_SUB_TYPE_END;
938 	p->length = sizeof(*p);
939 
940 	*device_path = dp;
941 	*file_path = fp;
942 	return EFI_SUCCESS;
943 }
944