efi_device_path.c 22 KB

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