part.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2001
  4. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  5. */
  6. #include <common.h>
  7. #include <blk.h>
  8. #include <command.h>
  9. #include <env.h>
  10. #include <errno.h>
  11. #include <ide.h>
  12. #include <log.h>
  13. #include <malloc.h>
  14. #include <part.h>
  15. #include <ubifs_uboot.h>
  16. #undef PART_DEBUG
  17. #ifdef PART_DEBUG
  18. #define PRINTF(fmt,args...) printf (fmt ,##args)
  19. #else
  20. #define PRINTF(fmt,args...)
  21. #endif
  22. /* Check all partition types */
  23. #define PART_TYPE_ALL -1
  24. static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc)
  25. {
  26. struct part_driver *drv =
  27. ll_entry_start(struct part_driver, part_driver);
  28. const int n_ents = ll_entry_count(struct part_driver, part_driver);
  29. struct part_driver *entry;
  30. if (dev_desc->part_type == PART_TYPE_UNKNOWN) {
  31. for (entry = drv; entry != drv + n_ents; entry++) {
  32. int ret;
  33. ret = entry->test(dev_desc);
  34. if (!ret) {
  35. dev_desc->part_type = entry->part_type;
  36. return entry;
  37. }
  38. }
  39. } else {
  40. for (entry = drv; entry != drv + n_ents; entry++) {
  41. if (dev_desc->part_type == entry->part_type)
  42. return entry;
  43. }
  44. }
  45. /* Not found */
  46. return NULL;
  47. }
  48. #ifdef CONFIG_HAVE_BLOCK_DEVICE
  49. static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
  50. {
  51. struct blk_desc *dev_desc;
  52. int ret;
  53. dev_desc = blk_get_devnum_by_typename(ifname, dev);
  54. if (!dev_desc) {
  55. debug("%s: No device for iface '%s', dev %d\n", __func__,
  56. ifname, dev);
  57. return NULL;
  58. }
  59. ret = blk_dselect_hwpart(dev_desc, hwpart);
  60. if (ret) {
  61. debug("%s: Failed to select h/w partition: err-%d\n", __func__,
  62. ret);
  63. return NULL;
  64. }
  65. return dev_desc;
  66. }
  67. struct blk_desc *blk_get_dev(const char *ifname, int dev)
  68. {
  69. return get_dev_hwpart(ifname, dev, 0);
  70. }
  71. #else
  72. struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
  73. {
  74. return NULL;
  75. }
  76. struct blk_desc *blk_get_dev(const char *ifname, int dev)
  77. {
  78. return NULL;
  79. }
  80. #endif
  81. #ifdef CONFIG_HAVE_BLOCK_DEVICE
  82. /* ------------------------------------------------------------------------- */
  83. /*
  84. * reports device info to the user
  85. */
  86. #ifdef CONFIG_LBA48
  87. typedef uint64_t lba512_t;
  88. #else
  89. typedef lbaint_t lba512_t;
  90. #endif
  91. /*
  92. * Overflowless variant of (block_count * mul_by / 2**right_shift)
  93. * when 2**right_shift > mul_by
  94. */
  95. static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by,
  96. int right_shift)
  97. {
  98. lba512_t bc_quot, bc_rem;
  99. /* x * m / d == x / d * m + (x % d) * m / d */
  100. bc_quot = block_count >> right_shift;
  101. bc_rem = block_count - (bc_quot << right_shift);
  102. return bc_quot * mul_by + ((bc_rem * mul_by) >> right_shift);
  103. }
  104. void dev_print (struct blk_desc *dev_desc)
  105. {
  106. lba512_t lba512; /* number of blocks if 512bytes block size */
  107. if (dev_desc->type == DEV_TYPE_UNKNOWN) {
  108. puts ("not available\n");
  109. return;
  110. }
  111. switch (dev_desc->if_type) {
  112. case IF_TYPE_SCSI:
  113. printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
  114. dev_desc->target,dev_desc->lun,
  115. dev_desc->vendor,
  116. dev_desc->product,
  117. dev_desc->revision);
  118. break;
  119. case IF_TYPE_ATAPI:
  120. case IF_TYPE_IDE:
  121. case IF_TYPE_SATA:
  122. printf ("Model: %s Firm: %s Ser#: %s\n",
  123. dev_desc->vendor,
  124. dev_desc->revision,
  125. dev_desc->product);
  126. break;
  127. case IF_TYPE_SD:
  128. case IF_TYPE_MMC:
  129. case IF_TYPE_USB:
  130. case IF_TYPE_NVME:
  131. case IF_TYPE_PVBLOCK:
  132. printf ("Vendor: %s Rev: %s Prod: %s\n",
  133. dev_desc->vendor,
  134. dev_desc->revision,
  135. dev_desc->product);
  136. break;
  137. case IF_TYPE_VIRTIO:
  138. printf("%s VirtIO Block Device\n", dev_desc->vendor);
  139. break;
  140. case IF_TYPE_DOC:
  141. puts("device type DOC\n");
  142. return;
  143. case IF_TYPE_UNKNOWN:
  144. puts("device type unknown\n");
  145. return;
  146. default:
  147. printf("Unhandled device type: %i\n", dev_desc->if_type);
  148. return;
  149. }
  150. puts (" Type: ");
  151. if (dev_desc->removable)
  152. puts ("Removable ");
  153. switch (dev_desc->type & 0x1F) {
  154. case DEV_TYPE_HARDDISK:
  155. puts ("Hard Disk");
  156. break;
  157. case DEV_TYPE_CDROM:
  158. puts ("CD ROM");
  159. break;
  160. case DEV_TYPE_OPDISK:
  161. puts ("Optical Device");
  162. break;
  163. case DEV_TYPE_TAPE:
  164. puts ("Tape");
  165. break;
  166. default:
  167. printf ("# %02X #", dev_desc->type & 0x1F);
  168. break;
  169. }
  170. puts ("\n");
  171. if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
  172. ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
  173. lbaint_t lba;
  174. lba = dev_desc->lba;
  175. lba512 = (lba * (dev_desc->blksz/512));
  176. /* round to 1 digit */
  177. /* 2048 = (1024 * 1024) / 512 MB */
  178. mb = lba512_muldiv(lba512, 10, 11);
  179. mb_quot = mb / 10;
  180. mb_rem = mb - (10 * mb_quot);
  181. gb = mb / 1024;
  182. gb_quot = gb / 10;
  183. gb_rem = gb - (10 * gb_quot);
  184. #ifdef CONFIG_LBA48
  185. if (dev_desc->lba48)
  186. printf (" Supports 48-bit addressing\n");
  187. #endif
  188. #if defined(CONFIG_SYS_64BIT_LBA)
  189. printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)\n",
  190. mb_quot, mb_rem,
  191. gb_quot, gb_rem,
  192. lba,
  193. dev_desc->blksz);
  194. #else
  195. printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)\n",
  196. mb_quot, mb_rem,
  197. gb_quot, gb_rem,
  198. (ulong)lba,
  199. dev_desc->blksz);
  200. #endif
  201. } else {
  202. puts (" Capacity: not available\n");
  203. }
  204. }
  205. #endif
  206. #ifdef CONFIG_HAVE_BLOCK_DEVICE
  207. void part_init(struct blk_desc *dev_desc)
  208. {
  209. struct part_driver *drv =
  210. ll_entry_start(struct part_driver, part_driver);
  211. const int n_ents = ll_entry_count(struct part_driver, part_driver);
  212. struct part_driver *entry;
  213. blkcache_invalidate(dev_desc->if_type, dev_desc->devnum);
  214. dev_desc->part_type = PART_TYPE_UNKNOWN;
  215. for (entry = drv; entry != drv + n_ents; entry++) {
  216. int ret;
  217. ret = entry->test(dev_desc);
  218. debug("%s: try '%s': ret=%d\n", __func__, entry->name, ret);
  219. if (!ret) {
  220. dev_desc->part_type = entry->part_type;
  221. break;
  222. }
  223. }
  224. }
  225. static void print_part_header(const char *type, struct blk_desc *dev_desc)
  226. {
  227. #if CONFIG_IS_ENABLED(MAC_PARTITION) || \
  228. CONFIG_IS_ENABLED(DOS_PARTITION) || \
  229. CONFIG_IS_ENABLED(ISO_PARTITION) || \
  230. CONFIG_IS_ENABLED(AMIGA_PARTITION) || \
  231. CONFIG_IS_ENABLED(EFI_PARTITION)
  232. puts ("\nPartition Map for ");
  233. switch (dev_desc->if_type) {
  234. case IF_TYPE_IDE:
  235. puts ("IDE");
  236. break;
  237. case IF_TYPE_SATA:
  238. puts ("SATA");
  239. break;
  240. case IF_TYPE_SCSI:
  241. puts ("SCSI");
  242. break;
  243. case IF_TYPE_ATAPI:
  244. puts ("ATAPI");
  245. break;
  246. case IF_TYPE_USB:
  247. puts ("USB");
  248. break;
  249. case IF_TYPE_DOC:
  250. puts ("DOC");
  251. break;
  252. case IF_TYPE_MMC:
  253. puts ("MMC");
  254. break;
  255. case IF_TYPE_HOST:
  256. puts ("HOST");
  257. break;
  258. case IF_TYPE_NVME:
  259. puts ("NVMe");
  260. break;
  261. case IF_TYPE_PVBLOCK:
  262. puts("PV BLOCK");
  263. break;
  264. case IF_TYPE_VIRTIO:
  265. puts("VirtIO");
  266. break;
  267. default:
  268. puts ("UNKNOWN");
  269. break;
  270. }
  271. printf (" device %d -- Partition Type: %s\n\n",
  272. dev_desc->devnum, type);
  273. #endif /* any CONFIG_..._PARTITION */
  274. }
  275. void part_print(struct blk_desc *dev_desc)
  276. {
  277. struct part_driver *drv;
  278. drv = part_driver_lookup_type(dev_desc);
  279. if (!drv) {
  280. printf("## Unknown partition table type %x\n",
  281. dev_desc->part_type);
  282. return;
  283. }
  284. PRINTF("## Testing for valid %s partition ##\n", drv->name);
  285. print_part_header(drv->name, dev_desc);
  286. if (drv->print)
  287. drv->print(dev_desc);
  288. }
  289. #endif /* CONFIG_HAVE_BLOCK_DEVICE */
  290. int part_get_info(struct blk_desc *dev_desc, int part,
  291. struct disk_partition *info)
  292. {
  293. #ifdef CONFIG_HAVE_BLOCK_DEVICE
  294. struct part_driver *drv;
  295. #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
  296. /* The common case is no UUID support */
  297. info->uuid[0] = 0;
  298. #endif
  299. #ifdef CONFIG_PARTITION_TYPE_GUID
  300. info->type_guid[0] = 0;
  301. #endif
  302. drv = part_driver_lookup_type(dev_desc);
  303. if (!drv) {
  304. debug("## Unknown partition table type %x\n",
  305. dev_desc->part_type);
  306. return -EPROTONOSUPPORT;
  307. }
  308. if (!drv->get_info) {
  309. PRINTF("## Driver %s does not have the get_info() method\n",
  310. drv->name);
  311. return -ENOSYS;
  312. }
  313. if (drv->get_info(dev_desc, part, info) == 0) {
  314. PRINTF("## Valid %s partition found ##\n", drv->name);
  315. return 0;
  316. }
  317. #endif /* CONFIG_HAVE_BLOCK_DEVICE */
  318. return -1;
  319. }
  320. int part_get_info_whole_disk(struct blk_desc *dev_desc,
  321. struct disk_partition *info)
  322. {
  323. info->start = 0;
  324. info->size = dev_desc->lba;
  325. info->blksz = dev_desc->blksz;
  326. info->bootable = 0;
  327. strcpy((char *)info->type, BOOT_PART_TYPE);
  328. strcpy((char *)info->name, "Whole Disk");
  329. #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
  330. info->uuid[0] = 0;
  331. #endif
  332. #ifdef CONFIG_PARTITION_TYPE_GUID
  333. info->type_guid[0] = 0;
  334. #endif
  335. return 0;
  336. }
  337. int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
  338. struct blk_desc **dev_desc)
  339. {
  340. char *ep;
  341. char *dup_str = NULL;
  342. const char *dev_str, *hwpart_str;
  343. int dev, hwpart;
  344. hwpart_str = strchr(dev_hwpart_str, '.');
  345. if (hwpart_str) {
  346. dup_str = strdup(dev_hwpart_str);
  347. dup_str[hwpart_str - dev_hwpart_str] = 0;
  348. dev_str = dup_str;
  349. hwpart_str++;
  350. } else {
  351. dev_str = dev_hwpart_str;
  352. hwpart = 0;
  353. }
  354. dev = simple_strtoul(dev_str, &ep, 16);
  355. if (*ep) {
  356. printf("** Bad device specification %s %s **\n",
  357. ifname, dev_str);
  358. dev = -EINVAL;
  359. goto cleanup;
  360. }
  361. if (hwpart_str) {
  362. hwpart = simple_strtoul(hwpart_str, &ep, 16);
  363. if (*ep) {
  364. printf("** Bad HW partition specification %s %s **\n",
  365. ifname, hwpart_str);
  366. dev = -EINVAL;
  367. goto cleanup;
  368. }
  369. }
  370. *dev_desc = get_dev_hwpart(ifname, dev, hwpart);
  371. if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
  372. debug("** Bad device %s %s **\n", ifname, dev_hwpart_str);
  373. dev = -ENOENT;
  374. goto cleanup;
  375. }
  376. #ifdef CONFIG_HAVE_BLOCK_DEVICE
  377. /*
  378. * Updates the partition table for the specified hw partition.
  379. * Always should be done, otherwise hw partition 0 will return stale
  380. * data after displaying a non-zero hw partition.
  381. */
  382. part_init(*dev_desc);
  383. #endif
  384. cleanup:
  385. free(dup_str);
  386. return dev;
  387. }
  388. #define PART_UNSPECIFIED -2
  389. #define PART_AUTO -1
  390. int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
  391. struct blk_desc **dev_desc,
  392. struct disk_partition *info, int allow_whole_dev)
  393. {
  394. int ret = -1;
  395. const char *part_str;
  396. char *dup_str = NULL;
  397. const char *dev_str;
  398. int dev;
  399. char *ep;
  400. int p;
  401. int part;
  402. struct disk_partition tmpinfo;
  403. #ifdef CONFIG_SANDBOX
  404. /*
  405. * Special-case a pseudo block device "hostfs", to allow access to the
  406. * host's own filesystem.
  407. */
  408. if (0 == strcmp(ifname, "hostfs")) {
  409. *dev_desc = NULL;
  410. info->start = 0;
  411. info->size = 0;
  412. info->blksz = 0;
  413. info->bootable = 0;
  414. strcpy((char *)info->type, BOOT_PART_TYPE);
  415. strcpy((char *)info->name, "Sandbox host");
  416. #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
  417. info->uuid[0] = 0;
  418. #endif
  419. #ifdef CONFIG_PARTITION_TYPE_GUID
  420. info->type_guid[0] = 0;
  421. #endif
  422. return 0;
  423. }
  424. #endif
  425. #ifdef CONFIG_CMD_UBIFS
  426. /*
  427. * Special-case ubi, ubi goes through a mtd, rather than through
  428. * a regular block device.
  429. */
  430. if (0 == strcmp(ifname, "ubi")) {
  431. if (!ubifs_is_mounted()) {
  432. printf("UBIFS not mounted, use ubifsmount to mount volume first!\n");
  433. return -1;
  434. }
  435. *dev_desc = NULL;
  436. memset(info, 0, sizeof(*info));
  437. strcpy((char *)info->type, BOOT_PART_TYPE);
  438. strcpy((char *)info->name, "UBI");
  439. #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
  440. info->uuid[0] = 0;
  441. #endif
  442. return 0;
  443. }
  444. #endif
  445. /* If no dev_part_str, use bootdevice environment variable */
  446. if (!dev_part_str || !strlen(dev_part_str) ||
  447. !strcmp(dev_part_str, "-"))
  448. dev_part_str = env_get("bootdevice");
  449. /* If still no dev_part_str, it's an error */
  450. if (!dev_part_str) {
  451. printf("** No device specified **\n");
  452. goto cleanup;
  453. }
  454. /* Separate device and partition ID specification */
  455. part_str = strchr(dev_part_str, ':');
  456. if (part_str) {
  457. dup_str = strdup(dev_part_str);
  458. dup_str[part_str - dev_part_str] = 0;
  459. dev_str = dup_str;
  460. part_str++;
  461. } else {
  462. dev_str = dev_part_str;
  463. }
  464. /* Look up the device */
  465. dev = blk_get_device_by_str(ifname, dev_str, dev_desc);
  466. if (dev < 0)
  467. goto cleanup;
  468. /* Convert partition ID string to number */
  469. if (!part_str || !*part_str) {
  470. part = PART_UNSPECIFIED;
  471. } else if (!strcmp(part_str, "auto")) {
  472. part = PART_AUTO;
  473. } else {
  474. /* Something specified -> use exactly that */
  475. part = (int)simple_strtoul(part_str, &ep, 16);
  476. /*
  477. * Less than whole string converted,
  478. * or request for whole device, but caller requires partition.
  479. */
  480. if (*ep || (part == 0 && !allow_whole_dev)) {
  481. printf("** Bad partition specification %s %s **\n",
  482. ifname, dev_part_str);
  483. goto cleanup;
  484. }
  485. }
  486. /*
  487. * No partition table on device,
  488. * or user requested partition 0 (entire device).
  489. */
  490. if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) ||
  491. (part == 0)) {
  492. if (!(*dev_desc)->lba) {
  493. printf("** Bad device size - %s %s **\n", ifname,
  494. dev_str);
  495. goto cleanup;
  496. }
  497. /*
  498. * If user specified a partition ID other than 0,
  499. * or the calling command only accepts partitions,
  500. * it's an error.
  501. */
  502. if ((part > 0) || (!allow_whole_dev)) {
  503. printf("** No partition table - %s %s **\n", ifname,
  504. dev_str);
  505. goto cleanup;
  506. }
  507. (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
  508. part_get_info_whole_disk(*dev_desc, info);
  509. ret = 0;
  510. goto cleanup;
  511. }
  512. /*
  513. * Now there's known to be a partition table,
  514. * not specifying a partition means to pick partition 1.
  515. */
  516. if (part == PART_UNSPECIFIED)
  517. part = 1;
  518. /*
  519. * If user didn't specify a partition number, or did specify something
  520. * other than "auto", use that partition number directly.
  521. */
  522. if (part != PART_AUTO) {
  523. ret = part_get_info(*dev_desc, part, info);
  524. if (ret) {
  525. printf("** Invalid partition %d **\n", part);
  526. goto cleanup;
  527. }
  528. } else {
  529. /*
  530. * Find the first bootable partition.
  531. * If none are bootable, fall back to the first valid partition.
  532. */
  533. part = 0;
  534. for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
  535. ret = part_get_info(*dev_desc, p, info);
  536. if (ret)
  537. continue;
  538. /*
  539. * First valid partition, or new better partition?
  540. * If so, save partition ID.
  541. */
  542. if (!part || info->bootable)
  543. part = p;
  544. /* Best possible partition? Stop searching. */
  545. if (info->bootable)
  546. break;
  547. /*
  548. * We now need to search further for best possible.
  549. * If we what we just queried was the best so far,
  550. * save the info since we over-write it next loop.
  551. */
  552. if (part == p)
  553. tmpinfo = *info;
  554. }
  555. /* If we found any acceptable partition */
  556. if (part) {
  557. /*
  558. * If we searched all possible partition IDs,
  559. * return the first valid partition we found.
  560. */
  561. if (p == MAX_SEARCH_PARTITIONS + 1)
  562. *info = tmpinfo;
  563. } else {
  564. printf("** No valid partitions found **\n");
  565. ret = -1;
  566. goto cleanup;
  567. }
  568. }
  569. if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
  570. printf("** Invalid partition type \"%.32s\""
  571. " (expect \"" BOOT_PART_TYPE "\")\n",
  572. info->type);
  573. ret = -1;
  574. goto cleanup;
  575. }
  576. (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
  577. ret = part;
  578. goto cleanup;
  579. cleanup:
  580. free(dup_str);
  581. return ret;
  582. }
  583. int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
  584. struct disk_partition *info, int part_type)
  585. {
  586. struct part_driver *part_drv;
  587. int ret;
  588. int i;
  589. part_drv = part_driver_lookup_type(dev_desc);
  590. if (!part_drv)
  591. return -1;
  592. for (i = 1; i < part_drv->max_entries; i++) {
  593. ret = part_drv->get_info(dev_desc, i, info);
  594. if (ret != 0) {
  595. /* no more entries in table */
  596. break;
  597. }
  598. if (strcmp(name, (const char *)info->name) == 0) {
  599. /* matched */
  600. return i;
  601. }
  602. }
  603. return -1;
  604. }
  605. int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
  606. struct disk_partition *info)
  607. {
  608. return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
  609. }
  610. /**
  611. * Get partition info from device number and partition name.
  612. *
  613. * Parse a device number and partition name string in the form of
  614. * "device_num#partition_name", for example "0#misc". If the partition
  615. * is found, sets dev_desc and part_info accordingly with the information
  616. * of the partition with the given partition_name.
  617. *
  618. * @param[in] dev_iface Device interface
  619. * @param[in] dev_part_str Input string argument, like "0#misc"
  620. * @param[out] dev_desc Place to store the device description pointer
  621. * @param[out] part_info Place to store the partition information
  622. * @return 0 on success, or a negative on error
  623. */
  624. static int part_get_info_by_dev_and_name(const char *dev_iface,
  625. const char *dev_part_str,
  626. struct blk_desc **dev_desc,
  627. struct disk_partition *part_info)
  628. {
  629. char *ep;
  630. const char *part_str;
  631. int dev_num;
  632. part_str = strchr(dev_part_str, '#');
  633. if (!part_str || part_str == dev_part_str)
  634. return -EINVAL;
  635. dev_num = simple_strtoul(dev_part_str, &ep, 16);
  636. if (ep != part_str) {
  637. /* Not all the first part before the # was parsed. */
  638. return -EINVAL;
  639. }
  640. part_str++;
  641. *dev_desc = blk_get_dev(dev_iface, dev_num);
  642. if (!*dev_desc) {
  643. printf("Could not find %s %d\n", dev_iface, dev_num);
  644. return -EINVAL;
  645. }
  646. if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
  647. printf("Could not find \"%s\" partition\n", part_str);
  648. return -EINVAL;
  649. }
  650. return 0;
  651. }
  652. int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
  653. const char *dev_part_str,
  654. struct blk_desc **dev_desc,
  655. struct disk_partition *part_info)
  656. {
  657. /* Split the part_name if passed as "$dev_num#part_name". */
  658. if (!part_get_info_by_dev_and_name(dev_iface, dev_part_str,
  659. dev_desc, part_info))
  660. return 0;
  661. /*
  662. * Couldn't lookup by name, try looking up the partition description
  663. * directly.
  664. */
  665. if (blk_get_device_part_str(dev_iface, dev_part_str,
  666. dev_desc, part_info, 1) < 0) {
  667. printf("Couldn't find partition %s %s\n",
  668. dev_iface, dev_part_str);
  669. return -EINVAL;
  670. }
  671. return 0;
  672. }
  673. void part_set_generic_name(const struct blk_desc *dev_desc,
  674. int part_num, char *name)
  675. {
  676. char *devtype;
  677. switch (dev_desc->if_type) {
  678. case IF_TYPE_IDE:
  679. case IF_TYPE_SATA:
  680. case IF_TYPE_ATAPI:
  681. devtype = "hd";
  682. break;
  683. case IF_TYPE_SCSI:
  684. devtype = "sd";
  685. break;
  686. case IF_TYPE_USB:
  687. devtype = "usbd";
  688. break;
  689. case IF_TYPE_DOC:
  690. devtype = "docd";
  691. break;
  692. case IF_TYPE_MMC:
  693. case IF_TYPE_SD:
  694. devtype = "mmcsd";
  695. break;
  696. default:
  697. devtype = "xx";
  698. break;
  699. }
  700. sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num);
  701. }