efi_device_path.c 22 KB

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