efi_device_path.c 13 KB

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