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