efi_device_path.c 22 KB

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