diff mbox

[U-Boot,2/4] disk: support devices with HW partitions

Message ID 1399486743-23807-2-git-send-email-swarren@wwwdotorg.org
State Accepted
Delegated to: Pantelis Antoniou
Headers show

Commit Message

Stephen Warren May 7, 2014, 6:19 p.m. UTC
From: Stephen Warren <swarren@nvidia.com>

Some device types (e.g. eMMC) have hardware-level partitions (for eMMC,
separate boot and user data partitions). This change allows the user to
specify the HW partition they wish to access when passing a device ID to
U-Boot Commands such as part, ls, load, ums, etc.

The syntax allows an optional ".$hwpartid" to be appended to the device
name string for those commands.

Existing syntax, for MMC device 0, default HW partition ID, SW partition
ID 1:

ls mmc 0:1 /

New syntax, for MMC device 0, HW partition ID 1 (boot0), SW partition
ID 2:

ls mmc 0.1:2 /

For my purposes, this is most useful for the ums (USB mass storage
gadget) command, but there's no reason not to allow the new syntax
globally.

This patch adds the core support infra-structure. The next patch will
provide the implementation for MMC.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 disk/part.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 64 insertions(+), 10 deletions(-)

Comments

Pantelis Antoniou May 23, 2014, 9:09 a.m. UTC | #1
Hi Stephen,

On May 7, 2014, at 9:19 PM, Stephen Warren wrote:

> From: Stephen Warren <swarren@nvidia.com>
> 
> Some device types (e.g. eMMC) have hardware-level partitions (for eMMC,
> separate boot and user data partitions). This change allows the user to
> specify the HW partition they wish to access when passing a device ID to
> U-Boot Commands such as part, ls, load, ums, etc.
> 
> The syntax allows an optional ".$hwpartid" to be appended to the device
> name string for those commands.
> 
> Existing syntax, for MMC device 0, default HW partition ID, SW partition
> ID 1:
> 
> ls mmc 0:1 /
> 
> New syntax, for MMC device 0, HW partition ID 1 (boot0), SW partition
> ID 2:
> 
> ls mmc 0.1:2 /
> 
> For my purposes, this is most useful for the ums (USB mass storage
> gadget) command, but there's no reason not to allow the new syntax
> globally.
> 
> This patch adds the core support infra-structure. The next patch will
> provide the implementation for MMC.
> 
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> disk/part.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 64 insertions(+), 10 deletions(-)
> 
> diff --git a/disk/part.c b/disk/part.c
> index b8c6aac80162..5e10cae015e5 100644
> --- a/disk/part.c
> +++ b/disk/part.c
> @@ -22,6 +22,7 @@
> 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[] = {
> @@ -52,11 +53,13 @@ static const struct block_drvr block_drvr[] = {
> 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);
> +	int (*select_hwpart)(int dev_num, int hwpart);
> 	char *name;
> +	int ret;
> 
> 	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;
> +		select_hwpart = drvr->select_hwpart;
> #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;
> }
> +
> +block_dev_desc_t *get_dev(const char *ifname, int dev)
> +{
> +	return get_dev_hwpart(ifname, dev, -1);
> +}
> #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;
> @@ -413,25 +440,52 @@ int get_partition_info(block_dev_desc_t *dev_desc, int part
> 	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;
> -	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);
> -		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)) {
> -		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;
> }
> 
> -- 
> 1.8.1.5
> 

Applied

Thanks

-- Pantelis

Acked-by: Pantelis Antoniou <panto@antoniou-consulting.com>
diff mbox

Patch

diff --git a/disk/part.c b/disk/part.c
index b8c6aac80162..5e10cae015e5 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -22,6 +22,7 @@ 
 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[] = {
@@ -52,11 +53,13 @@  static const struct block_drvr block_drvr[] = {
 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);
+	int (*select_hwpart)(int dev_num, int hwpart);
 	char *name;
+	int ret;
 
 	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;
+		select_hwpart = drvr->select_hwpart;
 #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;
 }
+
+block_dev_desc_t *get_dev(const char *ifname, int dev)
+{
+	return get_dev_hwpart(ifname, dev, -1);
+}
 #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;
@@ -413,25 +440,52 @@  int get_partition_info(block_dev_desc_t *dev_desc, int part
 	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;
-	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);
-		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)) {
-		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;
 }