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