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