]> git.sur5r.net Git - u-boot/blobdiff - disk/part.c
disk/part: introduce get_device_and_partition
[u-boot] / disk / part.c
index 5c4bf6b6142bb68cc190e1a549d9a054742d7606..f0afd89553345b974c828bde34425da61c9ee9ef 100644 (file)
@@ -70,21 +70,34 @@ static const struct block_drvr block_drvr[] = {
 
 DECLARE_GLOBAL_DATA_PTR;
 
-block_dev_desc_t *get_dev(char* ifname, int dev)
+block_dev_desc_t *get_dev(const char *ifname, int dev)
 {
        const struct block_drvr *drvr = block_drvr;
        block_dev_desc_t* (*reloc_get_dev)(int dev);
+       char *name;
+
+       if (!ifname)
+               return NULL;
 
+       name = drvr->name;
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+       name += gd->reloc_off;
+#endif
        while (drvr->name) {
-               reloc_get_dev = drvr->get_dev + gd->reloc_off;
-               if (strncmp(ifname, drvr->name, strlen(drvr->name)) == 0)
+               name = drvr->name;
+               reloc_get_dev = drvr->get_dev;
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+               name += gd->reloc_off;
+               reloc_get_dev += gd->reloc_off;
+#endif
+               if (strncmp(ifname, name, strlen(name)) == 0)
                        return reloc_get_dev(dev);
                drvr++;
        }
        return NULL;
 }
 #else
-block_dev_desc_t *get_dev(char* ifname, int dev)
+block_dev_desc_t *get_dev(const char *ifname, int dev)
 {
        return NULL;
 }
@@ -101,14 +114,36 @@ block_dev_desc_t *get_dev(char* ifname, int dev)
 /*
  * reports device info to the user
  */
-void dev_print (block_dev_desc_t *dev_desc)
-{
+
 #ifdef CONFIG_LBA48
-       uint64_t lba512; /* number of blocks if 512bytes block size */
+typedef uint64_t lba512_t;
 #else
-       lbaint_t lba512;
+typedef lbaint_t lba512_t;
 #endif
 
+/*
+ * Overflowless variant of (block_count * mul_by / div_by)
+ * when div_by > mul_by
+ */
+static lba512_t lba512_muldiv (lba512_t block_count, lba512_t mul_by, lba512_t div_by)
+{
+       lba512_t bc_quot, bc_rem;
+
+       /* x * m / d == x / d * m + (x % d) * m / d */
+       bc_quot = block_count / div_by;
+       bc_rem  = block_count - div_by * bc_quot;
+       return bc_quot * mul_by + (bc_rem * mul_by) / div_by;
+}
+
+void dev_print (block_dev_desc_t *dev_desc)
+{
+       lba512_t lba512; /* number of blocks if 512bytes block size */
+
+       if (dev_desc->type == DEV_TYPE_UNKNOWN) {
+               puts ("not available\n");
+               return;
+       }
+
        switch (dev_desc->if_type) {
        case IF_TYPE_SCSI:
                printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
@@ -117,6 +152,7 @@ void dev_print (block_dev_desc_t *dev_desc)
                        dev_desc->product,
                        dev_desc->revision);
                break;
+       case IF_TYPE_ATAPI:
        case IF_TYPE_IDE:
        case IF_TYPE_SATA:
                printf ("Model: %s Firm: %s Ser#: %s\n",
@@ -124,9 +160,22 @@ void dev_print (block_dev_desc_t *dev_desc)
                        dev_desc->revision,
                        dev_desc->product);
                break;
+       case IF_TYPE_SD:
+       case IF_TYPE_MMC:
+       case IF_TYPE_USB:
+               printf ("Vendor: %s Rev: %s Prod: %s\n",
+                       dev_desc->vendor,
+                       dev_desc->revision,
+                       dev_desc->product);
+               break;
+       case IF_TYPE_DOC:
+               puts("device type DOC\n");
+               return;
        case IF_TYPE_UNKNOWN:
+               puts("device type unknown\n");
+               return;
        default:
-               puts ("not available\n");
+               printf("Unhandled device type: %i\n", dev_desc->if_type);
                return;
        }
        puts ("            Type: ");
@@ -157,8 +206,9 @@ void dev_print (block_dev_desc_t *dev_desc)
                lba = dev_desc->lba;
 
                lba512 = (lba * (dev_desc->blksz/512));
-               mb = (10 * lba512) / 2048;      /* 2048 = (1024 * 1024) / 512 MB */
                /* round to 1 digit */
+               mb = lba512_muldiv(lba512, 10, 2048);   /* 2048 = (1024 * 1024) / 512 MB */
+
                mb_quot = mb / 10;
                mb_rem  = mb - (10 * mb_quot);
 
@@ -169,8 +219,8 @@ void dev_print (block_dev_desc_t *dev_desc)
                if (dev_desc->lba48)
                        printf ("            Supports 48-bit addressing\n");
 #endif
-#if defined(CFG_64BIT_LBA) && defined(CFG_64BIT_VSPRINTF)
-               printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%qd x %ld)\n",
+#if defined(CONFIG_SYS_64BIT_LBA)
+               printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%Ld x %ld)\n",
                        mb_quot, mb_rem,
                        gb_quot, gb_rem,
                        lba,
@@ -193,12 +243,13 @@ void dev_print (block_dev_desc_t *dev_desc)
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC)               || \
-     defined(CONFIG_SYSTEMACE)          )
+     defined(CONFIG_SYSTEMACE) )
 
 #if defined(CONFIG_MAC_PARTITION) || \
     defined(CONFIG_DOS_PARTITION) || \
     defined(CONFIG_ISO_PARTITION) || \
-    defined(CONFIG_AMIGA_PARTITION)
+    defined(CONFIG_AMIGA_PARTITION) || \
+    defined(CONFIG_EFI_PARTITION)
 
 void init_part (block_dev_desc_t * dev_desc)
 {
@@ -216,6 +267,14 @@ void init_part (block_dev_desc_t * dev_desc)
        }
 #endif
 
+/* must be placed before DOS partition detection */
+#ifdef CONFIG_EFI_PARTITION
+       if (test_part_efi(dev_desc) == 0) {
+               dev_desc->part_type = PART_TYPE_EFI;
+               return;
+       }
+#endif
+
 #ifdef CONFIG_DOS_PARTITION
        if (test_part_dos(dev_desc) == 0) {
                dev_desc->part_type = PART_TYPE_DOS;
@@ -229,55 +288,10 @@ void init_part (block_dev_desc_t * dev_desc)
            return;
        }
 #endif
+       dev_desc->part_type = PART_TYPE_UNKNOWN;
 }
 
 
-int get_partition_info (block_dev_desc_t *dev_desc, int part
-                                       , disk_partition_t *info)
-{
-       switch (dev_desc->part_type) {
-#ifdef CONFIG_MAC_PARTITION
-       case PART_TYPE_MAC:
-               if (get_partition_info_mac(dev_desc,part,info) == 0) {
-                       PRINTF ("## Valid MAC partition found ##\n");
-                       return (0);
-               }
-               break;
-#endif
-
-#ifdef CONFIG_DOS_PARTITION
-       case PART_TYPE_DOS:
-               if (get_partition_info_dos(dev_desc,part,info) == 0) {
-                       PRINTF ("## Valid DOS partition found ##\n");
-                       return (0);
-               }
-               break;
-#endif
-
-#ifdef CONFIG_ISO_PARTITION
-       case PART_TYPE_ISO:
-               if (get_partition_info_iso(dev_desc,part,info) == 0) {
-                       PRINTF ("## Valid ISO boot partition found ##\n");
-                       return (0);
-               }
-               break;
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
-       case PART_TYPE_AMIGA:
-           if (get_partition_info_amiga(dev_desc, part, info) == 0)
-           {
-               PRINTF ("## Valid Amiga partition found ##\n");
-               return (0);
-           }
-           break;
-#endif
-       default:
-               break;
-       }
-       return (-1);
-}
-
 static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
 {
        puts ("\nPartition Map for ");
@@ -300,6 +314,9 @@ static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
        case IF_TYPE_DOC:
                puts ("DOC");
                break;
+       case IF_TYPE_MMC:
+               puts ("MMC");
+               break;
        default:
                puts ("UNKNOWN");
                break;
@@ -342,14 +359,150 @@ void print_part (block_dev_desc_t * dev_desc)
            print_part_amiga (dev_desc);
            return;
 #endif
+
+#ifdef CONFIG_EFI_PARTITION
+       case PART_TYPE_EFI:
+               PRINTF ("## Testing for valid EFI partition ##\n");
+               print_part_header ("EFI", dev_desc);
+               print_part_efi (dev_desc);
+               return;
+#endif
        }
        puts ("## Unknown partition table\n");
 }
 
 
-#else  /* neither MAC nor DOS nor ISO partition configured */
+#else  /* neither MAC nor DOS nor ISO nor AMIGA nor EFI partition configured */
 # error neither CONFIG_MAC_PARTITION nor CONFIG_DOS_PARTITION
-# error nor CONFIG_ISO_PARTITION configured!
+# error nor CONFIG_ISO_PARTITION nor CONFIG_AMIGA_PARTITION
+# error nor CONFIG_EFI_PARTITION configured!
 #endif
 
 #endif
+
+int get_partition_info(block_dev_desc_t *dev_desc, int part
+                                       , disk_partition_t *info)
+{
+#if defined(CONFIG_CMD_IDE) || \
+       defined(CONFIG_CMD_SATA) || \
+       defined(CONFIG_CMD_SCSI) || \
+       defined(CONFIG_CMD_USB) || \
+       defined(CONFIG_MMC) || \
+       defined(CONFIG_SYSTEMACE)
+
+       switch (dev_desc->part_type) {
+#ifdef CONFIG_MAC_PARTITION
+       case PART_TYPE_MAC:
+               if (get_partition_info_mac(dev_desc, part, info) == 0) {
+                       PRINTF("## Valid MAC partition found ##\n");
+                       return 0;
+               }
+               break;
+#endif
+
+#ifdef CONFIG_DOS_PARTITION
+       case PART_TYPE_DOS:
+               if (get_partition_info_dos(dev_desc, part, info) == 0) {
+                       PRINTF("## Valid DOS partition found ##\n");
+                       return 0;
+               }
+               break;
+#endif
+
+#ifdef CONFIG_ISO_PARTITION
+       case PART_TYPE_ISO:
+               if (get_partition_info_iso(dev_desc, part, info) == 0) {
+                       PRINTF("## Valid ISO boot partition found ##\n");
+                       return 0;
+               }
+               break;
+#endif
+
+#ifdef CONFIG_AMIGA_PARTITION
+       case PART_TYPE_AMIGA:
+               if (get_partition_info_amiga(dev_desc, part, info) == 0) {
+                       PRINTF("## Valid Amiga partition found ##\n");
+                       return 0;
+               }
+               break;
+#endif
+
+#ifdef CONFIG_EFI_PARTITION
+       case PART_TYPE_EFI:
+               if (get_partition_info_efi(dev_desc, part, info) == 0) {
+                       PRINTF("## Valid EFI partition found ##\n");
+                       return 0;
+               }
+               break;
+#endif
+       default:
+               break;
+       }
+#endif
+
+       return -1;
+}
+
+int get_device_and_partition(const char *ifname, const char *dev_str,
+                            block_dev_desc_t **dev_desc,
+                            disk_partition_t *info)
+{
+       int ret;
+       char *ep;
+       int dev;
+       block_dev_desc_t *desc;
+       int part = 0;
+       char *part_str;
+
+       if (dev_str)
+               dev = simple_strtoul(dev_str, &ep, 16);
+
+       if (!dev_str || (dev_str == ep)) {
+               dev_str = getenv("bootdevice");
+               if (dev_str)
+                       dev = simple_strtoul(dev_str, &ep, 16);
+               if (!dev_str || (dev_str == ep))
+                       goto err;
+       }
+
+       desc = get_dev(ifname, dev);
+       if (!desc || (desc->type == DEV_TYPE_UNKNOWN))
+               goto err;
+
+       if (desc->part_type == PART_TYPE_UNKNOWN) {
+               /* disk doesn't use partition table */
+               if (!desc->lba) {
+                       printf("**Bad disk size - %s %d:0 **\n", ifname, dev);
+                       return -1;
+               }
+               info->start = 0;
+               info->size = desc->lba;
+               info->blksz = desc->blksz;
+
+               *dev_desc = desc;
+               return 0;
+       }
+
+       part_str = strchr(dev_str, ':');
+       if (part_str)
+               part = (int)simple_strtoul(++part_str, NULL, 16);
+
+       ret = get_partition_info(desc, part, info);
+       if (ret) {
+               printf("** Invalid partition %d, use `dev[:part]' **\n", part);
+               return -1;
+       }
+       if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
+               printf("** Invalid partition type \"%.32s\""
+                       " (expect \"" BOOT_PART_TYPE "\")\n",
+                       info->type);
+               return -1;
+       }
+
+       *dev_desc = desc;
+       return part;
+
+err:
+       puts("** Invalid boot device, use `dev[:part]' **\n");
+       return -1;
+}