]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - disk/part.c
common/cmd_mtdparts.c: print ECC stats along with partition information
[karo-tx-uboot.git] / disk / part.c
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 <ide.h>
11 #include <malloc.h>
12 #include <part.h>
13
14 #undef  PART_DEBUG
15
16 #ifdef  PART_DEBUG
17 #define PRINTF(fmt,args...)     printf (fmt ,##args)
18 #else
19 #define PRINTF(fmt,args...)
20 #endif
21
22 struct block_drvr {
23         char *name;
24         block_dev_desc_t* (*get_dev)(int dev);
25         int (*select_hwpart)(int dev_num, int hwpart);
26 };
27
28 static const struct block_drvr block_drvr[] = {
29 #if defined(CONFIG_CMD_IDE)
30         { .name = "ide", .get_dev = ide_get_dev, },
31 #endif
32 #if defined(CONFIG_CMD_PATA)
33         { .name = "pata", .get_dev = pata_get_dev, },
34 #endif
35 #if defined(CONFIG_CMD_SATA)
36         {.name = "sata", .get_dev = sata_get_dev, },
37 #endif
38 #if defined(CONFIG_CMD_SCSI)
39         { .name = "scsi", .get_dev = scsi_get_dev, },
40 #endif
41 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
42         { .name = "usb", .get_dev = usb_stor_get_dev, },
43 #endif
44 #if defined(CONFIG_MMC)
45         {
46                 .name = "mmc",
47                 .get_dev = mmc_get_dev,
48                 .select_hwpart = mmc_select_hwpart,
49         },
50 #endif
51 #if defined(CONFIG_SYSTEMACE)
52         { .name = "ace", .get_dev = systemace_get_dev, },
53 #endif
54 #if defined(CONFIG_SANDBOX)
55         { .name = "host", .get_dev = host_get_dev, },
56 #endif
57         { },
58 };
59
60 DECLARE_GLOBAL_DATA_PTR;
61
62 #ifdef HAVE_BLOCK_DEVICE
63 static block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
64 {
65         const struct block_drvr *drvr = block_drvr;
66         block_dev_desc_t* (*reloc_get_dev)(int dev);
67         int (*select_hwpart)(int dev_num, int hwpart);
68         char *name;
69         int ret;
70
71         if (!ifname)
72                 return NULL;
73
74         name = drvr->name;
75 #ifdef CONFIG_NEEDS_MANUAL_RELOC
76         name += gd->reloc_off;
77 #endif
78         while (drvr->name) {
79                 name = drvr->name;
80                 reloc_get_dev = drvr->get_dev;
81                 select_hwpart = drvr->select_hwpart;
82 #ifdef CONFIG_NEEDS_MANUAL_RELOC
83                 name += gd->reloc_off;
84                 reloc_get_dev += gd->reloc_off;
85                 if (select_hwpart)
86                         select_hwpart += gd->reloc_off;
87 #endif
88                 if (strncmp(ifname, name, strlen(name)) == 0) {
89                         block_dev_desc_t *dev_desc = reloc_get_dev(dev);
90                         if (!dev_desc)
91                                 return NULL;
92                         if (hwpart == 0 && !select_hwpart)
93                                 return dev_desc;
94                         if (!select_hwpart)
95                                 return NULL;
96                         ret = select_hwpart(dev_desc->dev, hwpart);
97                         if (ret < 0)
98                                 return NULL;
99                         return dev_desc;
100                 }
101                 drvr++;
102         }
103         return NULL;
104 }
105
106 block_dev_desc_t *get_dev(const char *ifname, int dev)
107 {
108         return get_dev_hwpart(ifname, dev, 0);
109 }
110 #else
111 block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
112 {
113         return NULL;
114 }
115
116 block_dev_desc_t *get_dev(const char *ifname, int dev)
117 {
118         return NULL;
119 }
120 #endif
121
122 #ifdef HAVE_BLOCK_DEVICE
123
124 /* ------------------------------------------------------------------------- */
125 /*
126  * reports device info to the user
127  */
128
129 #ifdef CONFIG_LBA48
130 typedef uint64_t lba512_t;
131 #else
132 typedef lbaint_t lba512_t;
133 #endif
134
135 /*
136  * Overflowless variant of (block_count * mul_by / div_by)
137  * when div_by > mul_by
138  */
139 static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by)
140 {
141         lba512_t bc_quot, bc_rem;
142
143         /* x * m / d == x / d * m + (x % d) * m / d */
144         bc_quot = block_count / div_by;
145         bc_rem  = block_count - div_by * bc_quot;
146         return bc_quot * mul_by + (bc_rem * mul_by) / div_by;
147 }
148
149 void dev_print (block_dev_desc_t *dev_desc)
150 {
151         lba512_t lba512; /* number of blocks if 512bytes block size */
152
153         if (dev_desc->type == DEV_TYPE_UNKNOWN) {
154                 puts ("not available\n");
155                 return;
156         }
157
158         switch (dev_desc->if_type) {
159         case IF_TYPE_SCSI:
160                 printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
161                         dev_desc->target,dev_desc->lun,
162                         dev_desc->vendor,
163                         dev_desc->product,
164                         dev_desc->revision);
165                 break;
166         case IF_TYPE_ATAPI:
167         case IF_TYPE_IDE:
168         case IF_TYPE_SATA:
169                 printf ("Model: %s Firm: %s Ser#: %s\n",
170                         dev_desc->vendor,
171                         dev_desc->revision,
172                         dev_desc->product);
173                 break;
174         case IF_TYPE_SD:
175         case IF_TYPE_MMC:
176         case IF_TYPE_USB:
177                 printf ("Vendor: %s Rev: %s Prod: %s\n",
178                         dev_desc->vendor,
179                         dev_desc->revision,
180                         dev_desc->product);
181                 break;
182         case IF_TYPE_DOC:
183                 puts("device type DOC\n");
184                 return;
185         case IF_TYPE_UNKNOWN:
186                 puts("device type unknown\n");
187                 return;
188         default:
189                 printf("Unhandled device type: %i\n", dev_desc->if_type);
190                 return;
191         }
192         puts ("            Type: ");
193         if (dev_desc->removable)
194                 puts ("Removable ");
195         switch (dev_desc->type & 0x1F) {
196         case DEV_TYPE_HARDDISK:
197                 puts ("Hard Disk");
198                 break;
199         case DEV_TYPE_CDROM:
200                 puts ("CD ROM");
201                 break;
202         case DEV_TYPE_OPDISK:
203                 puts ("Optical Device");
204                 break;
205         case DEV_TYPE_TAPE:
206                 puts ("Tape");
207                 break;
208         default:
209                 printf ("# %02X #", dev_desc->type & 0x1F);
210                 break;
211         }
212         puts ("\n");
213         if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
214                 ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
215                 lbaint_t lba;
216
217                 lba = dev_desc->lba;
218
219                 lba512 = (lba * (dev_desc->blksz/512));
220                 /* round to 1 digit */
221                 /* 2048 = (1024 * 1024) / 512 MB */
222                 mb = lba512_muldiv(lba512, 10, 2048);
223
224                 mb_quot = mb / 10;
225                 mb_rem  = mb - (10 * mb_quot);
226
227                 gb = mb / 1024;
228                 gb_quot = gb / 10;
229                 gb_rem  = gb - (10 * gb_quot);
230 #ifdef CONFIG_LBA48
231                 if (dev_desc->lba48)
232                         printf ("            Supports 48-bit addressing\n");
233 #endif
234 #if defined(CONFIG_SYS_64BIT_LBA)
235                 printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%Ld x %ld)\n",
236                         mb_quot, mb_rem,
237                         gb_quot, gb_rem,
238                         lba,
239                         dev_desc->blksz);
240 #else
241                 printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n",
242                         mb_quot, mb_rem,
243                         gb_quot, gb_rem,
244                         (ulong)lba,
245                         dev_desc->blksz);
246 #endif
247         } else {
248                 puts ("            Capacity: not available\n");
249         }
250 }
251 #endif
252
253 #ifdef HAVE_BLOCK_DEVICE
254
255 void init_part(block_dev_desc_t *dev_desc)
256 {
257 #ifdef CONFIG_ISO_PARTITION
258         if (test_part_iso(dev_desc) == 0) {
259                 dev_desc->part_type = PART_TYPE_ISO;
260                 return;
261         }
262 #endif
263
264 #ifdef CONFIG_MAC_PARTITION
265         if (test_part_mac(dev_desc) == 0) {
266                 dev_desc->part_type = PART_TYPE_MAC;
267                 return;
268         }
269 #endif
270
271 /* must be placed before DOS partition detection */
272 #ifdef CONFIG_EFI_PARTITION
273         if (test_part_efi(dev_desc) == 0) {
274                 dev_desc->part_type = PART_TYPE_EFI;
275                 return;
276         }
277 #endif
278
279 #ifdef CONFIG_DOS_PARTITION
280         if (test_part_dos(dev_desc) == 0) {
281                 dev_desc->part_type = PART_TYPE_DOS;
282                 return;
283         }
284 #endif
285
286 #ifdef CONFIG_AMIGA_PARTITION
287         if (test_part_amiga(dev_desc) == 0) {
288             dev_desc->part_type = PART_TYPE_AMIGA;
289             return;
290         }
291 #endif
292         dev_desc->part_type = PART_TYPE_UNKNOWN;
293 }
294
295
296 #if defined(CONFIG_MAC_PARTITION) || \
297         defined(CONFIG_DOS_PARTITION) || \
298         defined(CONFIG_ISO_PARTITION) || \
299         defined(CONFIG_AMIGA_PARTITION) || \
300         defined(CONFIG_EFI_PARTITION)
301
302 static void print_part_header(const char *type, block_dev_desc_t *dev_desc)
303 {
304         puts ("\nPartition Map for ");
305         switch (dev_desc->if_type) {
306         case IF_TYPE_IDE:
307                 puts ("IDE");
308                 break;
309         case IF_TYPE_SATA:
310                 puts ("SATA");
311                 break;
312         case IF_TYPE_SCSI:
313                 puts ("SCSI");
314                 break;
315         case IF_TYPE_ATAPI:
316                 puts ("ATAPI");
317                 break;
318         case IF_TYPE_USB:
319                 puts ("USB");
320                 break;
321         case IF_TYPE_DOC:
322                 puts ("DOC");
323                 break;
324         case IF_TYPE_MMC:
325                 puts ("MMC");
326                 break;
327         case IF_TYPE_HOST:
328                 puts("HOST");
329                 break;
330         default:
331                 puts ("UNKNOWN");
332                 break;
333         }
334         printf (" device %d  --   Partition Type: %s\n\n",
335                         dev_desc->dev, type);
336 }
337
338 #endif /* any CONFIG_..._PARTITION */
339
340 void print_part(block_dev_desc_t * dev_desc)
341 {
342
343                 switch (dev_desc->part_type) {
344 #ifdef CONFIG_MAC_PARTITION
345         case PART_TYPE_MAC:
346                 PRINTF ("## Testing for valid MAC partition ##\n");
347                 print_part_header ("MAC", dev_desc);
348                 print_part_mac (dev_desc);
349                 return;
350 #endif
351 #ifdef CONFIG_DOS_PARTITION
352         case PART_TYPE_DOS:
353                 PRINTF ("## Testing for valid DOS partition ##\n");
354                 print_part_header ("DOS", dev_desc);
355                 print_part_dos (dev_desc);
356                 return;
357 #endif
358
359 #ifdef CONFIG_ISO_PARTITION
360         case PART_TYPE_ISO:
361                 PRINTF ("## Testing for valid ISO Boot partition ##\n");
362                 print_part_header ("ISO", dev_desc);
363                 print_part_iso (dev_desc);
364                 return;
365 #endif
366
367 #ifdef CONFIG_AMIGA_PARTITION
368         case PART_TYPE_AMIGA:
369             PRINTF ("## Testing for a valid Amiga partition ##\n");
370             print_part_header ("AMIGA", dev_desc);
371             print_part_amiga (dev_desc);
372             return;
373 #endif
374
375 #ifdef CONFIG_EFI_PARTITION
376         case PART_TYPE_EFI:
377                 PRINTF ("## Testing for valid EFI partition ##\n");
378                 print_part_header ("EFI", dev_desc);
379                 print_part_efi (dev_desc);
380                 return;
381 #endif
382         }
383         puts ("## Unknown partition table\n");
384 }
385
386 #endif /* HAVE_BLOCK_DEVICE */
387
388 int get_partition_info(block_dev_desc_t *dev_desc, int part,
389                        disk_partition_t *info)
390 {
391 #ifdef HAVE_BLOCK_DEVICE
392
393 #ifdef CONFIG_PARTITION_UUIDS
394         /* The common case is no UUID support */
395         info->uuid[0] = 0;
396 #endif
397
398         switch (dev_desc->part_type) {
399 #ifdef CONFIG_MAC_PARTITION
400         case PART_TYPE_MAC:
401                 if (get_partition_info_mac(dev_desc, part, info) == 0) {
402                         PRINTF("## Valid MAC partition found ##\n");
403                         return 0;
404                 }
405                 break;
406 #endif
407
408 #ifdef CONFIG_DOS_PARTITION
409         case PART_TYPE_DOS:
410                 if (get_partition_info_dos(dev_desc, part, info) == 0) {
411                         PRINTF("## Valid DOS partition found ##\n");
412                         return 0;
413                 }
414                 break;
415 #endif
416
417 #ifdef CONFIG_ISO_PARTITION
418         case PART_TYPE_ISO:
419                 if (get_partition_info_iso(dev_desc, part, info) == 0) {
420                         PRINTF("## Valid ISO boot partition found ##\n");
421                         return 0;
422                 }
423                 break;
424 #endif
425
426 #ifdef CONFIG_AMIGA_PARTITION
427         case PART_TYPE_AMIGA:
428                 if (get_partition_info_amiga(dev_desc, part, info) == 0) {
429                         PRINTF("## Valid Amiga partition found ##\n");
430                         return 0;
431                 }
432                 break;
433 #endif
434
435 #ifdef CONFIG_EFI_PARTITION
436         case PART_TYPE_EFI:
437                 if (get_partition_info_efi(dev_desc, part, info) == 0) {
438                         PRINTF("## Valid EFI partition found ##\n");
439                         return 0;
440                 }
441                 break;
442 #endif
443         default:
444                 break;
445         }
446 #endif /* HAVE_BLOCK_DEVICE */
447
448         return -1;
449 }
450
451 int get_device(const char *ifname, const char *dev_hwpart_str,
452                block_dev_desc_t **dev_desc)
453 {
454         char *ep;
455         char *dup_str = NULL;
456         const char *dev_str, *hwpart_str;
457         int dev, hwpart;
458
459         hwpart_str = strchr(dev_hwpart_str, '.');
460         if (hwpart_str) {
461                 dup_str = strdup(dev_hwpart_str);
462                 dup_str[hwpart_str - dev_hwpart_str] = 0;
463                 dev_str = dup_str;
464                 hwpart_str++;
465         } else {
466                 dev_str = dev_hwpart_str;
467                 hwpart = 0;
468         }
469
470         dev = simple_strtoul(dev_str, &ep, 16);
471         if (*ep) {
472                 printf("** Bad device specification %s %s **\n",
473                        ifname, dev_str);
474                 dev = -1;
475                 goto cleanup;
476         }
477
478         if (hwpart_str) {
479                 hwpart = simple_strtoul(hwpart_str, &ep, 16);
480                 if (*ep) {
481                         printf("** Bad HW partition specification %s %s **\n",
482                             ifname, hwpart_str);
483                         dev = -1;
484                         goto cleanup;
485                 }
486         }
487
488         *dev_desc = get_dev_hwpart(ifname, dev, hwpart);
489         if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
490                 printf("** Bad device %s %s **\n", ifname, dev_hwpart_str);
491                 dev = -1;
492                 goto cleanup;
493         }
494
495 cleanup:
496         free(dup_str);
497         return dev;
498 }
499
500 #define PART_UNSPECIFIED -2
501 #define PART_AUTO -1
502 #define MAX_SEARCH_PARTITIONS 16
503 int get_device_and_partition(const char *ifname, const char *dev_part_str,
504                              block_dev_desc_t **dev_desc,
505                              disk_partition_t *info, int allow_whole_dev)
506 {
507         int ret = -1;
508         const char *part_str;
509         char *dup_str = NULL;
510         const char *dev_str;
511         int dev;
512         char *ep;
513         int p;
514         int part;
515         disk_partition_t tmpinfo;
516
517         /*
518          * Special-case a pseudo block device "hostfs", to allow access to the
519          * host's own filesystem.
520          */
521         if (0 == strcmp(ifname, "hostfs")) {
522                 *dev_desc = NULL;
523                 info->start = 0;
524                 info->size = 0;
525                 info->blksz = 0;
526                 info->bootable = 0;
527                 strcpy((char *)info->type, BOOT_PART_TYPE);
528                 strcpy((char *)info->name, "Sandbox host");
529 #ifdef CONFIG_PARTITION_UUIDS
530                 info->uuid[0] = 0;
531 #endif
532
533                 return 0;
534         }
535
536         /* If no dev_part_str, use bootdevice environment variable */
537         if (!dev_part_str || !strlen(dev_part_str) ||
538             !strcmp(dev_part_str, "-"))
539                 dev_part_str = getenv("bootdevice");
540
541         /* If still no dev_part_str, it's an error */
542         if (!dev_part_str) {
543                 printf("** No device specified **\n");
544                 goto cleanup;
545         }
546
547         /* Separate device and partition ID specification */
548         part_str = strchr(dev_part_str, ':');
549         if (part_str) {
550                 dup_str = strdup(dev_part_str);
551                 dup_str[part_str - dev_part_str] = 0;
552                 dev_str = dup_str;
553                 part_str++;
554         } else {
555                 dev_str = dev_part_str;
556         }
557
558         /* Look up the device */
559         dev = get_device(ifname, dev_str, dev_desc);
560         if (dev < 0)
561                 goto cleanup;
562
563         /* Convert partition ID string to number */
564         if (!part_str || !*part_str) {
565                 part = PART_UNSPECIFIED;
566         } else if (!strcmp(part_str, "auto")) {
567                 part = PART_AUTO;
568         } else {
569                 /* Something specified -> use exactly that */
570                 part = (int)simple_strtoul(part_str, &ep, 16);
571                 /*
572                  * Less than whole string converted,
573                  * or request for whole device, but caller requires partition.
574                  */
575                 if (*ep || (part == 0 && !allow_whole_dev)) {
576                         printf("** Bad partition specification %s %s **\n",
577                             ifname, dev_part_str);
578                         goto cleanup;
579                 }
580         }
581
582         /*
583          * No partition table on device,
584          * or user requested partition 0 (entire device).
585          */
586         if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) ||
587             (part == 0)) {
588                 if (!(*dev_desc)->lba) {
589                         printf("** Bad device size - %s %s **\n", ifname,
590                                dev_str);
591                         goto cleanup;
592                 }
593
594                 /*
595                  * If user specified a partition ID other than 0,
596                  * or the calling command only accepts partitions,
597                  * it's an error.
598                  */
599                 if ((part > 0) || (!allow_whole_dev)) {
600                         printf("** No partition table - %s %s **\n", ifname,
601                                dev_str);
602                         goto cleanup;
603                 }
604
605                 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
606
607                 info->start = 0;
608                 info->size = (*dev_desc)->lba;
609                 info->blksz = (*dev_desc)->blksz;
610                 info->bootable = 0;
611                 strcpy((char *)info->type, BOOT_PART_TYPE);
612                 strcpy((char *)info->name, "Whole Disk");
613 #ifdef CONFIG_PARTITION_UUIDS
614                 info->uuid[0] = 0;
615 #endif
616
617                 ret = 0;
618                 goto cleanup;
619         }
620
621         /*
622          * Now there's known to be a partition table,
623          * not specifying a partition means to pick partition 1.
624          */
625         if (part == PART_UNSPECIFIED)
626                 part = 1;
627
628         /*
629          * If user didn't specify a partition number, or did specify something
630          * other than "auto", use that partition number directly.
631          */
632         if (part != PART_AUTO) {
633                 ret = get_partition_info(*dev_desc, part, info);
634                 if (ret) {
635                         printf("** Invalid partition %d **\n", part);
636                         goto cleanup;
637                 }
638         } else {
639                 /*
640                  * Find the first bootable partition.
641                  * If none are bootable, fall back to the first valid partition.
642                  */
643                 part = 0;
644                 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
645                         ret = get_partition_info(*dev_desc, p, info);
646                         if (ret)
647                                 continue;
648
649                         /*
650                          * First valid partition, or new better partition?
651                          * If so, save partition ID.
652                          */
653                         if (!part || info->bootable)
654                                 part = p;
655
656                         /* Best possible partition? Stop searching. */
657                         if (info->bootable)
658                                 break;
659
660                         /*
661                          * We now need to search further for best possible.
662                          * If we what we just queried was the best so far,
663                          * save the info since we over-write it next loop.
664                          */
665                         if (part == p)
666                                 tmpinfo = *info;
667                 }
668                 /* If we found any acceptable partition */
669                 if (part) {
670                         /*
671                          * If we searched all possible partition IDs,
672                          * return the first valid partition we found.
673                          */
674                         if (p == MAX_SEARCH_PARTITIONS + 1)
675                                 *info = tmpinfo;
676                 } else {
677                         printf("** No valid partitions found **\n");
678                         ret = -1;
679                         goto cleanup;
680                 }
681         }
682         if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
683                 printf("** Invalid partition type \"%.32s\""
684                         " (expect \"" BOOT_PART_TYPE "\")\n",
685                         info->type);
686                 ret  = -1;
687                 goto cleanup;
688         }
689
690         (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
691
692         ret = part;
693         goto cleanup;
694
695 cleanup:
696         free(dup_str);
697         return ret;
698 }