efi_device_path.c 22 KB

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