disk/part: introduce get_device_and_partition

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 an enhancement over current versions. If no device
or partition is specified on the command line, the bootdevice env variable
will be used (scsiboot does this).

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
diff --git a/disk/part.c b/disk/part.c
index f659cc3..f0afd89 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -70,7 +70,7 @@
 
 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 @@
 	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 @@
 	    return;
 	}
 #endif
+	dev_desc->part_type = PART_TYPE_UNKNOWN;
 }
 
 
@@ -441,3 +442,67 @@
 
 	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;
+}