efi_device_path.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  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. 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. unsigned int dp_size = efi_dp_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_size(obj_dp);
  149. return efiobj;
  150. } else {
  151. /* Only return on exact matches */
  152. if (efi_dp_size(obj_dp) == 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. /* return size not including End node: */
  198. unsigned efi_dp_size(const struct efi_device_path *dp)
  199. {
  200. unsigned sz = 0;
  201. while (dp) {
  202. sz += dp->length;
  203. dp = efi_dp_next(dp);
  204. }
  205. return sz;
  206. }
  207. struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
  208. {
  209. struct efi_device_path *ndp;
  210. unsigned sz = efi_dp_size(dp) + sizeof(END);
  211. if (!dp)
  212. return NULL;
  213. ndp = dp_alloc(sz);
  214. if (!ndp)
  215. return NULL;
  216. memcpy(ndp, dp, sz);
  217. return ndp;
  218. }
  219. struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
  220. const struct efi_device_path *dp2)
  221. {
  222. struct efi_device_path *ret;
  223. if (!dp1) {
  224. ret = efi_dp_dup(dp2);
  225. } else if (!dp2) {
  226. ret = efi_dp_dup(dp1);
  227. } else {
  228. /* both dp1 and dp2 are non-null */
  229. unsigned sz1 = efi_dp_size(dp1);
  230. unsigned sz2 = efi_dp_size(dp2);
  231. void *p = dp_alloc(sz1 + sz2 + sizeof(END));
  232. if (!p)
  233. return NULL;
  234. memcpy(p, dp1, sz1);
  235. memcpy(p + sz1, dp2, sz2);
  236. memcpy(p + sz1 + sz2, &END, sizeof(END));
  237. ret = p;
  238. }
  239. return ret;
  240. }
  241. struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
  242. const struct efi_device_path *node)
  243. {
  244. struct efi_device_path *ret;
  245. if (!node && !dp) {
  246. ret = efi_dp_dup(&END);
  247. } else if (!node) {
  248. ret = efi_dp_dup(dp);
  249. } else if (!dp) {
  250. unsigned sz = node->length;
  251. void *p = dp_alloc(sz + sizeof(END));
  252. if (!p)
  253. return NULL;
  254. memcpy(p, node, sz);
  255. memcpy(p + sz, &END, sizeof(END));
  256. ret = p;
  257. } else {
  258. /* both dp and node are non-null */
  259. unsigned sz = efi_dp_size(dp);
  260. void *p = dp_alloc(sz + node->length + sizeof(END));
  261. if (!p)
  262. return NULL;
  263. memcpy(p, dp, sz);
  264. memcpy(p + sz, node, node->length);
  265. memcpy(p + sz + node->length, &END, sizeof(END));
  266. ret = p;
  267. }
  268. return ret;
  269. }
  270. #ifdef CONFIG_DM
  271. /* size of device-path not including END node for device and all parents
  272. * up to the root device.
  273. */
  274. static unsigned dp_size(struct udevice *dev)
  275. {
  276. if (!dev || !dev->driver)
  277. return sizeof(ROOT);
  278. switch (dev->driver->id) {
  279. case UCLASS_ROOT:
  280. case UCLASS_SIMPLE_BUS:
  281. /* stop traversing parents at this point: */
  282. return sizeof(ROOT);
  283. case UCLASS_ETH:
  284. return dp_size(dev->parent) +
  285. sizeof(struct efi_device_path_mac_addr);
  286. #ifdef CONFIG_BLK
  287. case UCLASS_BLK:
  288. switch (dev->parent->uclass->uc_drv->id) {
  289. #ifdef CONFIG_IDE
  290. case UCLASS_IDE:
  291. return dp_size(dev->parent) +
  292. sizeof(struct efi_device_path_atapi);
  293. #endif
  294. #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
  295. case UCLASS_SCSI:
  296. return dp_size(dev->parent) +
  297. sizeof(struct efi_device_path_scsi);
  298. #endif
  299. #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
  300. case UCLASS_MMC:
  301. return dp_size(dev->parent) +
  302. sizeof(struct efi_device_path_sd_mmc_path);
  303. #endif
  304. default:
  305. return dp_size(dev->parent);
  306. }
  307. #endif
  308. #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
  309. case UCLASS_MMC:
  310. return dp_size(dev->parent) +
  311. sizeof(struct efi_device_path_sd_mmc_path);
  312. #endif
  313. case UCLASS_MASS_STORAGE:
  314. case UCLASS_USB_HUB:
  315. return dp_size(dev->parent) +
  316. sizeof(struct efi_device_path_usb_class);
  317. default:
  318. /* just skip over unknown classes: */
  319. return dp_size(dev->parent);
  320. }
  321. }
  322. /*
  323. * Recursively build a device path.
  324. *
  325. * @buf pointer to the end of the device path
  326. * @dev device
  327. * @return pointer to the end of the device path
  328. */
  329. static void *dp_fill(void *buf, struct udevice *dev)
  330. {
  331. if (!dev || !dev->driver)
  332. return buf;
  333. switch (dev->driver->id) {
  334. case UCLASS_ROOT:
  335. case UCLASS_SIMPLE_BUS: {
  336. /* stop traversing parents at this point: */
  337. struct efi_device_path_vendor *vdp = buf;
  338. *vdp = ROOT;
  339. return &vdp[1];
  340. }
  341. #ifdef CONFIG_DM_ETH
  342. case UCLASS_ETH: {
  343. struct efi_device_path_mac_addr *dp =
  344. dp_fill(buf, dev->parent);
  345. struct eth_pdata *pdata = dev->platdata;
  346. dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  347. dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
  348. dp->dp.length = sizeof(*dp);
  349. memset(&dp->mac, 0, sizeof(dp->mac));
  350. /* We only support IPv4 */
  351. memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
  352. /* Ethernet */
  353. dp->if_type = 1;
  354. return &dp[1];
  355. }
  356. #endif
  357. #ifdef CONFIG_BLK
  358. case UCLASS_BLK:
  359. switch (dev->parent->uclass->uc_drv->id) {
  360. #ifdef CONFIG_IDE
  361. case UCLASS_IDE: {
  362. struct efi_device_path_atapi *dp =
  363. dp_fill(buf, dev->parent);
  364. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  365. dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  366. dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
  367. dp->dp.length = sizeof(*dp);
  368. dp->logical_unit_number = desc->devnum;
  369. dp->primary_secondary = IDE_BUS(desc->devnum);
  370. dp->slave_master = desc->devnum %
  371. (CONFIG_SYS_IDE_MAXDEVICE /
  372. CONFIG_SYS_IDE_MAXBUS);
  373. return &dp[1];
  374. }
  375. #endif
  376. #if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
  377. case UCLASS_SCSI: {
  378. struct efi_device_path_scsi *dp =
  379. dp_fill(buf, dev->parent);
  380. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  381. dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  382. dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
  383. dp->dp.length = sizeof(*dp);
  384. dp->logical_unit_number = desc->lun;
  385. dp->target_id = desc->target;
  386. return &dp[1];
  387. }
  388. #endif
  389. #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
  390. case UCLASS_MMC: {
  391. struct efi_device_path_sd_mmc_path *sddp =
  392. dp_fill(buf, dev->parent);
  393. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  394. sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  395. sddp->dp.sub_type = is_sd(desc) ?
  396. DEVICE_PATH_SUB_TYPE_MSG_SD :
  397. DEVICE_PATH_SUB_TYPE_MSG_MMC;
  398. sddp->dp.length = sizeof(*sddp);
  399. sddp->slot_number = dev->seq;
  400. return &sddp[1];
  401. }
  402. #endif
  403. default:
  404. debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
  405. __FILE__, __LINE__, __func__,
  406. dev->name, dev->parent->uclass->uc_drv->id);
  407. return dp_fill(buf, dev->parent);
  408. }
  409. #endif
  410. #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
  411. case UCLASS_MMC: {
  412. struct efi_device_path_sd_mmc_path *sddp =
  413. dp_fill(buf, dev->parent);
  414. struct mmc *mmc = mmc_get_mmc_dev(dev);
  415. struct blk_desc *desc = mmc_get_blk_desc(mmc);
  416. sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  417. sddp->dp.sub_type = is_sd(desc) ?
  418. DEVICE_PATH_SUB_TYPE_MSG_SD :
  419. DEVICE_PATH_SUB_TYPE_MSG_MMC;
  420. sddp->dp.length = sizeof(*sddp);
  421. sddp->slot_number = dev->seq;
  422. return &sddp[1];
  423. }
  424. #endif
  425. case UCLASS_MASS_STORAGE:
  426. case UCLASS_USB_HUB: {
  427. struct efi_device_path_usb_class *udp =
  428. dp_fill(buf, dev->parent);
  429. struct usb_device *udev = dev_get_parent_priv(dev);
  430. struct usb_device_descriptor *desc = &udev->descriptor;
  431. udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  432. udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
  433. udp->dp.length = sizeof(*udp);
  434. udp->vendor_id = desc->idVendor;
  435. udp->product_id = desc->idProduct;
  436. udp->device_class = desc->bDeviceClass;
  437. udp->device_subclass = desc->bDeviceSubClass;
  438. udp->device_protocol = desc->bDeviceProtocol;
  439. return &udp[1];
  440. }
  441. default:
  442. debug("%s(%u) %s: unhandled device class: %s (%u)\n",
  443. __FILE__, __LINE__, __func__,
  444. dev->name, dev->driver->id);
  445. return dp_fill(buf, dev->parent);
  446. }
  447. }
  448. /* Construct a device-path from a device: */
  449. struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
  450. {
  451. void *buf, *start;
  452. start = buf = dp_alloc(dp_size(dev) + sizeof(END));
  453. if (!buf)
  454. return NULL;
  455. buf = dp_fill(buf, dev);
  456. *((struct efi_device_path *)buf) = END;
  457. return start;
  458. }
  459. #endif
  460. static unsigned dp_part_size(struct blk_desc *desc, int part)
  461. {
  462. unsigned dpsize;
  463. #ifdef CONFIG_BLK
  464. {
  465. struct udevice *dev;
  466. int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
  467. if (ret)
  468. dev = desc->bdev->parent;
  469. dpsize = dp_size(dev);
  470. }
  471. #else
  472. dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
  473. #endif
  474. if (part == 0) /* the actual disk, not a partition */
  475. return dpsize;
  476. if (desc->part_type == PART_TYPE_ISO)
  477. dpsize += sizeof(struct efi_device_path_cdrom_path);
  478. else
  479. dpsize += sizeof(struct efi_device_path_hard_drive_path);
  480. return dpsize;
  481. }
  482. /*
  483. * Create a device node for a block device partition.
  484. *
  485. * @buf buffer to which the device path is wirtten
  486. * @desc block device descriptor
  487. * @part partition number, 0 identifies a block device
  488. */
  489. static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
  490. {
  491. disk_partition_t info;
  492. part_get_info(desc, part, &info);
  493. if (desc->part_type == PART_TYPE_ISO) {
  494. struct efi_device_path_cdrom_path *cddp = buf;
  495. cddp->boot_entry = part;
  496. cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
  497. cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
  498. cddp->dp.length = sizeof(*cddp);
  499. cddp->partition_start = info.start;
  500. cddp->partition_end = info.size;
  501. buf = &cddp[1];
  502. } else {
  503. struct efi_device_path_hard_drive_path *hddp = buf;
  504. hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
  505. hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
  506. hddp->dp.length = sizeof(*hddp);
  507. hddp->partition_number = part;
  508. hddp->partition_start = info.start;
  509. hddp->partition_end = info.size;
  510. if (desc->part_type == PART_TYPE_EFI)
  511. hddp->partmap_type = 2;
  512. else
  513. hddp->partmap_type = 1;
  514. switch (desc->sig_type) {
  515. case SIG_TYPE_NONE:
  516. default:
  517. hddp->signature_type = 0;
  518. memset(hddp->partition_signature, 0,
  519. sizeof(hddp->partition_signature));
  520. break;
  521. case SIG_TYPE_MBR:
  522. hddp->signature_type = 1;
  523. memset(hddp->partition_signature, 0,
  524. sizeof(hddp->partition_signature));
  525. memcpy(hddp->partition_signature, &desc->mbr_sig,
  526. sizeof(desc->mbr_sig));
  527. break;
  528. case SIG_TYPE_GUID:
  529. hddp->signature_type = 2;
  530. memcpy(hddp->partition_signature, &desc->guid_sig,
  531. sizeof(hddp->partition_signature));
  532. break;
  533. }
  534. buf = &hddp[1];
  535. }
  536. return buf;
  537. }
  538. /*
  539. * Create a device path for a block device or one of its partitions.
  540. *
  541. * @buf buffer to which the device path is wirtten
  542. * @desc block device descriptor
  543. * @part partition number, 0 identifies a block device
  544. */
  545. static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
  546. {
  547. #ifdef CONFIG_BLK
  548. {
  549. struct udevice *dev;
  550. int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
  551. if (ret)
  552. dev = desc->bdev->parent;
  553. buf = dp_fill(buf, dev);
  554. }
  555. #else
  556. /*
  557. * We *could* make a more accurate path, by looking at if_type
  558. * and handling all the different cases like we do for non-
  559. * legacy (ie CONFIG_BLK=y) case. But most important thing
  560. * is just to have a unique device-path for if_type+devnum.
  561. * So map things to a fictitious USB device.
  562. */
  563. struct efi_device_path_usb *udp;
  564. memcpy(buf, &ROOT, sizeof(ROOT));
  565. buf += sizeof(ROOT);
  566. udp = buf;
  567. udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  568. udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
  569. udp->dp.length = sizeof(*udp);
  570. udp->parent_port_number = desc->if_type;
  571. udp->usb_interface = desc->devnum;
  572. buf = &udp[1];
  573. #endif
  574. if (part == 0) /* the actual disk, not a partition */
  575. return buf;
  576. return dp_part_node(buf, desc, part);
  577. }
  578. /* Construct a device-path from a partition on a blk device: */
  579. struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
  580. {
  581. void *buf, *start;
  582. start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
  583. if (!buf)
  584. return NULL;
  585. buf = dp_part_fill(buf, desc, part);
  586. *((struct efi_device_path *)buf) = END;
  587. return start;
  588. }
  589. /*
  590. * Create a device node for a block device partition.
  591. *
  592. * @buf buffer to which the device path is wirtten
  593. * @desc block device descriptor
  594. * @part partition number, 0 identifies a block device
  595. */
  596. struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
  597. {
  598. efi_uintn_t dpsize;
  599. void *buf;
  600. if (desc->part_type == PART_TYPE_ISO)
  601. dpsize = sizeof(struct efi_device_path_cdrom_path);
  602. else
  603. dpsize = sizeof(struct efi_device_path_hard_drive_path);
  604. buf = dp_alloc(dpsize);
  605. dp_part_node(buf, desc, part);
  606. return buf;
  607. }
  608. /* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
  609. static void path_to_uefi(u16 *uefi, const char *path)
  610. {
  611. while (*path) {
  612. char c = *(path++);
  613. if (c == '/')
  614. c = '\\';
  615. *(uefi++) = c;
  616. }
  617. *uefi = '\0';
  618. }
  619. /*
  620. * If desc is NULL, this creates a path with only the file component,
  621. * otherwise it creates a full path with both device and file components
  622. */
  623. struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
  624. const char *path)
  625. {
  626. struct efi_device_path_file_path *fp;
  627. void *buf, *start;
  628. unsigned dpsize = 0, fpsize;
  629. if (desc)
  630. dpsize = dp_part_size(desc, part);
  631. fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1);
  632. dpsize += fpsize;
  633. start = buf = dp_alloc(dpsize + sizeof(END));
  634. if (!buf)
  635. return NULL;
  636. if (desc)
  637. buf = dp_part_fill(buf, desc, part);
  638. /* add file-path: */
  639. fp = buf;
  640. fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
  641. fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
  642. fp->dp.length = fpsize;
  643. path_to_uefi(fp->str, path);
  644. buf += fpsize;
  645. *((struct efi_device_path *)buf) = END;
  646. return start;
  647. }
  648. #ifdef CONFIG_CMD_NET
  649. struct efi_device_path *efi_dp_from_eth(void)
  650. {
  651. struct efi_device_path_mac_addr *ndp;
  652. void *buf, *start;
  653. unsigned dpsize = 0;
  654. assert(eth_get_dev());
  655. #ifdef CONFIG_DM_ETH
  656. dpsize += dp_size(eth_get_dev());
  657. #else
  658. dpsize += sizeof(ROOT);
  659. #endif
  660. dpsize += sizeof(*ndp);
  661. start = buf = dp_alloc(dpsize + sizeof(END));
  662. if (!buf)
  663. return NULL;
  664. #ifdef CONFIG_DM_ETH
  665. buf = dp_fill(buf, eth_get_dev());
  666. #else
  667. memcpy(buf, &ROOT, sizeof(ROOT));
  668. buf += sizeof(ROOT);
  669. #endif
  670. ndp = buf;
  671. ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
  672. ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
  673. ndp->dp.length = sizeof(*ndp);
  674. memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
  675. buf = &ndp[1];
  676. *((struct efi_device_path *)buf) = END;
  677. return start;
  678. }
  679. #endif
  680. /* Construct a device-path for memory-mapped image */
  681. struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
  682. uint64_t start_address,
  683. uint64_t end_address)
  684. {
  685. struct efi_device_path_memory *mdp;
  686. void *buf, *start;
  687. start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
  688. if (!buf)
  689. return NULL;
  690. mdp = buf;
  691. mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
  692. mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
  693. mdp->dp.length = sizeof(*mdp);
  694. mdp->memory_type = memory_type;
  695. mdp->start_address = start_address;
  696. mdp->end_address = end_address;
  697. buf = &mdp[1];
  698. *((struct efi_device_path *)buf) = END;
  699. return start;
  700. }
  701. /*
  702. * Helper to split a full device path (containing both device and file
  703. * parts) into it's constituent parts.
  704. */
  705. efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
  706. struct efi_device_path **device_path,
  707. struct efi_device_path **file_path)
  708. {
  709. struct efi_device_path *p, *dp, *fp;
  710. *device_path = NULL;
  711. *file_path = NULL;
  712. dp = efi_dp_dup(full_path);
  713. if (!dp)
  714. return EFI_OUT_OF_RESOURCES;
  715. p = dp;
  716. while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
  717. p = efi_dp_next(p);
  718. if (!p)
  719. return EFI_OUT_OF_RESOURCES;
  720. }
  721. fp = efi_dp_dup(p);
  722. if (!fp)
  723. return EFI_OUT_OF_RESOURCES;
  724. p->type = DEVICE_PATH_TYPE_END;
  725. p->sub_type = DEVICE_PATH_SUB_TYPE_END;
  726. p->length = sizeof(*p);
  727. *device_path = dp;
  728. *file_path = fp;
  729. return EFI_SUCCESS;
  730. }