[U-Boot] [PATCH 3/9] disk/part: introduce get_device_and_partition

Rob Herring
2012-08-23T21:31:44Z

All block device related commands (scsiboot, fatload, ext2ls, etc.) have
simliar duplicated device and partition parsing and selection code. This
adds a common function to replace various implementations.

The new function has some enhancements over current versions. If no device
or partition is specified on the command line, the bootdevice env variable
will be used (scsiboot does this). If the partition is not specified and
the device has partitions, then the first bootable partition will be used.
If a bootable partition is not found, the first valid partition is used.
The ret value is not needed since part will be zero when no partition is
found.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
disk/part.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
include/part.h | 13 ++++++--
2 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/disk/part.c b/disk/part.c
index 76f3939..1284e1a 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -70,7 +70,7 @@ 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);
@@ -97,7 +97,7 @@ block_dev_desc_t *get_dev(char* ifname, int dev)
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;
}
@@ -288,6 +288,7 @@ void init_part (block_dev_desc_t * dev_desc)
return;
}
#endif
+ dev_desc->part_type = PART_TYPE_UNKNOWN;
}

@@ -433,3 +434,88 @@ void print_part (block_dev_desc_t * dev_desc)
#endif

#endif
+
+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 p;
+ int part = 0;
+ char *part_str;
+ disk_partition_t *best_part = NULL;
+
+ 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);
+ } else {
+ /* find the first bootable partition. If none are bootable,
+ * fall back to the first valid partition */
+ for (p = 1; p < 16; p++) {
+ ret = get_partition_info(desc, p, info);
+ if (ret)
+ continue;
+
+ if (!best_part || info->bootable) {
+ best_part = info;
+ part = p;
+ }
+
+ if (info->bootable)
+ break;
+ }
+ info = best_part;
+ if (part)
+ ret = 0;
+ }
+ 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;
+}
diff --git a/include/part.h b/include/part.h
index 447f69d..a6d06f3 100644
--- a/include/part.h
+++ b/include/part.h
@@ -98,7 +98,7 @@ typedef struct disk_partition {

/* Misc _get_dev functions */
#ifdef CONFIG_PARTITIONS
-block_dev_desc_t* get_dev(char* ifname, int dev);
+block_dev_desc_t *get_dev(const char *ifname, int dev);
block_dev_desc_t* ide_get_dev(int dev);
block_dev_desc_t* sata_get_dev(int dev);
block_dev_desc_t* scsi_get_dev(int dev);
@@ -112,8 +112,12 @@ int get_partition_info (block_dev_desc_t * dev_desc, int part, disk_partition_t
void print_part (block_dev_desc_t *dev_desc);
void init_part (block_dev_desc_t *dev_desc);
void dev_print(block_dev_desc_t *dev_desc);
+int get_device_and_partition(const char *ifname, const char *dev_str,
+ block_dev_desc_t **dev_desc,
+ disk_partition_t *info);
#else
-static inline block_dev_desc_t* get_dev(char* ifname, int dev) { return NULL; }
+static inline block_dev_desc_t *get_dev(const char *ifname, int dev)
+{ return NULL; }
static inline block_dev_desc_t* ide_get_dev(int dev) { return NULL; }
static inline block_dev_desc_t* sata_get_dev(int dev) { return NULL; }
static inline block_dev_desc_t* scsi_get_dev(int dev) { return NULL; }
@@ -127,6 +131,11 @@ static inline int get_partition_info (block_dev_desc_t * dev_desc, int part,
static inline void print_part (block_dev_desc_t *dev_desc) {}
static inline void init_part (block_dev_desc_t *dev_desc) {}
static inline void dev_print(block_dev_desc_t *dev_desc) {}
+static inline int get_device_and_partition(const char *ifname,
+ const char *dev_str,
+ block_dev_desc_t **dev_desc,
+ disk_partition_t *info)
+{ *dev_desc = NULL; return -1; }
#endif

#ifdef CONFIG_MAC_PARTITION
--
1.7.9.5