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