]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - disk/part.c
disk: support devices with HW partitions
[karo-tx-uboot.git] / disk / part.c
index b8c6aac801626f165bab1bb800ccf657c5a944f4..5e10cae015e54e7dc7b5193cd67d5f76ee631582 100644 (file)
@@ -22,6 +22,7 @@
 struct block_drvr {
        char *name;
        block_dev_desc_t* (*get_dev)(int dev);
 struct block_drvr {
        char *name;
        block_dev_desc_t* (*get_dev)(int dev);
+       int (*select_hwpart)(int dev_num, int hwpart);
 };
 
 static const struct block_drvr block_drvr[] = {
 };
 
 static const struct block_drvr block_drvr[] = {
@@ -52,11 +53,13 @@ static const struct block_drvr block_drvr[] = {
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
-block_dev_desc_t *get_dev(const char *ifname, int dev)
+block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
 {
        const struct block_drvr *drvr = block_drvr;
        block_dev_desc_t* (*reloc_get_dev)(int dev);
 {
        const struct block_drvr *drvr = block_drvr;
        block_dev_desc_t* (*reloc_get_dev)(int dev);
+       int (*select_hwpart)(int dev_num, int hwpart);
        char *name;
        char *name;
+       int ret;
 
        if (!ifname)
                return NULL;
 
        if (!ifname)
                return NULL;
@@ -68,17 +71,41 @@ block_dev_desc_t *get_dev(const char *ifname, int dev)
        while (drvr->name) {
                name = drvr->name;
                reloc_get_dev = drvr->get_dev;
        while (drvr->name) {
                name = drvr->name;
                reloc_get_dev = drvr->get_dev;
+               select_hwpart = drvr->select_hwpart;
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
                name += gd->reloc_off;
                reloc_get_dev += gd->reloc_off;
 #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);
+               if (select_hwpart)
+                       select_hwpart += gd->reloc_off;
+#endif
+               if (strncmp(ifname, name, strlen(name)) == 0) {
+                       block_dev_desc_t *dev_desc = reloc_get_dev(dev);
+                       if (!dev_desc)
+                               return NULL;
+                       if (hwpart == -1)
+                               return dev_desc;
+                       if (!select_hwpart)
+                               return NULL;
+                       ret = select_hwpart(dev_desc->dev, hwpart);
+                       if (ret < 0)
+                               return NULL;
+                       return dev_desc;
+               }
                drvr++;
        }
        return NULL;
 }
                drvr++;
        }
        return NULL;
 }
+
+block_dev_desc_t *get_dev(const char *ifname, int dev)
+{
+       return get_dev_hwpart(ifname, dev, -1);
+}
 #else
 #else
+block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
+{
+       return NULL;
+}
+
 block_dev_desc_t *get_dev(const char *ifname, int dev)
 {
        return NULL;
 block_dev_desc_t *get_dev(const char *ifname, int dev)
 {
        return NULL;
@@ -413,25 +440,52 @@ int get_partition_info(block_dev_desc_t *dev_desc, int part
        return -1;
 }
 
        return -1;
 }
 
-int get_device(const char *ifname, const char *dev_str,
+int get_device(const char *ifname, const char *dev_hwpart_str,
               block_dev_desc_t **dev_desc)
 {
        char *ep;
               block_dev_desc_t **dev_desc)
 {
        char *ep;
-       int dev;
+       char *dup_str = NULL;
+       const char *dev_str, *hwpart_str;
+       int dev, hwpart;
+
+       hwpart_str = strchr(dev_hwpart_str, '.');
+       if (hwpart_str) {
+               dup_str = strdup(dev_hwpart_str);
+               dup_str[hwpart_str - dev_hwpart_str] = 0;
+               dev_str = dup_str;
+               hwpart_str++;
+       } else {
+               dev_str = dev_hwpart_str;
+               hwpart = -1;
+       }
 
        dev = simple_strtoul(dev_str, &ep, 16);
        if (*ep) {
                printf("** Bad device specification %s %s **\n",
                       ifname, dev_str);
 
        dev = simple_strtoul(dev_str, &ep, 16);
        if (*ep) {
                printf("** Bad device specification %s %s **\n",
                       ifname, dev_str);
-               return -1;
+               dev = -1;
+               goto cleanup;
+       }
+
+       if (hwpart_str) {
+               hwpart = simple_strtoul(hwpart_str, &ep, 16);
+               if (*ep) {
+                       printf("** Bad HW partition specification %s %s **\n",
+                           ifname, hwpart_str);
+                       dev = -1;
+                       goto cleanup;
+               }
        }
 
        }
 
-       *dev_desc = get_dev(ifname, dev);
+       *dev_desc = get_dev_hwpart(ifname, dev, hwpart);
        if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
        if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
-               printf("** Bad device %s %s **\n", ifname, dev_str);
-               return -1;
+               printf("** Bad device %s %s **\n", ifname, dev_hwpart_str);
+               dev = -1;
+               goto cleanup;
        }
 
        }
 
+cleanup:
+       free(dup_str);
        return dev;
 }
 
        return dev;
 }