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 #include <common.h> 10 #include <blk.h> 11 #include <dm.h> 12 #include <usb.h> 13 #include <mmc.h> 14 #include <efi_loader.h> 15 #include <inttypes.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 #define U_BOOT_GUID \ 26 EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \ 27 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b) 28 29 /* template ROOT node: */ 30 static const struct efi_device_path_vendor ROOT = { 31 .dp = { 32 .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE, 33 .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR, 34 .length = sizeof(ROOT), 35 }, 36 .guid = U_BOOT_GUID, 37 }; 38 39 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) 40 /* 41 * Determine if an MMC device is an SD card. 42 * 43 * @desc block device descriptor 44 * @return true if the device is an SD card 45 */ 46 static bool is_sd(struct blk_desc *desc) 47 { 48 struct mmc *mmc = find_mmc_device(desc->devnum); 49 50 if (!mmc) 51 return false; 52 53 return IS_SD(mmc) != 0U; 54 } 55 #endif 56 57 static void *dp_alloc(size_t sz) 58 { 59 void *buf; 60 61 if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) != EFI_SUCCESS) 62 return NULL; 63 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 /* 113 * See UEFI spec (section 3.1.2, about short-form device-paths.. 114 * tl;dr: we can have a device-path that starts with a USB WWID 115 * or USB Class node, and a few other cases which don't encode 116 * the full device path with bus hierarchy: 117 * 118 * - MESSAGING:USB_WWID 119 * - MESSAGING:USB_CLASS 120 * - MEDIA:FILE_PATH 121 * - MEDIA:HARD_DRIVE 122 * - MESSAGING:URI 123 */ 124 static struct efi_device_path *shorten_path(struct efi_device_path *dp) 125 { 126 while (dp) { 127 /* 128 * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI.. 129 * in practice fallback.efi just uses MEDIA:HARD_DRIVE 130 * so not sure when we would see these other cases. 131 */ 132 if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) || 133 EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) || 134 EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH)) 135 return dp; 136 137 dp = efi_dp_next(dp); 138 } 139 140 return dp; 141 } 142 143 static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, 144 struct efi_device_path **rem) 145 { 146 struct efi_object *efiobj; 147 unsigned int dp_size = efi_dp_size(dp); 148 149 list_for_each_entry(efiobj, &efi_obj_list, link) { 150 struct efi_handler *handler; 151 struct efi_device_path *obj_dp; 152 efi_status_t ret; 153 154 ret = efi_search_protocol(efiobj->handle, 155 &efi_guid_device_path, &handler); 156 if (ret != EFI_SUCCESS) 157 continue; 158 obj_dp = handler->protocol_interface; 159 160 do { 161 if (efi_dp_match(dp, obj_dp) == 0) { 162 if (rem) { 163 /* 164 * Allow partial matches, but inform 165 * the caller. 166 */ 167 *rem = ((void *)dp) + 168 efi_dp_size(obj_dp); 169 return efiobj; 170 } else { 171 /* Only return on exact matches */ 172 if (efi_dp_size(obj_dp) == 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 /* 186 * Find an efiobj from device-path, if 'rem' is not NULL, returns the 187 * remaining part of the device path after the matched object. 188 */ 189 struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, 190 struct efi_device_path **rem) 191 { 192 struct efi_object *efiobj; 193 194 /* Search for an exact match first */ 195 efiobj = find_obj(dp, false, NULL); 196 197 /* Then for a fuzzy match */ 198 if (!efiobj) 199 efiobj = find_obj(dp, false, rem); 200 201 /* And now for a fuzzy short match */ 202 if (!efiobj) 203 efiobj = find_obj(dp, true, rem); 204 205 return efiobj; 206 } 207 208 /* return size not including End node: */ 209 unsigned efi_dp_size(const struct efi_device_path *dp) 210 { 211 unsigned sz = 0; 212 213 while (dp) { 214 sz += dp->length; 215 dp = efi_dp_next(dp); 216 } 217 218 return sz; 219 } 220 221 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) 222 { 223 struct efi_device_path *ndp; 224 unsigned sz = efi_dp_size(dp) + sizeof(END); 225 226 if (!dp) 227 return NULL; 228 229 ndp = dp_alloc(sz); 230 memcpy(ndp, dp, sz); 231 232 return ndp; 233 } 234 235 struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, 236 const struct efi_device_path *dp2) 237 { 238 struct efi_device_path *ret; 239 240 if (!dp1) { 241 ret = efi_dp_dup(dp2); 242 } else if (!dp2) { 243 ret = efi_dp_dup(dp1); 244 } else { 245 /* both dp1 and dp2 are non-null */ 246 unsigned sz1 = efi_dp_size(dp1); 247 unsigned sz2 = efi_dp_size(dp2); 248 void *p = dp_alloc(sz1 + sz2 + sizeof(END)); 249 memcpy(p, dp1, sz1); 250 memcpy(p + sz1, dp2, sz2); 251 memcpy(p + sz1 + sz2, &END, sizeof(END)); 252 ret = p; 253 } 254 255 return ret; 256 } 257 258 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, 259 const struct efi_device_path *node) 260 { 261 struct efi_device_path *ret; 262 263 if (!node && !dp) { 264 ret = efi_dp_dup(&END); 265 } else if (!node) { 266 ret = efi_dp_dup(dp); 267 } else if (!dp) { 268 unsigned sz = node->length; 269 void *p = dp_alloc(sz + sizeof(END)); 270 memcpy(p, node, sz); 271 memcpy(p + sz, &END, sizeof(END)); 272 ret = p; 273 } else { 274 /* both dp and node are non-null */ 275 unsigned sz = efi_dp_size(dp); 276 void *p = dp_alloc(sz + node->length + sizeof(END)); 277 memcpy(p, dp, sz); 278 memcpy(p + sz, node, node->length); 279 memcpy(p + sz + node->length, &END, sizeof(END)); 280 ret = p; 281 } 282 283 return ret; 284 } 285 286 #ifdef CONFIG_DM 287 /* size of device-path not including END node for device and all parents 288 * up to the root device. 289 */ 290 static unsigned dp_size(struct udevice *dev) 291 { 292 if (!dev || !dev->driver) 293 return sizeof(ROOT); 294 295 switch (dev->driver->id) { 296 case UCLASS_ROOT: 297 case UCLASS_SIMPLE_BUS: 298 /* stop traversing parents at this point: */ 299 return sizeof(ROOT); 300 case UCLASS_MMC: 301 return dp_size(dev->parent) + 302 sizeof(struct efi_device_path_sd_mmc_path); 303 case UCLASS_MASS_STORAGE: 304 case UCLASS_USB_HUB: 305 return dp_size(dev->parent) + 306 sizeof(struct efi_device_path_usb_class); 307 default: 308 /* just skip over unknown classes: */ 309 return dp_size(dev->parent); 310 } 311 } 312 313 static void *dp_fill(void *buf, struct udevice *dev) 314 { 315 if (!dev || !dev->driver) 316 return buf; 317 318 switch (dev->driver->id) { 319 case UCLASS_ROOT: 320 case UCLASS_SIMPLE_BUS: { 321 /* stop traversing parents at this point: */ 322 struct efi_device_path_vendor *vdp = buf; 323 *vdp = ROOT; 324 return &vdp[1]; 325 } 326 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) 327 case UCLASS_MMC: { 328 struct efi_device_path_sd_mmc_path *sddp = 329 dp_fill(buf, dev->parent); 330 struct mmc *mmc = mmc_get_mmc_dev(dev); 331 struct blk_desc *desc = mmc_get_blk_desc(mmc); 332 333 sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; 334 sddp->dp.sub_type = is_sd(desc) ? 335 DEVICE_PATH_SUB_TYPE_MSG_SD : 336 DEVICE_PATH_SUB_TYPE_MSG_MMC; 337 sddp->dp.length = sizeof(*sddp); 338 sddp->slot_number = dev->seq; 339 340 return &sddp[1]; 341 } 342 #endif 343 case UCLASS_MASS_STORAGE: 344 case UCLASS_USB_HUB: { 345 struct efi_device_path_usb_class *udp = 346 dp_fill(buf, dev->parent); 347 struct usb_device *udev = dev_get_parent_priv(dev); 348 struct usb_device_descriptor *desc = &udev->descriptor; 349 350 udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; 351 udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS; 352 udp->dp.length = sizeof(*udp); 353 udp->vendor_id = desc->idVendor; 354 udp->product_id = desc->idProduct; 355 udp->device_class = desc->bDeviceClass; 356 udp->device_subclass = desc->bDeviceSubClass; 357 udp->device_protocol = desc->bDeviceProtocol; 358 359 return &udp[1]; 360 } 361 default: 362 debug("unhandled device class: %s (%u)\n", 363 dev->name, dev->driver->id); 364 return dp_fill(buf, dev->parent); 365 } 366 } 367 368 /* Construct a device-path from a device: */ 369 struct efi_device_path *efi_dp_from_dev(struct udevice *dev) 370 { 371 void *buf, *start; 372 373 start = buf = dp_alloc(dp_size(dev) + sizeof(END)); 374 buf = dp_fill(buf, dev); 375 *((struct efi_device_path *)buf) = END; 376 377 return start; 378 } 379 #endif 380 381 static unsigned dp_part_size(struct blk_desc *desc, int part) 382 { 383 unsigned dpsize; 384 385 #ifdef CONFIG_BLK 386 dpsize = dp_size(desc->bdev->parent); 387 #else 388 dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb); 389 #endif 390 391 if (part == 0) /* the actual disk, not a partition */ 392 return dpsize; 393 394 if (desc->part_type == PART_TYPE_ISO) 395 dpsize += sizeof(struct efi_device_path_cdrom_path); 396 else 397 dpsize += sizeof(struct efi_device_path_hard_drive_path); 398 399 return dpsize; 400 } 401 402 /* 403 * Create a device path for a block device or one of its partitions. 404 * 405 * @buf buffer to which the device path is wirtten 406 * @desc block device descriptor 407 * @part partition number, 0 identifies a block device 408 */ 409 static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) 410 { 411 disk_partition_t info; 412 413 #ifdef CONFIG_BLK 414 buf = dp_fill(buf, desc->bdev->parent); 415 #else 416 /* 417 * We *could* make a more accurate path, by looking at if_type 418 * and handling all the different cases like we do for non- 419 * legacy (ie CONFIG_BLK=y) case. But most important thing 420 * is just to have a unique device-path for if_type+devnum. 421 * So map things to a fictitious USB device. 422 */ 423 struct efi_device_path_usb *udp; 424 425 memcpy(buf, &ROOT, sizeof(ROOT)); 426 buf += sizeof(ROOT); 427 428 udp = buf; 429 udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; 430 udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB; 431 udp->dp.length = sizeof(*udp); 432 udp->parent_port_number = desc->if_type; 433 udp->usb_interface = desc->devnum; 434 buf = &udp[1]; 435 #endif 436 437 if (part == 0) /* the actual disk, not a partition */ 438 return buf; 439 440 part_get_info(desc, part, &info); 441 442 if (desc->part_type == PART_TYPE_ISO) { 443 struct efi_device_path_cdrom_path *cddp = buf; 444 445 cddp->boot_entry = part; 446 cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; 447 cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH; 448 cddp->dp.length = sizeof(*cddp); 449 cddp->partition_start = info.start; 450 cddp->partition_end = info.size; 451 452 buf = &cddp[1]; 453 } else { 454 struct efi_device_path_hard_drive_path *hddp = buf; 455 456 hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; 457 hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH; 458 hddp->dp.length = sizeof(*hddp); 459 hddp->partition_number = part; 460 hddp->partition_start = info.start; 461 hddp->partition_end = info.size; 462 if (desc->part_type == PART_TYPE_EFI) 463 hddp->partmap_type = 2; 464 else 465 hddp->partmap_type = 1; 466 467 switch (desc->sig_type) { 468 case SIG_TYPE_NONE: 469 default: 470 hddp->signature_type = 0; 471 memset(hddp->partition_signature, 0, 472 sizeof(hddp->partition_signature)); 473 break; 474 case SIG_TYPE_MBR: 475 hddp->signature_type = 1; 476 memset(hddp->partition_signature, 0, 477 sizeof(hddp->partition_signature)); 478 memcpy(hddp->partition_signature, &desc->mbr_sig, 479 sizeof(desc->mbr_sig)); 480 break; 481 case SIG_TYPE_GUID: 482 hddp->signature_type = 2; 483 memcpy(hddp->partition_signature, &desc->guid_sig, 484 sizeof(hddp->partition_signature)); 485 break; 486 } 487 488 buf = &hddp[1]; 489 } 490 491 return buf; 492 } 493 494 495 /* Construct a device-path from a partition on a blk device: */ 496 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part) 497 { 498 void *buf, *start; 499 500 start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END)); 501 502 buf = dp_part_fill(buf, desc, part); 503 504 *((struct efi_device_path *)buf) = END; 505 506 return start; 507 } 508 509 /* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */ 510 static void path_to_uefi(u16 *uefi, const char *path) 511 { 512 while (*path) { 513 char c = *(path++); 514 if (c == '/') 515 c = '\\'; 516 *(uefi++) = c; 517 } 518 *uefi = '\0'; 519 } 520 521 /* 522 * If desc is NULL, this creates a path with only the file component, 523 * otherwise it creates a full path with both device and file components 524 */ 525 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, 526 const char *path) 527 { 528 struct efi_device_path_file_path *fp; 529 void *buf, *start; 530 unsigned dpsize = 0, fpsize; 531 532 if (desc) 533 dpsize = dp_part_size(desc, part); 534 535 fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1); 536 dpsize += fpsize; 537 538 start = buf = dp_alloc(dpsize + sizeof(END)); 539 540 if (desc) 541 buf = dp_part_fill(buf, desc, part); 542 543 /* add file-path: */ 544 fp = buf; 545 fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; 546 fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH; 547 fp->dp.length = fpsize; 548 path_to_uefi(fp->str, path); 549 buf += fpsize; 550 551 *((struct efi_device_path *)buf) = END; 552 553 return start; 554 } 555 556 #ifdef CONFIG_NET 557 struct efi_device_path *efi_dp_from_eth(void) 558 { 559 struct efi_device_path_mac_addr *ndp; 560 void *buf, *start; 561 unsigned dpsize = 0; 562 563 assert(eth_get_dev()); 564 565 #ifdef CONFIG_DM_ETH 566 dpsize += dp_size(eth_get_dev()); 567 #else 568 dpsize += sizeof(ROOT); 569 #endif 570 dpsize += sizeof(*ndp); 571 572 start = buf = dp_alloc(dpsize + sizeof(END)); 573 574 #ifdef CONFIG_DM_ETH 575 buf = dp_fill(buf, eth_get_dev()); 576 #else 577 memcpy(buf, &ROOT, sizeof(ROOT)); 578 buf += sizeof(ROOT); 579 #endif 580 581 ndp = buf; 582 ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; 583 ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR; 584 ndp->dp.length = sizeof(*ndp); 585 memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN); 586 buf = &ndp[1]; 587 588 *((struct efi_device_path *)buf) = END; 589 590 return start; 591 } 592 #endif 593 594 /* Construct a device-path for memory-mapped image */ 595 struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, 596 uint64_t start_address, 597 uint64_t end_address) 598 { 599 struct efi_device_path_memory *mdp; 600 void *buf, *start; 601 602 start = buf = dp_alloc(sizeof(*mdp) + sizeof(END)); 603 604 mdp = buf; 605 mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; 606 mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY; 607 mdp->dp.length = sizeof(*mdp); 608 mdp->memory_type = memory_type; 609 mdp->start_address = start_address; 610 mdp->end_address = end_address; 611 buf = &mdp[1]; 612 613 *((struct efi_device_path *)buf) = END; 614 615 return start; 616 } 617 618 /* 619 * Helper to split a full device path (containing both device and file 620 * parts) into it's constituent parts. 621 */ 622 void efi_dp_split_file_path(struct efi_device_path *full_path, 623 struct efi_device_path **device_path, 624 struct efi_device_path **file_path) 625 { 626 struct efi_device_path *p, *dp, *fp; 627 628 dp = efi_dp_dup(full_path); 629 p = dp; 630 while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) 631 p = efi_dp_next(p); 632 fp = efi_dp_dup(p); 633 634 p->type = DEVICE_PATH_TYPE_END; 635 p->sub_type = DEVICE_PATH_SUB_TYPE_END; 636 p->length = sizeof(*p); 637 638 *device_path = dp; 639 *file_path = fp; 640 } 641