All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] cmd: gpt: GPT manipulation improvements
@ 2023-08-15 16:26 Joshua Watt
  2023-08-15 16:26 ` [PATCH 1/6] cmd: gpt: Remove confusing help text Joshua Watt
                   ` (6 more replies)
  0 siblings, 7 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:26 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds several improvements and additions to the gpt command processing,
specifically (although not exclusively) for the purpose of supporting
"ping-pong" booting when doing A/B boot partitions with u-boot itself.

In this mechanism, u-boot must boot up, and then check if the correct
boot partition is active, and if not switch the GPT partition table to
the other boot partition and reboot to activate the other u-boot.

In order to facilitate this, the gpt command needs to be better at
preserving entry attributes when manipulating the partition table. It
also learns two new commands, one which can swap the order of partitions
in the table, and another that lets it change which partitions have the
bootable flag.

Joshua Watt (6):
  cmd: gpt: Remove confusing help text
  cmd: gpt: Add command to set bootable flags
  cmd: gpt: Add gpt_partition_bootable variable
  cmd: gpt: Preserve type GUID if enabled
  cmd: gpt: Preserve bootable flag
  cmd: gpt: Add command to swap partition order

 cmd/gpt.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 154 insertions(+), 6 deletions(-)

-- 
2.33.0


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 1/6] cmd: gpt: Remove confusing help text
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
@ 2023-08-15 16:26 ` Joshua Watt
  2023-08-18 14:23   ` Tom Rini
  2023-08-23 23:57   ` Simon Glass
  2023-08-15 16:26 ` [PATCH 2/6] cmd: gpt: Add command to set bootable flags Joshua Watt
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:26 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

This help text appears to be a fragment of the text shown when
CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 007a68eaa7..e6f7b0319a 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -1060,8 +1060,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      gpt_partition_name, gpt_partition_entry\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
-	" read <interface> <dev>\n"
-	"    - read GPT into a data structure for manipulation\n"
 	" gpt guid <interface> <dev>\n"
 	"    - print disk GUID\n"
 	" gpt guid <interface> <dev> <varname>\n"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 2/6] cmd: gpt: Add command to set bootable flags
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-15 16:26 ` [PATCH 1/6] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-15 16:26 ` Joshua Watt
  2023-08-15 18:39   ` Simon Glass
  2023-08-15 16:26 ` [PATCH 3/6] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:26 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds a command that can be used to modify the GPT partition table to
indicate which partitions should have the bootable flag set

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index e6f7b0319a..a4b8b2b286 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -970,6 +970,80 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 }
 #endif
 
+/**
+ * gpt_set_bootable() - Set bootable flags for partitions
+ *
+ * Sets the bootable flag for any partition names in the comma separated list of
+ * partition names. Any partitions not in the list have their bootable flag
+ * cleared
+ *
+ * @desc: block device descriptor
+ * @name: Comma separated list of partition names
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const part_list)
+{
+	char *name;
+	char disk_guid[UUID_STR_LEN + 1];
+	struct list_head *pos;
+	struct disk_part *curr;
+	struct disk_partition *partitions = NULL;
+	int part_count = 0;
+
+	int ret = get_disk_guid(blk_dev_desc, disk_guid);
+	if (ret < 0)
+		return ret;
+
+	ret = get_gpt_info(blk_dev_desc);
+	if (ret <= 0)
+		goto out;
+
+	part_count = ret;
+	partitions = malloc(sizeof(*partitions) * part_count);
+	if (!partitions) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Copy partitions and clear bootable flag */
+	part_count = 0;
+	list_for_each(pos, &disk_partitions) {
+		curr = list_entry(pos, struct disk_part, list);
+		partitions[part_count] = curr->gpt_part_info;
+		partitions[part_count].bootable &= ~PART_BOOTABLE;
+		part_count++;
+	}
+
+	name = strtok(part_list, ",");
+	while (name) {
+		bool found = false;
+		for (int i = 0; i < part_count; i++) {
+			if (strcmp((char *)partitions[i].name, name) == 0) {
+				partitions[i].bootable |= PART_BOOTABLE;
+				found = true;
+			}
+		}
+
+		if (!found) {
+			printf("Warning: No partition matching '%s' found\n",
+			       name);
+		}
+
+		name = strtok(NULL, ",");
+	}
+
+	ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
+
+out:
+	del_gpt_info();
+
+	if (partitions)
+		free(partitions);
+
+	return ret;
+}
+
 /**
  * do_gpt(): Perform GPT operations
  *
@@ -1028,6 +1102,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		   (strcmp(argv[1], "rename") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
 #endif
+	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
+		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
 	} else {
 		return CMD_RET_USAGE;
 	}
@@ -1081,4 +1157,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
 #endif
+	" gpt set-bootable <interface> <dev> <list>\n"
+	"    - make partition names in list bootable\n"
+	" Example usage:\n"
+	" gpt set-bootable mmc 0 boot_a,boot_b\n"
 );
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 3/6] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-15 16:26 ` [PATCH 1/6] cmd: gpt: Remove confusing help text Joshua Watt
  2023-08-15 16:26 ` [PATCH 2/6] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-15 16:26 ` Joshua Watt
  2023-08-15 16:26 ` [PATCH 4/6] cmd: gpt: Preserve type GUID if enabled Joshua Watt
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:26 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds an additional variable called gpt_partition_bootable that indicates
if the given partition is bootable or not.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index a4b8b2b286..bc08799512 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -723,7 +723,7 @@ static int gpt_enumerate(struct blk_desc *desc)
  * gpt_setenv_part_variables() - setup partition environmental variables
  *
  * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
- * and gpt_partition_size environment variables.
+ * and gpt_partition_size, gpt_partition_bootable environment variables.
  *
  * @pinfo: pointer to disk partition
  * @i: partition entry
@@ -750,6 +750,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
 	if (ret)
 		goto fail;
 
+	ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
+	if (ret)
+		goto fail;
+
 	return 0;
 
 fail:
@@ -1133,7 +1137,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt setenv mmc 0 $name\n"
 	"    - setup environment variables for partition $name:\n"
 	"      gpt_partition_addr, gpt_partition_size,\n"
-	"      gpt_partition_name, gpt_partition_entry\n"
+	"      gpt_partition_name, gpt_partition_entry,\n"
+	"      gpt_partition_bootable\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
 	" gpt guid <interface> <dev>\n"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 4/6] cmd: gpt: Preserve type GUID if enabled
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
                   ` (2 preceding siblings ...)
  2023-08-15 16:26 ` [PATCH 3/6] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-15 16:26 ` Joshua Watt
  2023-08-15 16:26 ` [PATCH 5/6] cmd: gpt: Preserve bootable flag Joshua Watt
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:26 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
preserved when writing out the partition string. It was already
respected when writing out partitions; this ensures that if you capture
the current partition layout and write it back (such as when renaming),
the type GUIDs are preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index bc08799512..c6fbd94ba2 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
 	/* see part.h for definition of struct disk_partition */
 	partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
 	partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
+#endif
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
 		PART_TYPE_LEN);
 	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
 	newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
+		UUID_STR_LEN);
+	newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
 		UUID_STR_LEN);
@@ -252,6 +260,9 @@ static void print_gpt_info(void)
 		       curr->gpt_part_info.name);
 		printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
 		       curr->gpt_part_info.bootable & PART_BOOTABLE);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 		printf("UUID %s\n", curr->gpt_part_info.uuid);
 #endif
@@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 					    curr->gpt_part_info.blksz);
 		strncat(partitions_list, partstr, PART_NAME_LEN + 1);
 
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		strcat(partitions_list, ",type=");
+		strncat(partitions_list, curr->gpt_part_info.type_guid,
+			UUID_STR_LEN + 1);
+#endif
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 5/6] cmd: gpt: Preserve bootable flag
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
                   ` (3 preceding siblings ...)
  2023-08-15 16:26 ` [PATCH 4/6] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-15 16:26 ` Joshua Watt
  2023-08-15 16:27 ` [PATCH 6/6] cmd: gpt: Add command to swap partition order Joshua Watt
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  6 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:26 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Sets the bootable flag when constructing the partition string from the
current partition configuration. This ensures that when the partitions
are written back (for example, when renaming a partition), the flag is
preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index c6fbd94ba2..58564436d3 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -176,6 +176,7 @@ static int calc_parts_list_len(int numparts)
 #ifdef CONFIG_PARTITION_TYPE_GUID
 	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
 #endif
+	partlistlen += numparts * strlen("bootable,");
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -318,6 +319,8 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
+		if (curr->gpt_part_info.bootable & PART_BOOTABLE)
+			strcat(partitions_list, ",bootable");
 		strcat(partitions_list, ";");
 	}
 	return 0;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 6/6] cmd: gpt: Add command to swap partition order
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
                   ` (4 preceding siblings ...)
  2023-08-15 16:26 ` [PATCH 5/6] cmd: gpt: Preserve bootable flag Joshua Watt
@ 2023-08-15 16:27 ` Joshua Watt
  2023-08-23 23:57   ` Simon Glass
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  6 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-15 16:27 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds a command called "gpt swap-postition" which will swap the order two
partitions are listed in the GPT partition table (but leaves them
pointing to the same locations on disk).

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 58564436d3..c8a2b5ae7b 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -859,7 +859,7 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
 
 	if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
-	    (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
+	    (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") && strcmp(subcomm, "swap-position")))
 		return -EINVAL;
 
 	ret = get_disk_guid(dev_desc, disk_guid);
@@ -920,6 +920,48 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 			ret = -EINVAL;
 			goto out;
 		}
+	} else if(!strcmp(subcomm, "swap-position")) {
+		int idx1, idx2;
+		struct disk_partition first, second;
+		idx1 = simple_strtoul(name1, NULL, 10);
+		if (idx1 <= 0 || idx1 > numparts) {
+			printf("Illegal partition number %s\n", name1);
+			ret = -EINVAL;
+			goto out;
+		}
+		idx2 = simple_strtoul(name2, NULL, 10);
+		if (idx2 <= 0 || idx2 > numparts) {
+			printf("Illegal partition number %s\n", name2);
+			ret = -EINVAL;
+			goto out;
+		}
+		if (idx1 == idx2) {
+			printf("Cannot swap partition with itself\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		i = 1;
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (i == idx1) {
+				first = curr->gpt_part_info;
+			} else if (i == idx2) {
+				second = curr->gpt_part_info;
+			}
+			i++;
+		}
+
+		i = 1;
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (i == idx1) {
+				curr->gpt_part_info = second;
+			} else if (i == idx2) {
+				curr->gpt_part_info = first;
+			}
+			i++;
+		}
 	} else { /* rename */
 		if (strlen(name2) > PART_NAME_LEN) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
@@ -1122,7 +1164,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if (strcmp(argv[1], "read") == 0) {
 		ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
 	} else if ((strcmp(argv[1], "swap") == 0) ||
-		   (strcmp(argv[1], "rename") == 0)) {
+		   (strcmp(argv[1], "rename") == 0) ||
+		   (strcmp(argv[1], "swap-position") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
 #endif
 	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
@@ -1175,11 +1218,14 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap <interface> <dev> <name1> <name2>\n"
 	"    - change all partitions named name1 to name2\n"
 	"      and vice-versa\n"
+	" gpt swap-position <interface> <dev> <part1> <part2>\n"
+	"    - Swap the order of name1 with name2 in the partition table\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
 	" Example usage:\n"
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
+	" gpt swap-partitions mmc 0 1 2\n"
 #endif
 	" gpt set-bootable <interface> <dev> <list>\n"
 	"    - make partition names in list bootable\n"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH 2/6] cmd: gpt: Add command to set bootable flags
  2023-08-15 16:26 ` [PATCH 2/6] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-15 18:39   ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-15 18:39 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

Hi Joshua,

On Tue, 15 Aug 2023 at 10:28, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds a command that can be used to modify the GPT partition table to
> indicate which partitions should have the bootable flag set
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 80 insertions(+)

Can you add doc/usage/gpt.rst and a test?

Regards,
Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 1/6] cmd: gpt: Remove confusing help text
  2023-08-15 16:26 ` [PATCH 1/6] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-18 14:23   ` Tom Rini
  2023-08-23 23:57   ` Simon Glass
  1 sibling, 0 replies; 74+ messages in thread
From: Tom Rini @ 2023-08-18 14:23 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

[-- Attachment #1: Type: text/plain, Size: 313 bytes --]

On Tue, Aug 15, 2023 at 10:26:55AM -0600, Joshua Watt wrote:

> This help text appears to be a fragment of the text shown when
> CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.
> 
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements
  2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
                   ` (5 preceding siblings ...)
  2023-08-15 16:27 ` [PATCH 6/6] cmd: gpt: Add command to swap partition order Joshua Watt
@ 2023-08-23 16:47 ` Joshua Watt
  2023-08-23 16:47   ` [PATCH v2 1/8] cmd: gpt: Remove confusing help text Joshua Watt
                     ` (8 more replies)
  6 siblings, 9 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds several improvements and additions to the gpt command processing,
specifically (although not exclusively) for the purpose of supporting
"ping-pong" booting when doing A/B boot partitions with u-boot itself.

In this mechanism, u-boot must boot up, and then check if the correct
boot partition is active, and if not switch the GPT partition table to
the other boot partition and reboot to activate the other u-boot.

In order to facilitate this, the gpt command needs to be better at
preserving entry attributes when manipulating the partition table. It
also learns two new commands, one which can swap the order of partitions
in the table, and another that lets it change which partitions have the
bootable flag.

V2: Add documentation and tests

Joshua Watt (8):
  cmd: gpt: Remove confusing help text
  doc: Add gpt command documentation
  tests: gpt: Remove test order dependency
  cmd: gpt: Add gpt_partition_bootable variable
  cmd: gpt: Add command to set bootable flags
  cmd: gpt: Preserve type GUID if enabled
  cmd: gpt: Preserve bootable flag
  cmd: gpt: Add command to swap partition order

 cmd/gpt.c                 | 159 ++++++++++++++++++++++++++++++++--
 doc/usage/cmd/gpt.rst     | 174 ++++++++++++++++++++++++++++++++++++++
 test/py/tests/test_gpt.py | 151 ++++++++++++++++++++++++++++++---
 3 files changed, 466 insertions(+), 18 deletions(-)
 create mode 100644 doc/usage/cmd/gpt.rst

-- 
2.33.0


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v2 1/8] cmd: gpt: Remove confusing help text
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 18:15     ` Tom Rini
  2023-08-23 16:47   ` [PATCH v2 2/8] doc: Add gpt command documentation Joshua Watt
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

This help text appears to be a fragment of the text shown when
CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 007a68eaa7..e6f7b0319a 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -1060,8 +1060,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      gpt_partition_name, gpt_partition_entry\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
-	" read <interface> <dev>\n"
-	"    - read GPT into a data structure for manipulation\n"
 	" gpt guid <interface> <dev>\n"
 	"    - print disk GUID\n"
 	" gpt guid <interface> <dev> <varname>\n"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 2/8] doc: Add gpt command documentation
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-23 16:47   ` [PATCH v2 1/8] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 18:15     ` Tom Rini
  2023-08-23 23:57     ` Simon Glass
  2023-08-23 16:47   ` [PATCH v2 3/8] tests: gpt: Remove test order dependency Joshua Watt
                     ` (6 subsequent siblings)
  8 siblings, 2 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds initial documentation for the gpt command

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 doc/usage/cmd/gpt.rst | 139 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)
 create mode 100644 doc/usage/cmd/gpt.rst

diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
new file mode 100644
index 0000000000..ea2cf73a60
--- /dev/null
+++ b/doc/usage/cmd/gpt.rst
@@ -0,0 +1,139 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+gpt command
+===========
+
+Synopsis
+--------
+
+::
+
+    gpt repair <interface> <device no>
+    gpt write <interface> <device no> <partition string>
+    gpt verify <interface> <device no> <partition string>
+    gpt setenv <interface> <device no> <partition name>
+    gpt enumerate <interface> <device no>
+    gpt guid <interface> <device no> [<varname>]
+    gpt read <interface> <device no> [<varname>]
+    gpt swap <interface> <dev> <name1> <name2>
+    gpt rename <interface> <dev> <part> <name>
+
+Description
+-----------
+
+The gpt command lets users read, create, modify, or verify the GPT (GUID
+Partition Table) partition layout. 
+
+The syntax of the text description of the partition list is similar to
+the one used by the 'mbr' command.
+
+The partition list may start with a set of parameters for the whole disk:
+
+* uuid_disk (the UUID of the disk)
+
+Following the disk parameters, partitions are specified separated by a ';'.
+Supported partition parameters are:
+
+* name (required)
+* start (required, partition start offset in bytes)
+* size (in bytes or '-' to expand it to the whole free area)
+* bootable (boolean flag)
+* uuid (partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled)
+* type (partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y)
+
+Here is an example how to create a 6 partitions, some of the predefined sizes:
+
+::
+
+    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
+        name=boot,start=4M,size=128M,bootable,type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7,
+        name=rootfs,size=3072M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
+        name=system-data,size=512M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
+        name=[ext],size=-,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
+        name=user,size=-,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
+        name=modules,size=100M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
+        name=ramdisk,size=8M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
+    => gpt write mmc 0 $gpt_parts
+
+
+If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
+will be generated for the partition
+
+The 'gpt verify' command returns 0 if the layout matches the one on the storage
+device or 1 if not. To check if the layout on the MMC #0 storage device
+matches the provided text description one has to issue following command:
+
+::
+
+    => gpt verify mmc 0 $gpt_parts
+
+The verify sub-command is especially useful in the system update scripts:
+
+::
+
+    => if gpt verify mmc 0 $gpt_parts; then
+         echo GPT layout needs to be updated
+         ...
+       fi
+
+The 'gpt write' command returns 0 on success write or 1 on failure.
+
+The 'gpt setenv' command will set a series of environment variables with
+information about a particular partition. The variables are:
+
+* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
+* gpt_partition_size (the size of the partition, in hexadecimal blocks)
+* gpt_partition_name (the name of the partition)
+* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
+
+To get the information about the partition named 'rootfs', issue the following
+command:
+
+::
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_addr}
+    2000
+    => echo ${gpt_partition_size}
+    14a000
+    => echo ${gpt_partition_name}
+    rootfs
+    => echo ${gpt_partition_entry}
+    2
+
+The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
+list of partition names on the device. For example:
+
+::
+    => gpt enumerate
+    => echo gpt_partition_list
+    boot rootfs system-data [ext] user modules ramdisk
+
+The 'gpt guid' command will report the GUID of a disk. If 'varname' is
+specified, the command will set the variable to the GUID, otherwise it will be
+printed out. For example:
+
+::
+    => gpt guid mmc 0
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
+    => gpt guid mmc gpt_disk_uuid
+    => echo ${gpt_disk_uuid}
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
+
+The 'gpt read' command will print out the current state of the GPT partition
+table. If 'varname' is specified, the variable will be filled with a partition
+string as described above that is suitable for passing to other 'gpt' commands.
+If omitted, a human readable description is printed out.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+The 'gpt swap' command changes the names of all partitions that are named
+'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+Configuration
+-------------
+
+To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
+read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 3/8] tests: gpt: Remove test order dependency
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-23 16:47   ` [PATCH v2 1/8] cmd: gpt: Remove confusing help text Joshua Watt
  2023-08-23 16:47   ` [PATCH v2 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 23:57     ` Simon Glass
  2023-08-23 16:47   ` [PATCH v2 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
                     ` (5 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Re-create a clean disk image for each test to prevent modifications from
one test affecting another

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 test/py/tests/test_gpt.py | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 73bfbf77a2..339468bc12 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -61,18 +61,14 @@ class GptTestDiskImage(object):
         cmd = ('cp', persistent, self.path)
         u_boot_utils.run_and_log(u_boot_console, cmd)
 
-gtdi = None
 @pytest.fixture(scope='function')
 def state_disk_image(u_boot_console):
     """pytest fixture to provide a GptTestDiskImage object to tests.
     This is function-scoped because it uses u_boot_console, which is also
-    function-scoped. However, we don't need to actually do any function-scope
-    work, so this simply returns the same object over and over each time."""
+    function-scoped. A new disk is returned each time to prevent tests from
+    interfering with each other."""
 
-    global gtdi
-    if not gtdi:
-        gtdi = GptTestDiskImage(u_boot_console)
-    return gtdi
+    return GptTestDiskImage(u_boot_console)
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
@@ -186,12 +182,12 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
 
     u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"first"' in output
-    assert '0x00001000	0x00001bff	"second"' in output
-    u_boot_console.run_command('gpt swap host 0 first second')
+    assert '0x00000800	0x00000fff	"part1"' in output
+    assert '0x00001000	0x00001bff	"part2"' in output
+    u_boot_console.run_command('gpt swap host 0 part1 part2')
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"second"' in output
-    assert '0x00001000	0x00001bff	"first"' in output
+    assert '0x00000800	0x00000fff	"part2"' in output
+    assert '0x00001000	0x00001bff	"part1"' in output
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 4/8] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                     ` (2 preceding siblings ...)
  2023-08-23 16:47   ` [PATCH v2 3/8] tests: gpt: Remove test order dependency Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 23:57     ` Simon Glass
  2023-08-23 16:47   ` [PATCH v2 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
                     ` (4 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Enric Balletbo i Serra

Adds an additional variable called gpt_partition_bootable that indicates
if the given partition is bootable or not.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 |  9 +++++++--
 doc/usage/cmd/gpt.rst     |  3 +++
 test/py/tests/test_gpt.py | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index e6f7b0319a..7a8990e400 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -723,7 +723,7 @@ static int gpt_enumerate(struct blk_desc *desc)
  * gpt_setenv_part_variables() - setup partition environmental variables
  *
  * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
- * and gpt_partition_size environment variables.
+ * and gpt_partition_size, gpt_partition_bootable environment variables.
  *
  * @pinfo: pointer to disk partition
  * @i: partition entry
@@ -750,6 +750,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
 	if (ret)
 		goto fail;
 
+	ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
+	if (ret)
+		goto fail;
+
 	return 0;
 
 fail:
@@ -1057,7 +1061,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt setenv mmc 0 $name\n"
 	"    - setup environment variables for partition $name:\n"
 	"      gpt_partition_addr, gpt_partition_size,\n"
-	"      gpt_partition_name, gpt_partition_entry\n"
+	"      gpt_partition_name, gpt_partition_entry,\n"
+	"      gpt_partition_bootable\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
 	" gpt guid <interface> <dev>\n"
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index ea2cf73a60..c9d15b2cba 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -85,6 +85,7 @@ information about a particular partition. The variables are:
 * gpt_partition_size (the size of the partition, in hexadecimal blocks)
 * gpt_partition_name (the name of the partition)
 * gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
+* gpt_partition_bootable (1 if the partition is marked as bootable, 0 if not)
 
 To get the information about the partition named 'rootfs', issue the following
 command:
@@ -99,6 +100,8 @@ command:
     rootfs
     => echo ${gpt_partition_entry}
     2
+    => echo ${gpt_partition_bootable}
+    0
 
 The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
 list of partition names on the device. For example:
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 339468bc12..1537ceb8c8 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -49,6 +49,7 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
@@ -117,6 +118,38 @@ def test_gpt_guid(state_disk_image, u_boot_console):
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_setenv(state_disk_image, u_boot_console):
+    """Test the gpt setenv command."""
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt setenv host 0 part1')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part1'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == "1"
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == "1"
+
+    output = u_boot_console.run_command('gpt setenv host 0 part2')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '1000'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == 'c00'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part2'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == "2"
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == "0"
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                     ` (3 preceding siblings ...)
  2023-08-23 16:47   ` [PATCH v2 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 23:57     ` Simon Glass
  2023-08-23 16:47   ` [PATCH v2 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
                     ` (3 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Adds a command that can be used to modify the GPT partition table to
indicate which partitions should have the bootable flag set

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 79 +++++++++++++++++++++++++++++++++++++++
 doc/usage/cmd/gpt.rst     |  9 +++++
 test/py/tests/test_gpt.py | 22 +++++++++++
 3 files changed, 110 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 7a8990e400..70a01f7da1 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -972,6 +972,80 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	free(partitions_list);
 	return ret;
 }
+
+/**
+ * gpt_set_bootable() - Set bootable flags for partitions
+ *
+ * Sets the bootable flag for any partition names in the comma separated list of
+ * partition names. Any partitions not in the list have their bootable flag
+ * cleared
+ *
+ * @desc: block device descriptor
+ * @name: Comma separated list of partition names
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const part_list)
+{
+	char *name;
+	char disk_guid[UUID_STR_LEN + 1];
+	struct list_head *pos;
+	struct disk_part *curr;
+	struct disk_partition *partitions = NULL;
+	int part_count = 0;
+
+	int ret = get_disk_guid(blk_dev_desc, disk_guid);
+	if (ret < 0)
+		return ret;
+
+	ret = get_gpt_info(blk_dev_desc);
+	if (ret <= 0)
+		goto out;
+
+	part_count = ret;
+	partitions = malloc(sizeof(*partitions) * part_count);
+	if (!partitions) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Copy partitions and clear bootable flag */
+	part_count = 0;
+	list_for_each(pos, &disk_partitions) {
+		curr = list_entry(pos, struct disk_part, list);
+		partitions[part_count] = curr->gpt_part_info;
+		partitions[part_count].bootable &= ~PART_BOOTABLE;
+		part_count++;
+	}
+
+	name = strtok(part_list, ",");
+	while (name) {
+		bool found = false;
+		for (int i = 0; i < part_count; i++) {
+			if (strcmp((char *)partitions[i].name, name) == 0) {
+				partitions[i].bootable |= PART_BOOTABLE;
+				found = true;
+			}
+		}
+
+		if (!found) {
+			printf("Warning: No partition matching '%s' found\n",
+			       name);
+		}
+
+		name = strtok(NULL, ",");
+	}
+
+	ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
+
+out:
+	del_gpt_info();
+
+	if (partitions)
+		free(partitions);
+
+	return ret;
+}
 #endif
 
 /**
@@ -1031,6 +1105,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if ((strcmp(argv[1], "swap") == 0) ||
 		   (strcmp(argv[1], "rename") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
+	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
+		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
 #endif
 	} else {
 		return CMD_RET_USAGE;
@@ -1082,8 +1158,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      and vice-versa\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
+	" gpt set-bootable <interface> <dev> <list>\n"
+	"    - make partition names in list bootable\n"
 	" Example usage:\n"
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
+	" gpt set-bootable mmc 0 boot_a,boot_b\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index c9d15b2cba..c7a56ad825 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -17,6 +17,7 @@ Synopsis
     gpt read <interface> <device no> [<varname>]
     gpt swap <interface> <dev> <name1> <name2>
     gpt rename <interface> <dev> <part> <name>
+    gpt set-bootable <interface> <dev> <partition list>
 
 Description
 -----------
@@ -135,6 +136,14 @@ CONFIG_CMD_GPT_RENAME=y is required.
 The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
 CONFIG_CMD_GPT_RENAME=y is required.
 
+The 'gpt set-bootable' command sets the bootable flag for all partitions in the
+table. If the partition name is in 'partition list' (separated by ','), the
+bootable flag is set, otherwise it is cleared. CONFIG_CMD_GPT_RENAME=y is
+required.  For example, to mark only the 'boot' partition as bootable:
+
+::
+    => gpt set-bootable mmc 0 boot
+
 Configuration
 -------------
 
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 1537ceb8c8..8203515e05 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -222,6 +222,28 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part2"' in output
     assert '0x00001000	0x00001bff	"part1"' in output
 
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_set_bootable(state_disk_image, u_boot_console):
+    """Test the gpt set-bootable command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    parts = ('part2', 'part1')
+    for bootable in parts:
+        output = u_boot_console.run_command(f'gpt set-bootable host 0 {bootable}')
+        assert 'success!' in output
+
+        for p in parts:
+            output = u_boot_console.run_command(f'gpt setenv host 0 {p}')
+            assert 'success!' in output
+            output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+            if p == bootable:
+                assert output.rstrip() == '1'
+            else:
+                assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_part')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                     ` (4 preceding siblings ...)
  2023-08-23 16:47   ` [PATCH v2 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 23:57     ` Simon Glass
  2023-08-23 16:47   ` [PATCH v2 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Enric Balletbo i Serra

If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
preserved when writing out the partition string. It was already
respected when writing out partitions; this ensures that if you capture
the current partition layout and write it back (such as when renaming),
the type GUIDs are preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 16 +++++++++++
 test/py/tests/test_gpt.py | 57 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 70a01f7da1..fdd9c429f6 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
 	/* see part.h for definition of struct disk_partition */
 	partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
 	partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
+#endif
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
 		PART_TYPE_LEN);
 	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
 	newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
+		UUID_STR_LEN);
+	newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
 		UUID_STR_LEN);
@@ -252,6 +260,9 @@ static void print_gpt_info(void)
 		       curr->gpt_part_info.name);
 		printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
 		       curr->gpt_part_info.bootable & PART_BOOTABLE);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 		printf("UUID %s\n", curr->gpt_part_info.uuid);
 #endif
@@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 					    curr->gpt_part_info.blksz);
 		strncat(partitions_list, partstr, PART_NAME_LEN + 1);
 
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		strcat(partitions_list, ",type=");
+		strncat(partitions_list, curr->gpt_part_info.type_guid,
+			UUID_STR_LEN + 1);
+#endif
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 8203515e05..f9351f0274 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -16,6 +16,26 @@ the test.
 # Mark all tests here as slow
 pytestmark = pytest.mark.slow
 
+def parse_gpt_parts(s):
+    """Part a partition string into a list of partitions"""
+    parts = []
+    for part_str in s.split(';'):
+        part = {}
+        for option in part_str.split(","):
+            if not option:
+                continue
+
+            if "=" in option:
+                k, v = option.split("=")
+                part[k] = v
+            else:
+                part[option] = True
+
+        if part:
+            parts.append(part)
+
+    return parts
+
 class GptTestDiskImage(object):
     """Disk Image used by the GPT tests."""
 
@@ -49,11 +69,13 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
                     '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
+                    '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
                     persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--load-backup=' + persistent)
@@ -88,6 +110,40 @@ def test_gpt_read(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part1"' in output
     assert '0x00001000	0x00001bff	"part2"' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('partition_type_guid')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_read_var(state_disk_image, u_boot_console):
+    """Test the gpt read command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt read host 0 gpt_parts')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('echo ${gpt_parts}')
+    parts = parse_gpt_parts(output.rstrip())
+
+    assert parts == [
+        {
+            "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
+        },
+        {
+            "name": "part1",
+            "start": "0x100000",
+            "size": "0x100000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+        },
+        {
+            "name": "part2",
+            "start": "0x200000",
+            "size": "0x180000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
+        },
+    ]
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
@@ -263,3 +319,4 @@ def test_gpt_write(state_disk_image, u_boot_console):
     assert '0x00001000	0x00001bff	"second"' in output
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
+
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 7/8] cmd: gpt: Preserve bootable flag
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                     ` (5 preceding siblings ...)
  2023-08-23 16:47   ` [PATCH v2 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-23 23:57     ` Simon Glass
  2023-08-23 16:47   ` [PATCH v2 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Enric Balletbo i Serra

Sets the bootable flag when constructing the partition string from the
current partition configuration. This ensures that when the partitions
are written back (for example, when renaming a partition), the flag is
preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 3 +++
 test/py/tests/test_gpt.py | 1 +
 2 files changed, 4 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index fdd9c429f6..90a60fce8b 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -176,6 +176,7 @@ static int calc_parts_list_len(int numparts)
 #ifdef CONFIG_PARTITION_TYPE_GUID
 	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
 #endif
+	partlistlen += numparts * strlen("bootable,");
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -318,6 +319,8 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
+		if (curr->gpt_part_info.bootable & PART_BOOTABLE)
+			strcat(partitions_list, ",bootable");
 		strcat(partitions_list, ";");
 	}
 	return 0;
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index f9351f0274..6d79d07b09 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -134,6 +134,7 @@ def test_gpt_read_var(state_disk_image, u_boot_console):
             "size": "0x100000",
             "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
             "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+            "bootable": True,
         },
         {
             "name": "part2",
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v2 8/8] cmd: gpt: Add command to swap partition order
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                     ` (6 preceding siblings ...)
  2023-08-23 16:47   ` [PATCH v2 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
@ 2023-08-23 16:47   ` Joshua Watt
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-23 16:47 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Adds a command called "gpt swap-postition" which will swap the order two
partitions are listed in the GPT partition table (but leaves them
pointing to the same locations on disk).

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 50 +++++++++++++++++++++++++++++++++++++--
 doc/usage/cmd/gpt.rst     | 23 ++++++++++++++++++
 test/py/tests/test_gpt.py | 18 ++++++++++++++
 3 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 90a60fce8b..2448889573 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -859,7 +859,7 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
 
 	if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
-	    (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
+	    (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") && strcmp(subcomm, "swap-position")))
 		return -EINVAL;
 
 	ret = get_disk_guid(dev_desc, disk_guid);
@@ -920,6 +920,48 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 			ret = -EINVAL;
 			goto out;
 		}
+	} else if(!strcmp(subcomm, "swap-position")) {
+		int idx1, idx2;
+		struct disk_partition first, second;
+		idx1 = simple_strtoul(name1, NULL, 10);
+		if (idx1 <= 0 || idx1 > numparts) {
+			printf("Illegal partition number %s\n", name1);
+			ret = -EINVAL;
+			goto out;
+		}
+		idx2 = simple_strtoul(name2, NULL, 10);
+		if (idx2 <= 0 || idx2 > numparts) {
+			printf("Illegal partition number %s\n", name2);
+			ret = -EINVAL;
+			goto out;
+		}
+		if (idx1 == idx2) {
+			printf("Cannot swap partition with itself\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		i = 1;
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (i == idx1) {
+				first = curr->gpt_part_info;
+			} else if (i == idx2) {
+				second = curr->gpt_part_info;
+			}
+			i++;
+		}
+
+		i = 1;
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (i == idx1) {
+				curr->gpt_part_info = second;
+			} else if (i == idx2) {
+				curr->gpt_part_info = first;
+			}
+			i++;
+		}
 	} else { /* rename */
 		if (strlen(name2) > PART_NAME_LEN) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
@@ -1122,7 +1164,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if (strcmp(argv[1], "read") == 0) {
 		ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
 	} else if ((strcmp(argv[1], "swap") == 0) ||
-		   (strcmp(argv[1], "rename") == 0)) {
+		   (strcmp(argv[1], "rename") == 0) ||
+		   (strcmp(argv[1], "swap-position") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
 	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
 		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
@@ -1175,6 +1218,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap <interface> <dev> <name1> <name2>\n"
 	"    - change all partitions named name1 to name2\n"
 	"      and vice-versa\n"
+	" gpt swap-position <interface> <dev> <part1> <part2>\n"
+	"    - Swap the order of name1 with name2 in the partition table\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
 	" gpt set-bootable <interface> <dev> <list>\n"
@@ -1183,5 +1228,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
 	" gpt set-bootable mmc 0 boot_a,boot_b\n"
+	" gpt swap-position mmc 0 1 2\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index c7a56ad825..f3f778d383 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -17,6 +17,7 @@ Synopsis
     gpt read <interface> <device no> [<varname>]
     gpt swap <interface> <dev> <name1> <name2>
     gpt rename <interface> <dev> <part> <name>
+    gpt swap-position <interface> <dev> <part1> <part2>
     gpt set-bootable <interface> <dev> <partition list>
 
 Description
@@ -136,6 +137,28 @@ CONFIG_CMD_GPT_RENAME=y is required.
 The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
 CONFIG_CMD_GPT_RENAME=y is required.
 
+The 'gpt swap-position' command swaps the order of two partition index in the
+partition table, but otherwise leaves the actual partition data untouched. For
+example, to swap the order of the 'boot' and 'rootfs' partitions in the disk
+described above, you would do:
+
+::
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    2
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    1
+
+    => gpt swap-position mmc 0 1 2
+
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    1
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    2
+
 The 'gpt set-bootable' command sets the bootable flag for all partitions in the
 table. If the partition name is in 'partition list' (separated by ','), the
 bootable flag is set, otherwise it is cleared. CONFIG_CMD_GPT_RENAME=y is
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 6d79d07b09..af25bcd998 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -321,3 +321,21 @@ def test_gpt_write(state_disk_image, u_boot_console):
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
 
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_swap_position(state_disk_image, u_boot_console):
+    """Test the gpt swap-position command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('part list host 0')
+    assert '1\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '2\t0x00001000\t0x00001bff\t"part2"' in output
+
+    output = u_boot_console.run_command('gpt swap-position host 0 1 2')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('part list host 0')
+    assert '2\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '1\t0x00001000\t0x00001bff\t"part2"' in output
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 1/8] cmd: gpt: Remove confusing help text
  2023-08-23 16:47   ` [PATCH v2 1/8] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-23 18:15     ` Tom Rini
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Rini @ 2023-08-23 18:15 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

[-- Attachment #1: Type: text/plain, Size: 313 bytes --]

On Wed, Aug 23, 2023 at 10:47:37AM -0600, Joshua Watt wrote:

> This help text appears to be a fragment of the text shown when
> CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.
> 
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 2/8] doc: Add gpt command documentation
  2023-08-23 16:47   ` [PATCH v2 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-23 18:15     ` Tom Rini
  2023-08-23 23:57     ` Simon Glass
  1 sibling, 0 replies; 74+ messages in thread
From: Tom Rini @ 2023-08-23 18:15 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

[-- Attachment #1: Type: text/plain, Size: 530 bytes --]

On Wed, Aug 23, 2023 at 10:47:38AM -0600, Joshua Watt wrote:

> Adds initial documentation for the gpt command
> 
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  doc/usage/cmd/gpt.rst | 139 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
>  create mode 100644 doc/usage/cmd/gpt.rst

You need to update the index too so it's included (and doesn't trigger
an error about orphan files).  Please do a 'make htmldocs' to make sure
everything else is clean, thanks.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 1/6] cmd: gpt: Remove confusing help text
  2023-08-15 16:26 ` [PATCH 1/6] cmd: gpt: Remove confusing help text Joshua Watt
  2023-08-18 14:23   ` Tom Rini
@ 2023-08-23 23:57   ` Simon Glass
  1 sibling, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

On Tue, 15 Aug 2023 at 10:28, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> This help text appears to be a fragment of the text shown when
> CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c | 2 --
>  1 file changed, 2 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 2/8] doc: Add gpt command documentation
  2023-08-23 16:47   ` [PATCH v2 2/8] doc: Add gpt command documentation Joshua Watt
  2023-08-23 18:15     ` Tom Rini
@ 2023-08-23 23:57     ` Simon Glass
  1 sibling, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

Hi Joshua,

On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds initial documentation for the gpt command
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  doc/usage/cmd/gpt.rst | 139 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
>  create mode 100644 doc/usage/cmd/gpt.rst
>
> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> new file mode 100644
> index 0000000000..ea2cf73a60
> --- /dev/null
> +++ b/doc/usage/cmd/gpt.rst
> @@ -0,0 +1,139 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +gpt command
> +===========
> +
> +Synopsis
> +--------
> +
> +::
> +
> +    gpt repair <interface> <device no>
> +    gpt write <interface> <device no> <partition string>
> +    gpt verify <interface> <device no> <partition string>
> +    gpt setenv <interface> <device no> <partition name>
> +    gpt enumerate <interface> <device no>
> +    gpt guid <interface> <device no> [<varname>]
> +    gpt read <interface> <device no> [<varname>]
> +    gpt swap <interface> <dev> <name1> <name2>
> +    gpt rename <interface> <dev> <part> <name>
> +
> +Description
> +-----------
> +
> +The gpt command lets users read, create, modify, or verify the GPT (GUID
> +Partition Table) partition layout.
> +
> +The syntax of the text description of the partition list is similar to

By 'text description' do you mean '<partition string>' ?

> +the one used by the 'mbr' command.

OK, but I think you need to show the string  as a list of
semicolon-separated components (or whatever) and then describe them.
As written, this is quite confusing.

> +
> +The partition list may start with a set of parameters for the whole disk:
> +
> +* uuid_disk (the UUID of the disk)
> +
> +Following the disk parameters, partitions are specified separated by a ';'.
> +Supported partition parameters are:
> +
> +* name (required)
> +* start (required, partition start offset in bytes)
> +* size (in bytes or '-' to expand it to the whole free area)
> +* bootable (boolean flag)
> +* uuid (partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled)
> +* type (partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y)
> +
> +Here is an example how to create a 6 partitions, some of the predefined sizes:
> +
> +::
> +
> +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
> +        name=boot,start=4M,size=128M,bootable,type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7,
> +        name=rootfs,size=3072M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
> +        name=system-data,size=512M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
> +        name=[ext],size=-,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
> +        name=user,size=-,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
> +        name=modules,size=100M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;
> +        name=ramdisk,size=8M,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
> +    => gpt write mmc 0 $gpt_parts

Please use lower-case hex

> +
> +
> +If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
> +will be generated for the partition
> +
> +The 'gpt verify' command returns 0 if the layout matches the one on the storage
> +device or 1 if not. To check if the layout on the MMC #0 storage device
> +matches the provided text description one has to issue following command:
> +
> +::
> +
> +    => gpt verify mmc 0 $gpt_parts
> +
> +The verify sub-command is especially useful in the system update scripts:
> +
> +::
> +
> +    => if gpt verify mmc 0 $gpt_parts; then
> +         echo GPT layout needs to be updated
> +         ...
> +       fi
> +
> +The 'gpt write' command returns 0 on success write or 1 on failure.
> +
> +The 'gpt setenv' command will set a series of environment variables with
> +information about a particular partition. The variables are:
> +
> +* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
> +* gpt_partition_size (the size of the partition, in hexadecimal blocks)
> +* gpt_partition_name (the name of the partition)
> +* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
> +
> +To get the information about the partition named 'rootfs', issue the following
> +command:
> +
> +::
> +    => gpt setenv mmc 0 rootfs
> +    => echo ${gpt_partition_addr}
> +    2000
> +    => echo ${gpt_partition_size}
> +    14a000
> +    => echo ${gpt_partition_name}
> +    rootfs
> +    => echo ${gpt_partition_entry}
> +    2
> +
> +The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
> +list of partition names on the device. For example:
> +
> +::
> +    => gpt enumerate
> +    => echo gpt_partition_list
> +    boot rootfs system-data [ext] user modules ramdisk
> +
> +The 'gpt guid' command will report the GUID of a disk. If 'varname' is
> +specified, the command will set the variable to the GUID, otherwise it will be
> +printed out. For example:
> +
> +::
> +    => gpt guid mmc 0
> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> +    => gpt guid mmc gpt_disk_uuid
> +    => echo ${gpt_disk_uuid}
> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> +
> +The 'gpt read' command will print out the current state of the GPT partition
> +table. If 'varname' is specified, the variable will be filled with a partition
> +string as described above that is suitable for passing to other 'gpt' commands.
> +If omitted, a human readable description is printed out.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +The 'gpt swap' command changes the names of all partitions that are named
> +'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +Configuration
> +-------------
> +
> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
> +read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
> --
> 2.33.0
>

Great docs thank you!


- Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 3/8] tests: gpt: Remove test order dependency
  2023-08-23 16:47   ` [PATCH v2 3/8] tests: gpt: Remove test order dependency Joshua Watt
@ 2023-08-23 23:57     ` Simon Glass
  2023-08-24  3:29       ` Joshua Watt
  0 siblings, 1 reply; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

Hi Joshua,

On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Re-create a clean disk image for each test to prevent modifications from
> one test affecting another
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  test/py/tests/test_gpt.py | 20 ++++++++------------
>  1 file changed, 8 insertions(+), 12 deletions(-)

I suppose this is OK, but is it expensive in terms of time?

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-23 16:47   ` [PATCH v2 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-23 23:57     ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds a command that can be used to modify the GPT partition table to
> indicate which partitions should have the bootable flag set
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 | 79 +++++++++++++++++++++++++++++++++++++++
>  doc/usage/cmd/gpt.rst     |  9 +++++
>  test/py/tests/test_gpt.py | 22 +++++++++++
>  3 files changed, 110 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 4/8] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-23 16:47   ` [PATCH v2 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-23 23:57     ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

Hi Joshue,

On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds an additional variable called gpt_partition_bootable that indicates
> if the given partition is bootable or not.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 |  9 +++++++--
>  doc/usage/cmd/gpt.rst     |  3 +++
>  test/py/tests/test_gpt.py | 33 +++++++++++++++++++++++++++++++++
>  3 files changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index e6f7b0319a..7a8990e400 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -723,7 +723,7 @@ static int gpt_enumerate(struct blk_desc *desc)
>   * gpt_setenv_part_variables() - setup partition environmental variables
>   *
>   * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
> - * and gpt_partition_size environment variables.
> + * and gpt_partition_size, gpt_partition_bootable environment variables.
>   *
>   * @pinfo: pointer to disk partition
>   * @i: partition entry
> @@ -750,6 +750,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
>         if (ret)
>                 goto fail;
>
> +       ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
> +       if (ret)
> +               goto fail;
> +
>         return 0;
>
>  fail:
> @@ -1057,7 +1061,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
>         " gpt setenv mmc 0 $name\n"
>         "    - setup environment variables for partition $name:\n"
>         "      gpt_partition_addr, gpt_partition_size,\n"
> -       "      gpt_partition_name, gpt_partition_entry\n"
> +       "      gpt_partition_name, gpt_partition_entry,\n"
> +       "      gpt_partition_bootable\n"

Please use single quotes except for the """ for function headers.

>         " gpt enumerate mmc 0\n"
>         "    - store list of partitions to gpt_partition_list environment variable\n"
>         " gpt guid <interface> <dev>\n"
> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> index ea2cf73a60..c9d15b2cba 100644
> --- a/doc/usage/cmd/gpt.rst
> +++ b/doc/usage/cmd/gpt.rst
> @@ -85,6 +85,7 @@ information about a particular partition. The variables are:
>  * gpt_partition_size (the size of the partition, in hexadecimal blocks)
>  * gpt_partition_name (the name of the partition)
>  * gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
> +* gpt_partition_bootable (1 if the partition is marked as bootable, 0 if not)
>
>  To get the information about the partition named 'rootfs', issue the following
>  command:
> @@ -99,6 +100,8 @@ command:
>      rootfs
>      => echo ${gpt_partition_entry}
>      2
> +    => echo ${gpt_partition_bootable}
> +    0
>
>  The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
>  list of partition names on the device. For example:
> diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
> index 339468bc12..1537ceb8c8 100644
> --- a/test/py/tests/test_gpt.py
> +++ b/test/py/tests/test_gpt.py
> @@ -49,6 +49,7 @@ class GptTestDiskImage(object):
>                  u_boot_utils.run_and_log(u_boot_console, cmd)
>                  # part1 offset 1MB size 1MB
>                  cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
> +                    '-A 1:set:2',
>                      persistent)
>                  # part2 offset 2MB size 1.5MB
>                  u_boot_utils.run_and_log(u_boot_console, cmd)
> @@ -117,6 +118,38 @@ def test_gpt_guid(state_disk_image, u_boot_console):
>      output = u_boot_console.run_command('gpt guid host 0')
>      assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
>
> +@pytest.mark.boardspec('sandbox')
> +@pytest.mark.buildconfigspec('cmd_gpt')
> +@pytest.mark.requiredtool('sgdisk')
> +def test_gpt_setenv(state_disk_image, u_boot_console):
> +    """Test the gpt setenv command."""
> +    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
> +    output = u_boot_console.run_command('gpt setenv host 0 part1')
> +    assert 'success!' in output
> +    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
> +    assert output.rstrip() == '800'
> +    output = u_boot_console.run_command('echo ${gpt_partition_size}')
> +    assert output.rstrip() == '800'
> +    output = u_boot_console.run_command('echo ${gpt_partition_name}')
> +    assert output.rstrip() == 'part1'
> +    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
> +    assert output.rstrip() == "1"
> +    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
> +    assert output.rstrip() == "1"
> +
> +    output = u_boot_console.run_command('gpt setenv host 0 part2')
> +    assert 'success!' in output
> +    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
> +    assert output.rstrip() == '1000'
> +    output = u_boot_console.run_command('echo ${gpt_partition_size}')
> +    assert output.rstrip() == 'c00'
> +    output = u_boot_console.run_command('echo ${gpt_partition_name}')
> +    assert output.rstrip() == 'part2'
> +    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
> +    assert output.rstrip() == "2"
> +    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
> +    assert output.rstrip() == "0"
> +
>  @pytest.mark.boardspec('sandbox')
>  @pytest.mark.buildconfigspec('cmd_gpt')
>  @pytest.mark.requiredtool('sgdisk')
> --
> 2.33.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-23 16:47   ` [PATCH v2 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-23 23:57     ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

Hi Joshua,

On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
> preserved when writing out the partition string. It was already
> respected when writing out partitions; this ensures that if you capture
> the current partition layout and write it back (such as when renaming),
> the type GUIDs are preserved.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 | 16 +++++++++++
>  test/py/tests/test_gpt.py | 57 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+)
>
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index 70a01f7da1..fdd9c429f6 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
>         /* see part.h for definition of struct disk_partition */
>         partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
>         partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +       partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
> +#endif
>         partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
>         /* for the terminating null */
>         partlistlen++;
> @@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
>                 PART_TYPE_LEN);
>         newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
>         newpart->gpt_part_info.bootable = info->bootable;
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +       strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
> +               UUID_STR_LEN);
> +       newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
> +#endif
>  #ifdef CONFIG_PARTITION_UUIDS
>         strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
>                 UUID_STR_LEN);
> @@ -252,6 +260,9 @@ static void print_gpt_info(void)
>                        curr->gpt_part_info.name);
>                 printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
>                        curr->gpt_part_info.bootable & PART_BOOTABLE);
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +               printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
> +#endif
>  #ifdef CONFIG_PARTITION_UUIDS
>                 printf("UUID %s\n", curr->gpt_part_info.uuid);
>  #endif
> @@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
>                                             curr->gpt_part_info.blksz);
>                 strncat(partitions_list, partstr, PART_NAME_LEN + 1);
>
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +               strcat(partitions_list, ",type=");
> +               strncat(partitions_list, curr->gpt_part_info.type_guid,
> +                       UUID_STR_LEN + 1);
> +#endif
>                 strcat(partitions_list, ",uuid=");
>                 strncat(partitions_list, curr->gpt_part_info.uuid,
>                         UUID_STR_LEN + 1);
> diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
> index 8203515e05..f9351f0274 100644
> --- a/test/py/tests/test_gpt.py
> +++ b/test/py/tests/test_gpt.py
> @@ -16,6 +16,26 @@ the test.
>  # Mark all tests here as slow
>  pytestmark = pytest.mark.slow
>
> +def parse_gpt_parts(s):
> +    """Part a partition string into a list of partitions"""

Please remember to fully comment functions, including arg and return value.

Also 's' can be used in loops but not as a var or param. I think we
need to use 3 chars or more.

> +    parts = []
> +    for part_str in s.split(';'):
> +        part = {}
> +        for option in part_str.split(","):
> +            if not option:
> +                continue
> +
> +            if "=" in option:
> +                k, v = option.split("=")
> +                part[k] = v
> +            else:
> +                part[option] = True
> +
> +        if part:
> +            parts.append(part)
> +
> +    return parts
> +
>  class GptTestDiskImage(object):
>      """Disk Image used by the GPT tests."""
>
> @@ -49,11 +69,13 @@ class GptTestDiskImage(object):
>                  u_boot_utils.run_and_log(u_boot_console, cmd)
>                  # part1 offset 1MB size 1MB
>                  cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
> +                    '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
>                      '-A 1:set:2',
>                      persistent)
>                  # part2 offset 2MB size 1.5MB
>                  u_boot_utils.run_and_log(u_boot_console, cmd)
>                  cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
> +                    '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
>                      persistent)
>                  u_boot_utils.run_and_log(u_boot_console, cmd)
>                  cmd = ('sgdisk', '--load-backup=' + persistent)
> @@ -88,6 +110,40 @@ def test_gpt_read(state_disk_image, u_boot_console):
>      assert '0x00000800 0x00000fff      "part1"' in output
>      assert '0x00001000 0x00001bff      "part2"' in output
>
> +@pytest.mark.boardspec('sandbox')
> +@pytest.mark.buildconfigspec('cmd_gpt')
> +@pytest.mark.buildconfigspec('partition_type_guid')
> +@pytest.mark.requiredtool('sgdisk')
> +def test_gpt_read_var(state_disk_image, u_boot_console):
> +    """Test the gpt read command."""
> +
> +    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
> +    output = u_boot_console.run_command('gpt read host 0 gpt_parts')
> +    assert 'success!' in output
> +
> +    output = u_boot_console.run_command('echo ${gpt_parts}')
> +    parts = parse_gpt_parts(output.rstrip())
> +
> +    assert parts == [
> +        {
> +            "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
> +        },
> +        {
> +            "name": "part1",

single quotes

> +            "start": "0x100000",
> +            "size": "0x100000",
> +            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
> +            "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
> +        },
> +        {
> +            "name": "part2",
> +            "start": "0x200000",
> +            "size": "0x180000",
> +            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
> +            "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
> +        },
> +    ]
> +
>  @pytest.mark.boardspec('sandbox')
>  @pytest.mark.buildconfigspec('cmd_gpt')
>  @pytest.mark.requiredtool('sgdisk')
> @@ -263,3 +319,4 @@ def test_gpt_write(state_disk_image, u_boot_console):
>      assert '0x00001000 0x00001bff      "second"' in output
>      output = u_boot_console.run_command('gpt guid host 0')
>      assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
> +
> --
> 2.33.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 7/8] cmd: gpt: Preserve bootable flag
  2023-08-23 16:47   ` [PATCH v2 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
@ 2023-08-23 23:57     ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Sets the bootable flag when constructing the partition string from the
> current partition configuration. This ensures that when the partitions
> are written back (for example, when renaming a partition), the flag is
> preserved.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 | 3 +++
>  test/py/tests/test_gpt.py | 1 +
>  2 files changed, 4 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 6/6] cmd: gpt: Add command to swap partition order
  2023-08-15 16:27 ` [PATCH 6/6] cmd: gpt: Add command to swap partition order Joshua Watt
@ 2023-08-23 23:57   ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-23 23:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot

Hi Joshua,

On Tue, 15 Aug 2023 at 10:28, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds a command called "gpt swap-postition" which will swap the order two
> partitions are listed in the GPT partition table (but leaves them
> pointing to the same locations on disk).
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 48 insertions(+), 2 deletions(-)
>
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index 58564436d3..c8a2b5ae7b 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -859,7 +859,7 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
>         int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
>
>         if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
> -           (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
> +           (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") && strcmp(subcomm, "swap-position")))

While you are here you could tidy this code:

if (!subcomm || !name1 || !name2 ||
...

>                 return -EINVAL;
>
>         ret = get_disk_guid(dev_desc, disk_guid);
> @@ -920,6 +920,48 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
>                         ret = -EINVAL;
>                         goto out;
>                 }
> +       } else if(!strcmp(subcomm, "swap-position")) {
> +               int idx1, idx2;
> +               struct disk_partition first, second;

blank line

> +               idx1 = simple_strtoul(name1, NULL, 10);
> +               if (idx1 <= 0 || idx1 > numparts) {
> +                       printf("Illegal partition number %s\n", name1);
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +               idx2 = simple_strtoul(name2, NULL, 10);
> +               if (idx2 <= 0 || idx2 > numparts) {
> +                       printf("Illegal partition number %s\n", name2);
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +               if (idx1 == idx2) {
> +                       printf("Cannot swap partition with itself\n");
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +
> +               i = 1;
> +               list_for_each(pos, &disk_partitions) {
> +                       curr = list_entry(pos, struct disk_part, list);
> +                       if (i == idx1) {
> +                               first = curr->gpt_part_info;
> +                       } else if (i == idx2) {
> +                               second = curr->gpt_part_info;
> +                       }

Can you please either use patman or manually checkpatch on your
patches? This should not have {}

> +                       i++;
> +               }
> +
> +               i = 1;
> +               list_for_each(pos, &disk_partitions) {
> +                       curr = list_entry(pos, struct disk_part, list);
> +                       if (i == idx1) {
> +                               curr->gpt_part_info = second;
> +                       } else if (i == idx2) {
> +                               curr->gpt_part_info = first;
> +                       }
> +                       i++;
> +               }
>         } else { /* rename */
>                 if (strlen(name2) > PART_NAME_LEN) {
>                         printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
> @@ -1122,7 +1164,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>         } else if (strcmp(argv[1], "read") == 0) {
>                 ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
>         } else if ((strcmp(argv[1], "swap") == 0) ||
> -                  (strcmp(argv[1], "rename") == 0)) {
> +                  (strcmp(argv[1], "rename") == 0) ||
> +                  (strcmp(argv[1], "swap-position") == 0)) {
>                 ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
>  #endif
>         } else if ((strcmp(argv[1], "set-bootable") == 0)) {
> @@ -1175,11 +1218,14 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
>         " gpt swap <interface> <dev> <name1> <name2>\n"
>         "    - change all partitions named name1 to name2\n"
>         "      and vice-versa\n"
> +       " gpt swap-position <interface> <dev> <part1> <part2>\n"
> +       "    - Swap the order of name1 with name2 in the partition table\n"
>         " gpt rename <interface> <dev> <part> <name>\n"
>         "    - rename the specified partition\n"
>         " Example usage:\n"
>         " gpt swap mmc 0 foo bar\n"
>         " gpt rename mmc 0 3 foo\n"
> +       " gpt swap-partitions mmc 0 1 2\n"
>  #endif
>         " gpt set-bootable <interface> <dev> <list>\n"
>         "    - make partition names in list bootable\n"
> --
> 2.33.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v2 3/8] tests: gpt: Remove test order dependency
  2023-08-23 23:57     ` Simon Glass
@ 2023-08-24  3:29       ` Joshua Watt
  0 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-24  3:29 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, Enric Balletbo i Serra

On Wed, Aug 23, 2023 at 5:59 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joshua,
>
> On Wed, 23 Aug 2023 at 10:48, Joshua Watt <jpewhacker@gmail.com> wrote:
> >
> > Re-create a clean disk image for each test to prevent modifications from
> > one test affecting another
> >
> > Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> > ---
> >  test/py/tests/test_gpt.py | 20 ++++++++------------
> >  1 file changed, 8 insertions(+), 12 deletions(-)
>
> I suppose this is OK, but is it expensive in terms of time?

There wasn't a noticeable slowdown in test execution time on my
(admittedly powerful) workstation.

>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements
  2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                     ` (7 preceding siblings ...)
  2023-08-23 16:47   ` [PATCH v2 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
@ 2023-08-25 19:38   ` Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 1/8] cmd: gpt: Remove confusing help text Joshua Watt
                       ` (8 more replies)
  8 siblings, 9 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds several improvements and additions to the gpt command processing,
specifically (although not exclusively) for the purpose of supporting
"ping-pong" booting when doing A/B boot partitions with u-boot itself.

In this mechanism, u-boot must boot up, and then check if the correct
boot partition is active, and if not switch the GPT partition table to
the other boot partition and reboot to activate the other u-boot.

In order to facilitate this, the gpt command needs to be better at
preserving entry attributes when manipulating the partition table. It
also learns two new commands, one which can swap the order of partitions
in the table, and another that lets it change which partitions have the
bootable flag.

V2: Add documentation and tests
V3: Review Feedback

Joshua Watt (8):
  cmd: gpt: Remove confusing help text
  doc: Add gpt command documentation
  tests: gpt: Remove test order dependency
  cmd: gpt: Add gpt_partition_bootable variable
  cmd: gpt: Add command to set bootable flags
  cmd: gpt: Preserve type GUID if enabled
  cmd: gpt: Preserve bootable flag
  cmd: gpt: Add command to swap partition order

 cmd/gpt.c                 | 162 +++++++++++++++++++++++++++++++++--
 doc/usage/cmd/gpt.rst     | 176 ++++++++++++++++++++++++++++++++++++++
 doc/usage/index.rst       |   1 +
 test/py/tests/test_gpt.py | 160 +++++++++++++++++++++++++++++++---
 4 files changed, 480 insertions(+), 19 deletions(-)
 create mode 100644 doc/usage/cmd/gpt.rst

-- 
2.33.0


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v3 1/8] cmd: gpt: Remove confusing help text
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 2/8] doc: Add gpt command documentation Joshua Watt
                       ` (7 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

This help text appears to be a fragment of the text shown when
CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 007a68eaa7..e6f7b0319a 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -1060,8 +1060,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      gpt_partition_name, gpt_partition_entry\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
-	" read <interface> <dev>\n"
-	"    - read GPT into a data structure for manipulation\n"
 	" gpt guid <interface> <dev>\n"
 	"    - print disk GUID\n"
 	" gpt guid <interface> <dev> <varname>\n"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 1/8] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 23:53       ` Simon Glass
  2023-08-26  1:57       ` Heinrich Schuchardt
  2023-08-25 19:38     ` [PATCH v3 3/8] tests: gpt: Remove test order dependency Joshua Watt
                       ` (6 subsequent siblings)
  8 siblings, 2 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt

Adds initial documentation for the gpt command

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
 doc/usage/index.rst   |   1 +
 2 files changed, 142 insertions(+)
 create mode 100644 doc/usage/cmd/gpt.rst

diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
new file mode 100644
index 0000000000..f6e082fb94
--- /dev/null
+++ b/doc/usage/cmd/gpt.rst
@@ -0,0 +1,141 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+gpt command
+===========
+
+Synopsis
+--------
+
+::
+
+    gpt repair <interface> <device no>
+    gpt write <interface> <device no> <partition string>
+    gpt verify <interface> <device no> <partition string>
+    gpt setenv <interface> <device no> <partition name>
+    gpt enumerate <interface> <device no>
+    gpt guid <interface> <device no> [<varname>]
+    gpt read <interface> <device no> [<varname>]
+    gpt swap <interface> <dev> <name1> <name2>
+    gpt rename <interface> <dev> <part> <name>
+
+Description
+-----------
+
+The gpt command lets users read, create, modify, or verify the GPT (GUID
+Partition Table) partition layout.
+
+The syntax of the text description of the partition list is similar to
+the one used by the 'mbr' command. The string contains one or more partition
+descriptors, each separated by a ";". Each descriptor contains one or more
+fields, with each field separated by a ",". Fields are either of the form
+"key=value" to set a specific value, or simple "flag" to set a boolean flag
+
+The first descriptor can optionally be used to describe parameters for the
+whole disk with the following fields:
+
+* uuid_disk=UUID - Set the UUID for the disk
+
+Partition descriptors can have the following fields:
+* name=NAME - The partition name, required
+* start=BYTES - The partition start offset in bytes, required
+* size=BYTES - The partition size, in bytes or "-" to expand it to the whole free area
+* bootable - Set the legacy bootable flag
+* uuid=UUID - Set the partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
+* type=UUID - Set the partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
+
+Here is an example how to create a 6 partitions, some of the predefined sizes:
+
+::
+
+    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
+        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
+        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
+    => gpt write mmc 0 $gpt_parts
+
+
+If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
+will be generated for the partition
+
+The 'gpt verify' command returns 0 if the layout matches the one on the storage
+device or 1 if not. To check if the layout on the MMC #0 storage device
+matches the provided text description one has to issue following command:
+
+::
+
+    => gpt verify mmc 0 $gpt_parts
+
+The verify sub-command is especially useful in the system update scripts:
+
+::
+
+    => if gpt verify mmc 0 $gpt_parts; then
+         echo GPT layout needs to be updated
+         ...
+       fi
+
+The 'gpt write' command returns 0 on success write or 1 on failure.
+
+The 'gpt setenv' command will set a series of environment variables with
+information about a particular partition. The variables are:
+
+* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
+* gpt_partition_size (the size of the partition, in hexadecimal blocks)
+* gpt_partition_name (the name of the partition)
+* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
+
+To get the information about the partition named 'rootfs', issue the following
+command:
+
+::
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_addr}
+    2000
+    => echo ${gpt_partition_size}
+    14a000
+    => echo ${gpt_partition_name}
+    rootfs
+    => echo ${gpt_partition_entry}
+    2
+
+The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
+list of partition names on the device. For example:
+
+::
+    => gpt enumerate
+    => echo gpt_partition_list
+    boot rootfs system-data [ext] user modules ramdisk
+
+The 'gpt guid' command will report the GUID of a disk. If 'varname' is
+specified, the command will set the variable to the GUID, otherwise it will be
+printed out. For example:
+
+::
+    => gpt guid mmc 0
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
+    => gpt guid mmc gpt_disk_uuid
+    => echo ${gpt_disk_uuid}
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
+
+The 'gpt read' command will print out the current state of the GPT partition
+table. If 'varname' is specified, the variable will be filled with a partition
+string as described above that is suitable for passing to other 'gpt' commands.
+If omitted, a human readable description is printed out.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+The 'gpt swap' command changes the names of all partitions that are named
+'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+Configuration
+-------------
+
+To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
+read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 3326ec82ff..4bfaabbd16 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -65,6 +65,7 @@ Shell commands
    cmd/for
    cmd/fwu_mdata
    cmd/gpio
+   cmd/gpt
    cmd/host
    cmd/imxtract
    cmd/load
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 3/8] tests: gpt: Remove test order dependency
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 1/8] cmd: gpt: Remove confusing help text Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
                       ` (5 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Re-create a clean disk image for each test to prevent modifications from
one test affecting another

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 test/py/tests/test_gpt.py | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 73bfbf77a2..339468bc12 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -61,18 +61,14 @@ class GptTestDiskImage(object):
         cmd = ('cp', persistent, self.path)
         u_boot_utils.run_and_log(u_boot_console, cmd)
 
-gtdi = None
 @pytest.fixture(scope='function')
 def state_disk_image(u_boot_console):
     """pytest fixture to provide a GptTestDiskImage object to tests.
     This is function-scoped because it uses u_boot_console, which is also
-    function-scoped. However, we don't need to actually do any function-scope
-    work, so this simply returns the same object over and over each time."""
+    function-scoped. A new disk is returned each time to prevent tests from
+    interfering with each other."""
 
-    global gtdi
-    if not gtdi:
-        gtdi = GptTestDiskImage(u_boot_console)
-    return gtdi
+    return GptTestDiskImage(u_boot_console)
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
@@ -186,12 +182,12 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
 
     u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"first"' in output
-    assert '0x00001000	0x00001bff	"second"' in output
-    u_boot_console.run_command('gpt swap host 0 first second')
+    assert '0x00000800	0x00000fff	"part1"' in output
+    assert '0x00001000	0x00001bff	"part2"' in output
+    u_boot_console.run_command('gpt swap host 0 part1 part2')
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"second"' in output
-    assert '0x00001000	0x00001bff	"first"' in output
+    assert '0x00000800	0x00000fff	"part2"' in output
+    assert '0x00001000	0x00001bff	"part1"' in output
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 4/8] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                       ` (2 preceding siblings ...)
  2023-08-25 19:38     ` [PATCH v3 3/8] tests: gpt: Remove test order dependency Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 23:53       ` Simon Glass
  2023-08-25 19:38     ` [PATCH v3 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
                       ` (4 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Enric Balletbo i Serra

Adds an additional variable called gpt_partition_bootable that indicates
if the given partition is bootable or not.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 |  9 +++++++--
 doc/usage/cmd/gpt.rst     |  3 +++
 test/py/tests/test_gpt.py | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index e6f7b0319a..7a8990e400 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -723,7 +723,7 @@ static int gpt_enumerate(struct blk_desc *desc)
  * gpt_setenv_part_variables() - setup partition environmental variables
  *
  * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
- * and gpt_partition_size environment variables.
+ * and gpt_partition_size, gpt_partition_bootable environment variables.
  *
  * @pinfo: pointer to disk partition
  * @i: partition entry
@@ -750,6 +750,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
 	if (ret)
 		goto fail;
 
+	ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
+	if (ret)
+		goto fail;
+
 	return 0;
 
 fail:
@@ -1057,7 +1061,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt setenv mmc 0 $name\n"
 	"    - setup environment variables for partition $name:\n"
 	"      gpt_partition_addr, gpt_partition_size,\n"
-	"      gpt_partition_name, gpt_partition_entry\n"
+	"      gpt_partition_name, gpt_partition_entry,\n"
+	"      gpt_partition_bootable\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
 	" gpt guid <interface> <dev>\n"
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index f6e082fb94..88839b8e1b 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -87,6 +87,7 @@ information about a particular partition. The variables are:
 * gpt_partition_size (the size of the partition, in hexadecimal blocks)
 * gpt_partition_name (the name of the partition)
 * gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
+* gpt_partition_bootable (1 if the partition is marked as bootable, 0 if not)
 
 To get the information about the partition named 'rootfs', issue the following
 command:
@@ -101,6 +102,8 @@ command:
     rootfs
     => echo ${gpt_partition_entry}
     2
+    => echo ${gpt_partition_bootable}
+    0
 
 The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
 list of partition names on the device. For example:
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 339468bc12..946858800d 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -49,6 +49,7 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
@@ -117,6 +118,38 @@ def test_gpt_guid(state_disk_image, u_boot_console):
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_setenv(state_disk_image, u_boot_console):
+    """Test the gpt setenv command."""
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt setenv host 0 part1')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part1'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == '1'
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == '1'
+
+    output = u_boot_console.run_command('gpt setenv host 0 part2')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '1000'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == 'c00'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part2'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == '2'
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                       ` (3 preceding siblings ...)
  2023-08-25 19:38     ` [PATCH v3 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
                       ` (3 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Adds a command that can be used to modify the GPT partition table to
indicate which partitions should have the bootable flag set

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 80 +++++++++++++++++++++++++++++++++++++++
 doc/usage/cmd/gpt.rst     |  9 +++++
 test/py/tests/test_gpt.py | 22 +++++++++++
 3 files changed, 111 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 7a8990e400..1fe7f1a7db 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -972,6 +972,81 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	free(partitions_list);
 	return ret;
 }
+
+/**
+ * gpt_set_bootable() - Set bootable flags for partitions
+ *
+ * Sets the bootable flag for any partition names in the comma separated list of
+ * partition names. Any partitions not in the list have their bootable flag
+ * cleared
+ *
+ * @desc: block device descriptor
+ * @name: Comma separated list of partition names
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const part_list)
+{
+	char *name;
+	char disk_guid[UUID_STR_LEN + 1];
+	struct list_head *pos;
+	struct disk_part *curr;
+	struct disk_partition *partitions = NULL;
+	int part_count = 0;
+	int ret = get_disk_guid(blk_dev_desc, disk_guid);
+
+	if (ret < 0)
+		return ret;
+
+	ret = get_gpt_info(blk_dev_desc);
+	if (ret <= 0)
+		goto out;
+
+	part_count = ret;
+	partitions = malloc(sizeof(*partitions) * part_count);
+	if (!partitions) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Copy partitions and clear bootable flag */
+	part_count = 0;
+	list_for_each(pos, &disk_partitions) {
+		curr = list_entry(pos, struct disk_part, list);
+		partitions[part_count] = curr->gpt_part_info;
+		partitions[part_count].bootable &= ~PART_BOOTABLE;
+		part_count++;
+	}
+
+	name = strtok(part_list, ",");
+	while (name) {
+		bool found = false;
+
+		for (int i = 0; i < part_count; i++) {
+			if (strcmp((char *)partitions[i].name, name) == 0) {
+				partitions[i].bootable |= PART_BOOTABLE;
+				found = true;
+			}
+		}
+
+		if (!found) {
+			printf("Warning: No partition matching '%s' found\n",
+			       name);
+		}
+
+		name = strtok(NULL, ",");
+	}
+
+	ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
+
+out:
+	del_gpt_info();
+
+	if (partitions)
+		free(partitions);
+
+	return ret;
+}
 #endif
 
 /**
@@ -1031,6 +1106,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if ((strcmp(argv[1], "swap") == 0) ||
 		   (strcmp(argv[1], "rename") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
+	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
+		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
 #endif
 	} else {
 		return CMD_RET_USAGE;
@@ -1082,8 +1159,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      and vice-versa\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
+	" gpt set-bootable <interface> <dev> <list>\n"
+	"    - make partition names in list bootable\n"
 	" Example usage:\n"
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
+	" gpt set-bootable mmc 0 boot_a,boot_b\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index 88839b8e1b..353dfb05cf 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -17,6 +17,7 @@ Synopsis
     gpt read <interface> <device no> [<varname>]
     gpt swap <interface> <dev> <name1> <name2>
     gpt rename <interface> <dev> <part> <name>
+    gpt set-bootable <interface> <dev> <partition list>
 
 Description
 -----------
@@ -137,6 +138,14 @@ CONFIG_CMD_GPT_RENAME=y is required.
 The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
 CONFIG_CMD_GPT_RENAME=y is required.
 
+The 'gpt set-bootable' command sets the bootable flag for all partitions in the
+table. If the partition name is in 'partition list' (separated by ','), the
+bootable flag is set, otherwise it is cleared. CONFIG_CMD_GPT_RENAME=y is
+required.  For example, to mark only the 'boot' partition as bootable:
+
+::
+    => gpt set-bootable mmc 0 boot
+
 Configuration
 -------------
 
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 946858800d..5d23f9b292 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -222,6 +222,28 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part2"' in output
     assert '0x00001000	0x00001bff	"part1"' in output
 
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_set_bootable(state_disk_image, u_boot_console):
+    """Test the gpt set-bootable command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    parts = ('part2', 'part1')
+    for bootable in parts:
+        output = u_boot_console.run_command(f'gpt set-bootable host 0 {bootable}')
+        assert 'success!' in output
+
+        for p in parts:
+            output = u_boot_console.run_command(f'gpt setenv host 0 {p}')
+            assert 'success!' in output
+            output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+            if p == bootable:
+                assert output.rstrip() == '1'
+            else:
+                assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_part')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                       ` (4 preceding siblings ...)
  2023-08-25 19:38     ` [PATCH v3 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 23:53       ` Simon Glass
  2023-08-26  0:37       ` Heinrich Schuchardt
  2023-08-25 19:38     ` [PATCH v3 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
                       ` (2 subsequent siblings)
  8 siblings, 2 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Enric Balletbo i Serra

If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
preserved when writing out the partition string. It was already
respected when writing out partitions; this ensures that if you capture
the current partition layout and write it back (such as when renaming),
the type GUIDs are preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 16 ++++++++++
 test/py/tests/test_gpt.py | 66 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 1fe7f1a7db..b7d861aa1e 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
 	/* see part.h for definition of struct disk_partition */
 	partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
 	partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
+#endif
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
 		PART_TYPE_LEN);
 	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
 	newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
+		UUID_STR_LEN);
+	newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
 		UUID_STR_LEN);
@@ -252,6 +260,9 @@ static void print_gpt_info(void)
 		       curr->gpt_part_info.name);
 		printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
 		       curr->gpt_part_info.bootable & PART_BOOTABLE);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 		printf("UUID %s\n", curr->gpt_part_info.uuid);
 #endif
@@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 					    curr->gpt_part_info.blksz);
 		strncat(partitions_list, partstr, PART_NAME_LEN + 1);
 
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		strcat(partitions_list, ",type=");
+		strncat(partitions_list, curr->gpt_part_info.type_guid,
+			UUID_STR_LEN + 1);
+#endif
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 5d23f9b292..09a90f026f 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -16,6 +16,35 @@ the test.
 # Mark all tests here as slow
 pytestmark = pytest.mark.slow
 
+def parse_gpt_parts(disk_str):
+    """Parser a partition string into a list of partitions.
+
+    Args:
+        disk_str: The disk description string, as returned by `gpt read`
+
+    Returns:
+        A list of parsed partitions. Each partition is a dictionary with the
+        string value from each specified key in the partition description, or a
+        key with with the value True for a boolean flag
+    """
+    parts = []
+    for part_str in disk_str.split(';'):
+        part = {}
+        for option in part_str.split(","):
+            if not option:
+                continue
+
+            if "=" in option:
+                k, v = option.split("=")
+                part[k] = v
+            else:
+                part[option] = True
+
+        if part:
+            parts.append(part)
+
+    return parts
+
 class GptTestDiskImage(object):
     """Disk Image used by the GPT tests."""
 
@@ -49,11 +78,13 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
                     '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
+                    '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
                     persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--load-backup=' + persistent)
@@ -88,6 +119,40 @@ def test_gpt_read(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part1"' in output
     assert '0x00001000	0x00001bff	"part2"' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('partition_type_guid')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_read_var(state_disk_image, u_boot_console):
+    """Test the gpt read command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt read host 0 gpt_parts')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('echo ${gpt_parts}')
+    parts = parse_gpt_parts(output.rstrip())
+
+    assert parts == [
+        {
+            "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
+        },
+        {
+            "name": "part1",
+            "start": "0x100000",
+            "size": "0x100000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+        },
+        {
+            "name": "part2",
+            "start": "0x200000",
+            "size": "0x180000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
+        },
+    ]
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
@@ -263,3 +328,4 @@ def test_gpt_write(state_disk_image, u_boot_console):
     assert '0x00001000	0x00001bff	"second"' in output
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
+
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 7/8] cmd: gpt: Preserve bootable flag
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                       ` (5 preceding siblings ...)
  2023-08-25 19:38     ` [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 19:38     ` [PATCH v3 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Enric Balletbo i Serra

Sets the bootable flag when constructing the partition string from the
current partition configuration. This ensures that when the partitions
are written back (for example, when renaming a partition), the flag is
preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 3 +++
 test/py/tests/test_gpt.py | 1 +
 2 files changed, 4 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index b7d861aa1e..0479b3a6a4 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -176,6 +176,7 @@ static int calc_parts_list_len(int numparts)
 #ifdef CONFIG_PARTITION_TYPE_GUID
 	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
 #endif
+	partlistlen += numparts * strlen("bootable,");
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -318,6 +319,8 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
+		if (curr->gpt_part_info.bootable & PART_BOOTABLE)
+			strcat(partitions_list, ",bootable");
 		strcat(partitions_list, ";");
 	}
 	return 0;
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 09a90f026f..666d387ac8 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -143,6 +143,7 @@ def test_gpt_read_var(state_disk_image, u_boot_console):
             "size": "0x100000",
             "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
             "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+            "bootable": True,
         },
         {
             "name": "part2",
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v3 8/8] cmd: gpt: Add command to swap partition order
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                       ` (6 preceding siblings ...)
  2023-08-25 19:38     ` [PATCH v3 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
@ 2023-08-25 19:38     ` Joshua Watt
  2023-08-25 23:53       ` Simon Glass
  2023-08-26  1:00       ` Heinrich Schuchardt
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  8 siblings, 2 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-25 19:38 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Adds a command called "gpt swap-postition" which will swap the order two
partitions are listed in the GPT partition table (but leaves them
pointing to the same locations on disk).

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 52 ++++++++++++++++++++++++++++++++++++---
 doc/usage/cmd/gpt.rst     | 23 +++++++++++++++++
 test/py/tests/test_gpt.py | 18 ++++++++++++++
 3 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 0479b3a6a4..3c39446258 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -858,8 +858,9 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	u8 part_count = 0;
 	int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
 
-	if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
-	    (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
+	if (!subcomm || !name1 || !name2 ||
+	    (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") &&
+	     strcmp(subcomm, "swap-position")))
 		return -EINVAL;
 
 	ret = get_disk_guid(dev_desc, disk_guid);
@@ -920,6 +921,47 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 			ret = -EINVAL;
 			goto out;
 		}
+	} else if (!strcmp(subcomm, "swap-position")) {
+		int idx1, idx2;
+		struct disk_partition first, second;
+
+		idx1 = simple_strtoul(name1, NULL, 10);
+		if (idx1 <= 0 || idx1 > numparts) {
+			printf("Illegal partition number %s\n", name1);
+			ret = -EINVAL;
+			goto out;
+		}
+		idx2 = simple_strtoul(name2, NULL, 10);
+		if (idx2 <= 0 || idx2 > numparts) {
+			printf("Illegal partition number %s\n", name2);
+			ret = -EINVAL;
+			goto out;
+		}
+		if (idx1 == idx2) {
+			printf("Cannot swap partition with itself\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		i = 1;
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (i == idx1)
+				first = curr->gpt_part_info;
+			else if (i == idx2)
+				second = curr->gpt_part_info;
+			i++;
+		}
+
+		i = 1;
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (i == idx1)
+				curr->gpt_part_info = second;
+			else if (i == idx2)
+				curr->gpt_part_info = first;
+			i++;
+		}
 	} else { /* rename */
 		if (strlen(name2) > PART_NAME_LEN) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
@@ -1123,7 +1165,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if (strcmp(argv[1], "read") == 0) {
 		ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
 	} else if ((strcmp(argv[1], "swap") == 0) ||
-		   (strcmp(argv[1], "rename") == 0)) {
+		   (strcmp(argv[1], "rename") == 0) ||
+		   (strcmp(argv[1], "swap-position") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
 	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
 		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
@@ -1176,6 +1219,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap <interface> <dev> <name1> <name2>\n"
 	"    - change all partitions named name1 to name2\n"
 	"      and vice-versa\n"
+	" gpt swap-position <interface> <dev> <part1> <part2>\n"
+	"    - Swap the order of name1 with name2 in the partition table\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
 	" gpt set-bootable <interface> <dev> <list>\n"
@@ -1184,5 +1229,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
 	" gpt set-bootable mmc 0 boot_a,boot_b\n"
+	" gpt swap-position mmc 0 1 2\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index 353dfb05cf..bc14bda6e5 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -17,6 +17,7 @@ Synopsis
     gpt read <interface> <device no> [<varname>]
     gpt swap <interface> <dev> <name1> <name2>
     gpt rename <interface> <dev> <part> <name>
+    gpt swap-position <interface> <dev> <part1> <part2>
     gpt set-bootable <interface> <dev> <partition list>
 
 Description
@@ -138,6 +139,28 @@ CONFIG_CMD_GPT_RENAME=y is required.
 The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
 CONFIG_CMD_GPT_RENAME=y is required.
 
+The 'gpt swap-position' command swaps the order of two partition index in the
+partition table, but otherwise leaves the actual partition data untouched. For
+example, to swap the order of the 'boot' and 'rootfs' partitions in the disk
+described above, you would do:
+
+::
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    2
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    1
+
+    => gpt swap-position mmc 0 1 2
+
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    1
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    2
+
 The 'gpt set-bootable' command sets the bootable flag for all partitions in the
 table. If the partition name is in 'partition list' (separated by ','), the
 bootable flag is set, otherwise it is cleared. CONFIG_CMD_GPT_RENAME=y is
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 666d387ac8..3d23b98cea 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -330,3 +330,21 @@ def test_gpt_write(state_disk_image, u_boot_console):
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
 
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_swap_position(state_disk_image, u_boot_console):
+    """Test the gpt swap-position command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('part list host 0')
+    assert '1\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '2\t0x00001000\t0x00001bff\t"part2"' in output
+
+    output = u_boot_console.run_command('gpt swap-position host 0 1 2')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('part list host 0')
+    assert '2\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '1\t0x00001000\t0x00001bff\t"part2"' in output
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 8/8] cmd: gpt: Add command to swap partition order
  2023-08-25 19:38     ` [PATCH v3 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
@ 2023-08-25 23:53       ` Simon Glass
  2023-08-26  1:00       ` Heinrich Schuchardt
  1 sibling, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-25 23:53 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

On Fri, 25 Aug 2023 at 13:39, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds a command called "gpt swap-postition" which will swap the order two
> partitions are listed in the GPT partition table (but leaves them
> pointing to the same locations on disk).
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 | 52 ++++++++++++++++++++++++++++++++++++---
>  doc/usage/cmd/gpt.rst     | 23 +++++++++++++++++
>  test/py/tests/test_gpt.py | 18 ++++++++++++++
>  3 files changed, 90 insertions(+), 3 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-25 19:38     ` [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-25 23:53       ` Simon Glass
  2023-08-26  0:37       ` Heinrich Schuchardt
  1 sibling, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-25 23:53 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

On Fri, 25 Aug 2023 at 13:39, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
> preserved when writing out the partition string. It was already
> respected when writing out partitions; this ensures that if you capture
> the current partition layout and write it back (such as when renaming),
> the type GUIDs are preserved.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 | 16 ++++++++++
>  test/py/tests/test_gpt.py | 66 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 82 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 4/8] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-25 19:38     ` [PATCH v3 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-25 23:53       ` Simon Glass
  0 siblings, 0 replies; 74+ messages in thread
From: Simon Glass @ 2023-08-25 23:53 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra

On Fri, 25 Aug 2023 at 13:38, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds an additional variable called gpt_partition_bootable that indicates
> if the given partition is bootable or not.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  cmd/gpt.c                 |  9 +++++++--
>  doc/usage/cmd/gpt.rst     |  3 +++
>  test/py/tests/test_gpt.py | 33 +++++++++++++++++++++++++++++++++
>  3 files changed, 43 insertions(+), 2 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-25 19:38     ` [PATCH v3 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-25 23:53       ` Simon Glass
  2023-08-28 21:52         ` Joshua Watt
  2023-08-26  1:57       ` Heinrich Schuchardt
  1 sibling, 1 reply; 74+ messages in thread
From: Simon Glass @ 2023-08-25 23:53 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Heinrich Schuchardt

Hi Joshua,

On Fri, 25 Aug 2023 at 13:38, Joshua Watt <jpewhacker@gmail.com> wrote:
>
> Adds initial documentation for the gpt command
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>  doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
>  doc/usage/index.rst   |   1 +
>  2 files changed, 142 insertions(+)
>  create mode 100644 doc/usage/cmd/gpt.rst

I don't see a change log?

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-25 19:38     ` [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
  2023-08-25 23:53       ` Simon Glass
@ 2023-08-26  0:37       ` Heinrich Schuchardt
  1 sibling, 0 replies; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-26  0:37 UTC (permalink / raw)
  To: Joshua Watt; +Cc: Simon Glass, Enric Balletbo i Serra, u-boot

On 8/25/23 21:38, Joshua Watt wrote:
> If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
> preserved when writing out the partition string. It was already
> respected when writing out partitions; this ensures that if you capture
> the current partition layout and write it back (such as when renaming),
> the type GUIDs are preserved.
> 
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>   cmd/gpt.c                 | 16 ++++++++++
>   test/py/tests/test_gpt.py | 66 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 82 insertions(+)
> 
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index 1fe7f1a7db..b7d861aa1e 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
>   	/* see part.h for definition of struct disk_partition */
>   	partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
>   	partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
> +#endif
>   	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
>   	/* for the terminating null */
>   	partlistlen++;
> @@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
>   		PART_TYPE_LEN);
>   	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
>   	newpart->gpt_part_info.bootable = info->bootable;
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +	strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
> +		UUID_STR_LEN);
> +	newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
> +#endif
>   #ifdef CONFIG_PARTITION_UUIDS
>   	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
>   		UUID_STR_LEN);
> @@ -252,6 +260,9 @@ static void print_gpt_info(void)
>   		       curr->gpt_part_info.name);
>   		printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
>   		       curr->gpt_part_info.bootable & PART_BOOTABLE);
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +		printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
> +#endif
>   #ifdef CONFIG_PARTITION_UUIDS
>   		printf("UUID %s\n", curr->gpt_part_info.uuid);
>   #endif
> @@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
>   					    curr->gpt_part_info.blksz);
>   		strncat(partitions_list, partstr, PART_NAME_LEN + 1);
>   
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> +		strcat(partitions_list, ",type=");
> +		strncat(partitions_list, curr->gpt_part_info.type_guid,
> +			UUID_STR_LEN + 1);
> +#endif
>   		strcat(partitions_list, ",uuid=");
>   		strncat(partitions_list, curr->gpt_part_info.uuid,
>   			UUID_STR_LEN + 1);
> diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
> index 5d23f9b292..09a90f026f 100644
> --- a/test/py/tests/test_gpt.py
> +++ b/test/py/tests/test_gpt.py
> @@ -16,6 +16,35 @@ the test.
>   # Mark all tests here as slow
>   pytestmark = pytest.mark.slow
>   
> +def parse_gpt_parts(disk_str):
> +    """Parser a partition string into a list of partitions.
> +
> +    Args:
> +        disk_str: The disk description string, as returned by `gpt read`
> +
> +    Returns:
> +        A list of parsed partitions. Each partition is a dictionary with the
> +        string value from each specified key in the partition description, or a
> +        key with with the value True for a boolean flag
> +    """
> +    parts = []
> +    for part_str in disk_str.split(';'):
> +        part = {}
> +        for option in part_str.split(","):
> +            if not option:
> +                continue
> +
> +            if "=" in option:
> +                k, v = option.split("=")

This results in a pylint warning:

C0103: Variable name "v" doesn't conform to snake_case naming style 
(invalid-name)

How about key, value?

> +                part[k] = v
> +            else:
> +                part[option] = True
> +
> +        if part:
> +            parts.append(part)
> +
> +    return parts
> +
>   class GptTestDiskImage(object):
>       """Disk Image used by the GPT tests."""
>   
> @@ -49,11 +78,13 @@ class GptTestDiskImage(object):
>                   u_boot_utils.run_and_log(u_boot_console, cmd)
>                   # part1 offset 1MB size 1MB
>                   cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
> +                    '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
>                       '-A 1:set:2',
>                       persistent)
>                   # part2 offset 2MB size 1.5MB
>                   u_boot_utils.run_and_log(u_boot_console, cmd)
>                   cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
> +                    '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
>                       persistent)
>                   u_boot_utils.run_and_log(u_boot_console, cmd)
>                   cmd = ('sgdisk', '--load-backup=' + persistent)
> @@ -88,6 +119,40 @@ def test_gpt_read(state_disk_image, u_boot_console):
>       assert '0x00000800	0x00000fff	"part1"' in output
>       assert '0x00001000	0x00001bff	"part2"' in output
>   
> +@pytest.mark.boardspec('sandbox')
> +@pytest.mark.buildconfigspec('cmd_gpt')
> +@pytest.mark.buildconfigspec('partition_type_guid')
> +@pytest.mark.requiredtool('sgdisk')
> +def test_gpt_read_var(state_disk_image, u_boot_console):
> +    """Test the gpt read command."""
> +
> +    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
> +    output = u_boot_console.run_command('gpt read host 0 gpt_parts')
> +    assert 'success!' in output
> +
> +    output = u_boot_console.run_command('echo ${gpt_parts}')
> +    parts = parse_gpt_parts(output.rstrip())
> +
> +    assert parts == [
> +        {
> +            "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
> +        },
> +        {
> +            "name": "part1",
> +            "start": "0x100000",
> +            "size": "0x100000",
> +            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
> +            "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
> +        },
> +        {
> +            "name": "part2",
> +            "start": "0x200000",
> +            "size": "0x180000",
> +            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
> +            "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
> +        },
> +    ]
> +
>   @pytest.mark.boardspec('sandbox')
>   @pytest.mark.buildconfigspec('cmd_gpt')
>   @pytest.mark.requiredtool('sgdisk')
> @@ -263,3 +328,4 @@ def test_gpt_write(state_disk_image, u_boot_console):
>       assert '0x00001000	0x00001bff	"second"' in output
>       output = u_boot_console.run_command('gpt guid host 0')
>       assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
> +

Please, remove this white space line.

Best regards

Heinrich

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 8/8] cmd: gpt: Add command to swap partition order
  2023-08-25 19:38     ` [PATCH v3 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
  2023-08-25 23:53       ` Simon Glass
@ 2023-08-26  1:00       ` Heinrich Schuchardt
  1 sibling, 0 replies; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-26  1:00 UTC (permalink / raw)
  To: Joshua Watt; +Cc: Enric Balletbo i Serra, Simon Glass, u-boot

On 8/25/23 21:38, Joshua Watt wrote:
> Adds a command called "gpt swap-postition" which will swap the order two
> partitions are listed in the GPT partition table (but leaves them
> pointing to the same locations on disk).

Why is this functionality needed in a boot firmware?

> 
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org > ---
>   cmd/gpt.c                 | 52 ++++++++++++++++++++++++++++++++++++---
>   doc/usage/cmd/gpt.rst     | 23 +++++++++++++++++
>   test/py/tests/test_gpt.py | 18 ++++++++++++++
>   3 files changed, 90 insertions(+), 3 deletions(-)
> 
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index 0479b3a6a4..3c39446258 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -858,8 +858,9 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
>   	u8 part_count = 0;
>   	int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
>   
> -	if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
> -	    (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
> +	if (!subcomm || !name1 || !name2 ||
> +	    (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") &&
> +	     strcmp(subcomm, "swap-position")))
>   		return -EINVAL;
>   
>   	ret = get_disk_guid(dev_desc, disk_guid);
> @@ -920,6 +921,47 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
>   			ret = -EINVAL;
>   			goto out;
>   		}
> +	} else if (!strcmp(subcomm, "swap-position")) {
> +		int idx1, idx2;
> +		struct disk_partition first, second;
> +
> +		idx1 = simple_strtoul(name1, NULL, 10);
> +		if (idx1 <= 0 || idx1 > numparts) {

The number of partitions is irrelevant here.

Take a partition table with two partitions 37 and 63. numparts is 2. But 
of course you can swap the two. You have to check that idx1 relates to 
an existing partition here.

I would have preferred to see the numerous bugs in the gpt command to be 
fixed before adding new functionality.

> +			printf("Illegal partition number %s\n", name1);
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		idx2 = simple_strtoul(name2, NULL, 10);
> +		if (idx2 <= 0 || idx2 > numparts) {
> +			printf("Illegal partition number %s\n", name2);
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		if (idx1 == idx2) {
> +			printf("Cannot swap partition with itself\n");
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		i = 1;
> +		list_for_each(pos, &disk_partitions) {
> +			curr = list_entry(pos, struct disk_part, list);
> +			if (i == idx1)
> +				first = curr->gpt_part_info;
> +			else if (i == idx2)
> +				second = curr->gpt_part_info;
> +			i++;
> +		}
> +
> +		i = 1;
> +		list_for_each(pos, &disk_partitions) {
> +			curr = list_entry(pos, struct disk_part, list);
> +			if (i == idx1)
> +				curr->gpt_part_info = second;
> +			else if (i == idx2)
> +				curr->gpt_part_info = first;
> +			i++;
> +		}
>   	} else { /* rename */
>   		if (strlen(name2) > PART_NAME_LEN) {
>   			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
> @@ -1123,7 +1165,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>   	} else if (strcmp(argv[1], "read") == 0) {
>   		ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
>   	} else if ((strcmp(argv[1], "swap") == 0) ||
> -		   (strcmp(argv[1], "rename") == 0)) {
> +		   (strcmp(argv[1], "rename") == 0) ||
> +		   (strcmp(argv[1], "swap-position") == 0)) {
>   		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
>   	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
>   		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
> @@ -1176,6 +1219,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
>   	" gpt swap <interface> <dev> <name1> <name2>\n"
>   	"    - change all partitions named name1 to name2\n"
>   	"      and vice-versa\n"
> +	" gpt swap-position <interface> <dev> <part1> <part2>\n"
> +	"    - Swap the order of name1 with name2 in the partition table\n"
>   	" gpt rename <interface> <dev> <part> <name>\n"
>   	"    - rename the specified partition\n"
>   	" gpt set-bootable <interface> <dev> <list>\n"
> @@ -1184,5 +1229,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
>   	" gpt swap mmc 0 foo bar\n"
>   	" gpt rename mmc 0 3 foo\n"
>   	" gpt set-bootable mmc 0 boot_a,boot_b\n"
> +	" gpt swap-position mmc 0 1 2\n"
>   #endif
>   );
> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> index 353dfb05cf..bc14bda6e5 100644
> --- a/doc/usage/cmd/gpt.rst
> +++ b/doc/usage/cmd/gpt.rst
> @@ -17,6 +17,7 @@ Synopsis
>       gpt read <interface> <device no> [<varname>]
>       gpt swap <interface> <dev> <name1> <name2>
>       gpt rename <interface> <dev> <part> <name>
> +    gpt swap-position <interface> <dev> <part1> <part2>
>       gpt set-bootable <interface> <dev> <partition list>
>   
>   Description
> @@ -138,6 +139,28 @@ CONFIG_CMD_GPT_RENAME=y is required.
>   The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
>   CONFIG_CMD_GPT_RENAME=y is required.
>   
> +The 'gpt swap-position' command swaps the order of two partition index in the

Two requires a plural form.

You don't swap indices, you swap the partition table entries indexed by 
part1 and part2.

> +partition table, but otherwise leaves the actual partition data untouched. For
> +example, to swap the order of the 'boot' and 'rootfs' partitions in the disk

You don't swap the order in the disks. You swap the entries in the 
partition table.

Best regards

Heinrich

> +described above, you would do:
> +
> +::
> +    => gpt setenv mmc 0 rootfs
> +    => echo ${gpt_partition_entry}
> +    2
> +    => gpt setenv mmc 0 boot
> +    => echo ${gpt_partition_entry}
> +    1
> +
> +    => gpt swap-position mmc 0 1 2
> +
> +    => gpt setenv mmc 0 rootfs
> +    => echo ${gpt_partition_entry}
> +    1
> +    => gpt setenv mmc 0 boot
> +    => echo ${gpt_partition_entry}
> +    2
> +
>   The 'gpt set-bootable' command sets the bootable flag for all partitions in the
>   table. If the partition name is in 'partition list' (separated by ','), the
>   bootable flag is set, otherwise it is cleared. CONFIG_CMD_GPT_RENAME=y is
> diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
> index 666d387ac8..3d23b98cea 100644
> --- a/test/py/tests/test_gpt.py
> +++ b/test/py/tests/test_gpt.py
> @@ -330,3 +330,21 @@ def test_gpt_write(state_disk_image, u_boot_console):
>       output = u_boot_console.run_command('gpt guid host 0')
>       assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
>   
> +@pytest.mark.buildconfigspec('cmd_gpt')
> +@pytest.mark.buildconfigspec('cmd_gpt_rename')
> +@pytest.mark.buildconfigspec('cmd_part')
> +@pytest.mark.requiredtool('sgdisk')
> +def test_gpt_swap_position(state_disk_image, u_boot_console):
> +    """Test the gpt swap-position command."""
> +
> +    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
> +    output = u_boot_console.run_command('part list host 0')
> +    assert '1\t0x00000800\t0x00000fff\t"part1"' in output
> +    assert '2\t0x00001000\t0x00001bff\t"part2"' in output
> +
> +    output = u_boot_console.run_command('gpt swap-position host 0 1 2')
> +    assert 'success!' in output
> +
> +    output = u_boot_console.run_command('part list host 0')
> +    assert '2\t0x00000800\t0x00000fff\t"part1"' in output
> +    assert '1\t0x00001000\t0x00001bff\t"part2"' in output

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-25 19:38     ` [PATCH v3 2/8] doc: Add gpt command documentation Joshua Watt
  2023-08-25 23:53       ` Simon Glass
@ 2023-08-26  1:57       ` Heinrich Schuchardt
  2023-08-28 19:29         ` Joshua Watt
  1 sibling, 1 reply; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-26  1:57 UTC (permalink / raw)
  To: Joshua Watt; +Cc: Simon Glass, u-boot

On 8/25/23 21:38, Joshua Watt wrote:
> Adds initial documentation for the gpt command

Thanks a lot for filling the gap.

>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>   doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
>   doc/usage/index.rst   |   1 +
>   2 files changed, 142 insertions(+)
>   create mode 100644 doc/usage/cmd/gpt.rst
>
> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> new file mode 100644
> index 0000000000..f6e082fb94
> --- /dev/null
> +++ b/doc/usage/cmd/gpt.rst
> @@ -0,0 +1,141 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +gpt command
> +===========
> +
> +Synopsis
> +--------
> +
> +::
> +
> +    gpt repair <interface> <device no>
> +    gpt write <interface> <device no> <partition string>
> +    gpt verify <interface> <device no> <partition string>

<partition string> is not required. Please, add brackets [].

> +    gpt setenv <interface> <device no> <partition name>

gpt setenv can be called without partition name which leads to a crash.

If that parameter is meant to be optional, this should be indicated
here. Otherwise an argc check is missing.

> +    gpt enumerate <interface> <device no>
> +    gpt guid <interface> <device no> [<varname>]
> +    gpt read <interface> <device no> [<varname>]
> +    gpt swap <interface> <dev> <name1> <name2>
> +    gpt rename <interface> <dev> <part> <name>

Thanks a lot for providing a man-page for this command.

If <device no> and <dev> both relate to the same object type, we should
use the same text. <dev> would be fine.

The sequence looks random. Please, sort the sub-commands either
logically or alphabetically.

> +
> +Description
> +-----------
> +
> +The gpt command lets users read, create, modify, or verify the GPT (GUID
> +Partition Table) partition layout.
> +
> +The syntax of the text description of the partition list is similar to
> +the one used by the 'mbr' command. The string contains one or more partition

Please, link the mbr page:

by the :doc:`mbr command <mbr>`.

> +descriptors, each separated by a ";". Each descriptor contains one or more
> +fields, with each field separated by a ",". Fields are either of the form
> +"key=value" to set a specific value, or simple "flag" to set a boolean flag

At this point it remains unclear to the reader what this ;-separated
string format relates to.
Is it an output format?
Is it a format used in variables?
Is it used for the parameter 'partition string'?

Maybe describe it after the parameters and relate it to the 'partition
string' parameter.

Please, describe all parameters (in this indented format):

interface
     interface for accessing the block device (mmc, sata, scsi, usb, ....)

device no
     device number

...

> +
> +The first descriptor can optionally be used to describe parameters for the
> +whole disk with the following fields:
> +
> +* uuid_disk=UUID - Set the UUID for the disk
> +
> +Partition descriptors can have the following fields:
> +* name=NAME - The partition name, required

Maybe better

name=<NAME>

This is not rendered as an unordered list but everything is in one line.
Please, add the missing blank lines.

Please, generate the HTML documentation as described in
https://u-boot.readthedocs.io/en/latest/build/documentation.html
and check the output before resubmitting.

> +* start=BYTES - The partition start offset in bytes, required
> +* size=BYTES - The partition size, in bytes or "-" to expand it to the whole free area
> +* bootable - Set the legacy bootable flag
> +* uuid=UUID - Set the partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
> +* type=UUID - Set the partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
> +

The following should be in a separate 'Examples' section to match the
other man-pages.

> +Here is an example how to create a 6 partitions, some of the predefined sizes:
> +
> +::
> +
> +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
> +        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
> +        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
> +    => gpt write mmc 0 $gpt_parts
> +
> +
> +If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
> +will be generated for the partition
> +
> +The 'gpt verify' command returns 0 if the layout matches the one on the storage
> +device or 1 if not. To check if the layout on the MMC #0 storage device
> +matches the provided text description one has to issue following command:

The command can be used with and without partition parameter. This
should be described here.

I would prefer:

sets the return value $? to 0 (true) if the layout
or 1 (false) if not

> +
> +::
> +
> +    => gpt verify mmc 0 $gpt_parts
> +
> +The verify sub-command is especially useful in the system update scripts:
> +
> +::
> +
> +    => if gpt verify mmc 0 $gpt_parts; then
> +         echo GPT layout needs to be updated
> +         ...
> +       fi
> +
> +The 'gpt write' command returns 0 on success write or 1 on failure.
> +
> +The 'gpt setenv' command will set a series of environment variables with
> +information about a particular partition. The variables are:
> +
> +* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
> +* gpt_partition_size (the size of the partition, in hexadecimal blocks)

The blocks that are not hexadecimal, the numbers are.

gpt_partition_addr (first block of the partition as hexadecimal number)
gpt_partition_size (number of blocks as hexadecimal number)

> +* gpt_partition_name (the name of the partition)
> +* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)

This value is currently decimal but this seems to be a bug. We need a
hexadecimal number to use this variable in a command like

     load host 0:$gpt_partition_entry $loadaddr filename

Another bug is that this command assumes that partitions are
continuously numbered.

> +
> +To get the information about the partition named 'rootfs', issue the following
> +command:
> +
> +::
> +    => gpt setenv mmc 0 rootfs
> +    => echo ${gpt_partition_addr}
> +    2000
> +    => echo ${gpt_partition_size}
> +    14a000
> +    => echo ${gpt_partition_name}
> +    rootfs
> +    => echo ${gpt_partition_entry}
> +    2
> +
> +The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
> +list of partition names on the device. For example:
> +
> +::
> +    => gpt enumerate
> +    => echo gpt_partition_list
> +    boot rootfs system-data [ext] user modules ramdisk

As we cannot see from the output if there is a partition 'user' and a
partition 'modules' or only a single partition 'user modules' this
sub-command seems to need some rework.

Best regards

Heinrich

> +
> +The 'gpt guid' command will report the GUID of a disk. If 'varname' is
> +specified, the command will set the variable to the GUID, otherwise it will be
> +printed out. For example:
> +
> +::
> +    => gpt guid mmc 0
> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> +    => gpt guid mmc gpt_disk_uuid
> +    => echo ${gpt_disk_uuid}
> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> +
> +The 'gpt read' command will print out the current state of the GPT partition
> +table. If 'varname' is specified, the variable will be filled with a partition
> +string as described above that is suitable for passing to other 'gpt' commands.
> +If omitted, a human readable description is printed out.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +The 'gpt swap' command changes the names of all partitions that are named
> +'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +Configuration
> +-------------
> +
> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
> +read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> index 3326ec82ff..4bfaabbd16 100644
> --- a/doc/usage/index.rst
> +++ b/doc/usage/index.rst
> @@ -65,6 +65,7 @@ Shell commands
>      cmd/for
>      cmd/fwu_mdata
>      cmd/gpio
> +   cmd/gpt
>      cmd/host
>      cmd/imxtract
>      cmd/load


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-26  1:57       ` Heinrich Schuchardt
@ 2023-08-28 19:29         ` Joshua Watt
  2023-08-28 20:01           ` Heinrich Schuchardt
  0 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 19:29 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: Simon Glass, u-boot

On Fri, Aug 25, 2023 at 7:57 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 8/25/23 21:38, Joshua Watt wrote:
> > Adds initial documentation for the gpt command
>
> Thanks a lot for filling the gap.
>
> >
> > Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> > ---
> >   doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
> >   doc/usage/index.rst   |   1 +
> >   2 files changed, 142 insertions(+)
> >   create mode 100644 doc/usage/cmd/gpt.rst
> >
> > diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> > new file mode 100644
> > index 0000000000..f6e082fb94
> > --- /dev/null
> > +++ b/doc/usage/cmd/gpt.rst
> > @@ -0,0 +1,141 @@
> > +.. SPDX-License-Identifier: GPL-2.0+
> > +
> > +gpt command
> > +===========
> > +
> > +Synopsis
> > +--------
> > +
> > +::
> > +
> > +    gpt repair <interface> <device no>
> > +    gpt write <interface> <device no> <partition string>
> > +    gpt verify <interface> <device no> <partition string>
>
> <partition string> is not required. Please, add brackets [].

It's not optional; there is no standardized string for the list of GPT
partitions like there is for MBR

>
> > +    gpt setenv <interface> <device no> <partition name>
>
> gpt setenv can be called without partition name which leads to a crash.
>
> If that parameter is meant to be optional, this should be indicated
> here. Otherwise an argc check is missing.

I don't believe the argument is optional, but either way it can be
fixed in a subsequent patch series. I'd rather not hold up the
documentation to fix bugs

>
> > +    gpt enumerate <interface> <device no>
> > +    gpt guid <interface> <device no> [<varname>]
> > +    gpt read <interface> <device no> [<varname>]
> > +    gpt swap <interface> <dev> <name1> <name2>
> > +    gpt rename <interface> <dev> <part> <name>
>
> Thanks a lot for providing a man-page for this command.
>
> If <device no> and <dev> both relate to the same object type, we should
> use the same text. <dev> would be fine.
>
> The sequence looks random. Please, sort the sub-commands either
> logically or alphabetically.

They are sorted to match the gpt command help text. Reordering of both
can be done later if desired.

>
> > +
> > +Description
> > +-----------
> > +
> > +The gpt command lets users read, create, modify, or verify the GPT (GUID
> > +Partition Table) partition layout.
> > +
> > +The syntax of the text description of the partition list is similar to
> > +the one used by the 'mbr' command. The string contains one or more partition
>
> Please, link the mbr page:
>
> by the :doc:`mbr command <mbr>`.
>
> > +descriptors, each separated by a ";". Each descriptor contains one or more
> > +fields, with each field separated by a ",". Fields are either of the form
> > +"key=value" to set a specific value, or simple "flag" to set a boolean flag
>
> At this point it remains unclear to the reader what this ;-separated
> string format relates to.
> Is it an output format?
> Is it a format used in variables?
> Is it used for the parameter 'partition string'?
>
> Maybe describe it after the parameters and relate it to the 'partition
> string' parameter.
>
> Please, describe all parameters (in this indented format):
>
> interface
>      interface for accessing the block device (mmc, sata, scsi, usb, ....)
>
> device no
>      device number
>
> ...
>
> > +
> > +The first descriptor can optionally be used to describe parameters for the
> > +whole disk with the following fields:
> > +
> > +* uuid_disk=UUID - Set the UUID for the disk
> > +
> > +Partition descriptors can have the following fields:
> > +* name=NAME - The partition name, required
>
> Maybe better
>
> name=<NAME>
>
> This is not rendered as an unordered list but everything is in one line.
> Please, add the missing blank lines.
>
> Please, generate the HTML documentation as described in
> https://u-boot.readthedocs.io/en/latest/build/documentation.html
> and check the output before resubmitting.
>
> > +* start=BYTES - The partition start offset in bytes, required
> > +* size=BYTES - The partition size, in bytes or "-" to expand it to the whole free area
> > +* bootable - Set the legacy bootable flag
> > +* uuid=UUID - Set the partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
> > +* type=UUID - Set the partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
> > +
>
> The following should be in a separate 'Examples' section to match the
> other man-pages.
>
> > +Here is an example how to create a 6 partitions, some of the predefined sizes:
> > +
> > +::
> > +
> > +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
> > +        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
> > +        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> > +        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> > +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> > +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> > +        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> > +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
> > +    => gpt write mmc 0 $gpt_parts
> > +
> > +
> > +If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
> > +will be generated for the partition
> > +
> > +The 'gpt verify' command returns 0 if the layout matches the one on the storage
> > +device or 1 if not. To check if the layout on the MMC #0 storage device
> > +matches the provided text description one has to issue following command:
>
> The command can be used with and without partition parameter. This
> should be described here.
>
> I would prefer:
>
> sets the return value $? to 0 (true) if the layout
> or 1 (false) if not
>
> > +
> > +::
> > +
> > +    => gpt verify mmc 0 $gpt_parts
> > +
> > +The verify sub-command is especially useful in the system update scripts:
> > +
> > +::
> > +
> > +    => if gpt verify mmc 0 $gpt_parts; then
> > +         echo GPT layout needs to be updated
> > +         ...
> > +       fi
> > +
> > +The 'gpt write' command returns 0 on success write or 1 on failure.
> > +
> > +The 'gpt setenv' command will set a series of environment variables with
> > +information about a particular partition. The variables are:
> > +
> > +* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
> > +* gpt_partition_size (the size of the partition, in hexadecimal blocks)
>
> The blocks that are not hexadecimal, the numbers are.
>
> gpt_partition_addr (first block of the partition as hexadecimal number)
> gpt_partition_size (number of blocks as hexadecimal number)
>
> > +* gpt_partition_name (the name of the partition)
> > +* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
>
> This value is currently decimal but this seems to be a bug. We need a
> hexadecimal number to use this variable in a command like
>
>      load host 0:$gpt_partition_entry $loadaddr filename
>
> Another bug is that this command assumes that partitions are
> continuously numbered.
>
> > +
> > +To get the information about the partition named 'rootfs', issue the following
> > +command:
> > +
> > +::
> > +    => gpt setenv mmc 0 rootfs
> > +    => echo ${gpt_partition_addr}
> > +    2000
> > +    => echo ${gpt_partition_size}
> > +    14a000
> > +    => echo ${gpt_partition_name}
> > +    rootfs
> > +    => echo ${gpt_partition_entry}
> > +    2
> > +
> > +The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
> > +list of partition names on the device. For example:
> > +
> > +::
> > +    => gpt enumerate
> > +    => echo gpt_partition_list
> > +    boot rootfs system-data [ext] user modules ramdisk
>
> As we cannot see from the output if there is a partition 'user' and a
> partition 'modules' or only a single partition 'user modules' this
> sub-command seems to need some rework.

Can be fixed later.

>
> Best regards
>
> Heinrich
>
> > +
> > +The 'gpt guid' command will report the GUID of a disk. If 'varname' is
> > +specified, the command will set the variable to the GUID, otherwise it will be
> > +printed out. For example:
> > +
> > +::
> > +    => gpt guid mmc 0
> > +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> > +    => gpt guid mmc gpt_disk_uuid
> > +    => echo ${gpt_disk_uuid}
> > +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> > +
> > +The 'gpt read' command will print out the current state of the GPT partition
> > +table. If 'varname' is specified, the variable will be filled with a partition
> > +string as described above that is suitable for passing to other 'gpt' commands.
> > +If omitted, a human readable description is printed out.
> > +CONFIG_CMD_GPT_RENAME=y is required.
> > +
> > +The 'gpt swap' command changes the names of all partitions that are named
> > +'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
> > +CONFIG_CMD_GPT_RENAME=y is required.
> > +
> > +The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
> > +CONFIG_CMD_GPT_RENAME=y is required.
> > +
> > +Configuration
> > +-------------
> > +
> > +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
> > +read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
> > diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> > index 3326ec82ff..4bfaabbd16 100644
> > --- a/doc/usage/index.rst
> > +++ b/doc/usage/index.rst
> > @@ -65,6 +65,7 @@ Shell commands
> >      cmd/for
> >      cmd/fwu_mdata
> >      cmd/gpio
> > +   cmd/gpt
> >      cmd/host
> >      cmd/imxtract
> >      cmd/load
>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-28 19:29         ` Joshua Watt
@ 2023-08-28 20:01           ` Heinrich Schuchardt
  2023-08-28 21:01             ` Joshua Watt
  0 siblings, 1 reply; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-28 20:01 UTC (permalink / raw)
  To: Joshua Watt; +Cc: Simon Glass, u-boot

On 8/28/23 21:29, Joshua Watt wrote:
> On Fri, Aug 25, 2023 at 7:57 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>
>> On 8/25/23 21:38, Joshua Watt wrote:
>>> Adds initial documentation for the gpt command
>>
>> Thanks a lot for filling the gap.
>>
>>>
>>> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
>>> ---
>>>    doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
>>>    doc/usage/index.rst   |   1 +
>>>    2 files changed, 142 insertions(+)
>>>    create mode 100644 doc/usage/cmd/gpt.rst
>>>
>>> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
>>> new file mode 100644
>>> index 0000000000..f6e082fb94
>>> --- /dev/null
>>> +++ b/doc/usage/cmd/gpt.rst
>>> @@ -0,0 +1,141 @@
>>> +.. SPDX-License-Identifier: GPL-2.0+
>>> +
>>> +gpt command
>>> +===========
>>> +
>>> +Synopsis
>>> +--------
>>> +
>>> +::
>>> +
>>> +    gpt repair <interface> <device no>
>>> +    gpt write <interface> <device no> <partition string>
>>> +    gpt verify <interface> <device no> <partition string>
>>
>> <partition string> is not required. Please, add brackets [].
>
> It's not optional; there is no standardized string for the list of GPT
> partitions like there is for MBR

You can use the command without partition string. It will tell you if
the device is partitioned or not.

>
>>
>>> +    gpt setenv <interface> <device no> <partition name>
>>
>> gpt setenv can be called without partition name which leads to a crash.
>>
>> If that parameter is meant to be optional, this should be indicated
>> here. Otherwise an argc check is missing.
>
> I don't believe the argument is optional, but either way it can be
> fixed in a subsequent patch series. I'd rather not hold up the
> documentation to fix bugs
>
>>
>>> +    gpt enumerate <interface> <device no>
>>> +    gpt guid <interface> <device no> [<varname>]
>>> +    gpt read <interface> <device no> [<varname>]
>>> +    gpt swap <interface> <dev> <name1> <name2>
>>> +    gpt rename <interface> <dev> <part> <name>
>>
>> Thanks a lot for providing a man-page for this command.
>>
>> If <device no> and <dev> both relate to the same object type, we should
>> use the same text. <dev> would be fine.
>>
>> The sequence looks random. Please, sort the sub-commands either
>> logically or alphabetically.
>
> They are sorted to match the gpt command help text. Reordering of both
> can be done later if desired.

There is no requirement to follow the gpt help =sequence here.

We should not reproduce what is not helpful.

Best regards

Heinrich

>
>>
>>> +
>>> +Description
>>> +-----------
>>> +
>>> +The gpt command lets users read, create, modify, or verify the GPT (GUID
>>> +Partition Table) partition layout.
>>> +
>>> +The syntax of the text description of the partition list is similar to
>>> +the one used by the 'mbr' command. The string contains one or more partition
>>
>> Please, link the mbr page:
>>
>> by the :doc:`mbr command <mbr>`.
>>
>>> +descriptors, each separated by a ";". Each descriptor contains one or more
>>> +fields, with each field separated by a ",". Fields are either of the form
>>> +"key=value" to set a specific value, or simple "flag" to set a boolean flag
>>
>> At this point it remains unclear to the reader what this ;-separated
>> string format relates to.
>> Is it an output format?
>> Is it a format used in variables?
>> Is it used for the parameter 'partition string'?
>>
>> Maybe describe it after the parameters and relate it to the 'partition
>> string' parameter.
>>
>> Please, describe all parameters (in this indented format):
>>
>> interface
>>       interface for accessing the block device (mmc, sata, scsi, usb, ....)
>>
>> device no
>>       device number
>>
>> ...
>>
>>> +
>>> +The first descriptor can optionally be used to describe parameters for the
>>> +whole disk with the following fields:
>>> +
>>> +* uuid_disk=UUID - Set the UUID for the disk
>>> +
>>> +Partition descriptors can have the following fields:
>>> +* name=NAME - The partition name, required
>>
>> Maybe better
>>
>> name=<NAME>
>>
>> This is not rendered as an unordered list but everything is in one line.
>> Please, add the missing blank lines.
>>
>> Please, generate the HTML documentation as described in
>> https://u-boot.readthedocs.io/en/latest/build/documentation.html
>> and check the output before resubmitting.
>>
>>> +* start=BYTES - The partition start offset in bytes, required
>>> +* size=BYTES - The partition size, in bytes or "-" to expand it to the whole free area
>>> +* bootable - Set the legacy bootable flag
>>> +* uuid=UUID - Set the partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
>>> +* type=UUID - Set the partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
>>> +
>>
>> The following should be in a separate 'Examples' section to match the
>> other man-pages.
>>
>>> +Here is an example how to create a 6 partitions, some of the predefined sizes:
>>> +
>>> +::
>>> +
>>> +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
>>> +        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
>>> +        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>>> +        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>>> +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>>> +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>>> +        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>>> +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
>>> +    => gpt write mmc 0 $gpt_parts
>>> +
>>> +
>>> +If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
>>> +will be generated for the partition
>>> +
>>> +The 'gpt verify' command returns 0 if the layout matches the one on the storage
>>> +device or 1 if not. To check if the layout on the MMC #0 storage device
>>> +matches the provided text description one has to issue following command:
>>
>> The command can be used with and without partition parameter. This
>> should be described here.
>>
>> I would prefer:
>>
>> sets the return value $? to 0 (true) if the layout
>> or 1 (false) if not
>>
>>> +
>>> +::
>>> +
>>> +    => gpt verify mmc 0 $gpt_parts
>>> +
>>> +The verify sub-command is especially useful in the system update scripts:
>>> +
>>> +::
>>> +
>>> +    => if gpt verify mmc 0 $gpt_parts; then
>>> +         echo GPT layout needs to be updated
>>> +         ...
>>> +       fi
>>> +
>>> +The 'gpt write' command returns 0 on success write or 1 on failure.
>>> +
>>> +The 'gpt setenv' command will set a series of environment variables with
>>> +information about a particular partition. The variables are:
>>> +
>>> +* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
>>> +* gpt_partition_size (the size of the partition, in hexadecimal blocks)
>>
>> The blocks that are not hexadecimal, the numbers are.
>>
>> gpt_partition_addr (first block of the partition as hexadecimal number)
>> gpt_partition_size (number of blocks as hexadecimal number)
>>
>>> +* gpt_partition_name (the name of the partition)
>>> +* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
>>
>> This value is currently decimal but this seems to be a bug. We need a
>> hexadecimal number to use this variable in a command like
>>
>>       load host 0:$gpt_partition_entry $loadaddr filename
>>
>> Another bug is that this command assumes that partitions are
>> continuously numbered.
>>
>>> +
>>> +To get the information about the partition named 'rootfs', issue the following
>>> +command:
>>> +
>>> +::
>>> +    => gpt setenv mmc 0 rootfs
>>> +    => echo ${gpt_partition_addr}
>>> +    2000
>>> +    => echo ${gpt_partition_size}
>>> +    14a000
>>> +    => echo ${gpt_partition_name}
>>> +    rootfs
>>> +    => echo ${gpt_partition_entry}
>>> +    2
>>> +
>>> +The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
>>> +list of partition names on the device. For example:
>>> +
>>> +::
>>> +    => gpt enumerate
>>> +    => echo gpt_partition_list
>>> +    boot rootfs system-data [ext] user modules ramdisk
>>
>> As we cannot see from the output if there is a partition 'user' and a
>> partition 'modules' or only a single partition 'user modules' this
>> sub-command seems to need some rework.
>
> Can be fixed later.
>
>>
>> Best regards
>>
>> Heinrich
>>
>>> +
>>> +The 'gpt guid' command will report the GUID of a disk. If 'varname' is
>>> +specified, the command will set the variable to the GUID, otherwise it will be
>>> +printed out. For example:
>>> +
>>> +::
>>> +    => gpt guid mmc 0
>>> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
>>> +    => gpt guid mmc gpt_disk_uuid
>>> +    => echo ${gpt_disk_uuid}
>>> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
>>> +
>>> +The 'gpt read' command will print out the current state of the GPT partition
>>> +table. If 'varname' is specified, the variable will be filled with a partition
>>> +string as described above that is suitable for passing to other 'gpt' commands.
>>> +If omitted, a human readable description is printed out.
>>> +CONFIG_CMD_GPT_RENAME=y is required.
>>> +
>>> +The 'gpt swap' command changes the names of all partitions that are named
>>> +'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
>>> +CONFIG_CMD_GPT_RENAME=y is required.
>>> +
>>> +The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
>>> +CONFIG_CMD_GPT_RENAME=y is required.
>>> +
>>> +Configuration
>>> +-------------
>>> +
>>> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
>>> +read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
>>> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
>>> index 3326ec82ff..4bfaabbd16 100644
>>> --- a/doc/usage/index.rst
>>> +++ b/doc/usage/index.rst
>>> @@ -65,6 +65,7 @@ Shell commands
>>>       cmd/for
>>>       cmd/fwu_mdata
>>>       cmd/gpio
>>> +   cmd/gpt
>>>       cmd/host
>>>       cmd/imxtract
>>>       cmd/load
>>


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-28 20:01           ` Heinrich Schuchardt
@ 2023-08-28 21:01             ` Joshua Watt
  0 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:01 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: Simon Glass, u-boot

On Mon, Aug 28, 2023 at 2:00 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 8/28/23 21:29, Joshua Watt wrote:
> > On Fri, Aug 25, 2023 at 7:57 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >>
> >> On 8/25/23 21:38, Joshua Watt wrote:
> >>> Adds initial documentation for the gpt command
> >>
> >> Thanks a lot for filling the gap.
> >>
> >>>
> >>> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> >>> ---
> >>>    doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
> >>>    doc/usage/index.rst   |   1 +
> >>>    2 files changed, 142 insertions(+)
> >>>    create mode 100644 doc/usage/cmd/gpt.rst
> >>>
> >>> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> >>> new file mode 100644
> >>> index 0000000000..f6e082fb94
> >>> --- /dev/null
> >>> +++ b/doc/usage/cmd/gpt.rst
> >>> @@ -0,0 +1,141 @@
> >>> +.. SPDX-License-Identifier: GPL-2.0+
> >>> +
> >>> +gpt command
> >>> +===========
> >>> +
> >>> +Synopsis
> >>> +--------
> >>> +
> >>> +::
> >>> +
> >>> +    gpt repair <interface> <device no>
> >>> +    gpt write <interface> <device no> <partition string>
> >>> +    gpt verify <interface> <device no> <partition string>
> >>
> >> <partition string> is not required. Please, add brackets [].
> >
> > It's not optional; there is no standardized string for the list of GPT
> > partitions like there is for MBR
>
> You can use the command without partition string. It will tell you if
> the device is partitioned or not.

Ah, right. I missed that

>
> >
> >>
> >>> +    gpt setenv <interface> <device no> <partition name>
> >>
> >> gpt setenv can be called without partition name which leads to a crash.
> >>
> >> If that parameter is meant to be optional, this should be indicated
> >> here. Otherwise an argc check is missing.
> >
> > I don't believe the argument is optional, but either way it can be
> > fixed in a subsequent patch series. I'd rather not hold up the
> > documentation to fix bugs
> >
> >>
> >>> +    gpt enumerate <interface> <device no>
> >>> +    gpt guid <interface> <device no> [<varname>]
> >>> +    gpt read <interface> <device no> [<varname>]
> >>> +    gpt swap <interface> <dev> <name1> <name2>
> >>> +    gpt rename <interface> <dev> <part> <name>
> >>
> >> Thanks a lot for providing a man-page for this command.
> >>
> >> If <device no> and <dev> both relate to the same object type, we should
> >> use the same text. <dev> would be fine.
> >>
> >> The sequence looks random. Please, sort the sub-commands either
> >> logically or alphabetically.
> >
> > They are sorted to match the gpt command help text. Reordering of both
> > can be done later if desired.
>
> There is no requirement to follow the gpt help =sequence here.
>
> We should not reproduce what is not helpful.
>
> Best regards
>
> Heinrich
>
> >
> >>
> >>> +
> >>> +Description
> >>> +-----------
> >>> +
> >>> +The gpt command lets users read, create, modify, or verify the GPT (GUID
> >>> +Partition Table) partition layout.
> >>> +
> >>> +The syntax of the text description of the partition list is similar to
> >>> +the one used by the 'mbr' command. The string contains one or more partition
> >>
> >> Please, link the mbr page:
> >>
> >> by the :doc:`mbr command <mbr>`.
> >>
> >>> +descriptors, each separated by a ";". Each descriptor contains one or more
> >>> +fields, with each field separated by a ",". Fields are either of the form
> >>> +"key=value" to set a specific value, or simple "flag" to set a boolean flag
> >>
> >> At this point it remains unclear to the reader what this ;-separated
> >> string format relates to.
> >> Is it an output format?
> >> Is it a format used in variables?
> >> Is it used for the parameter 'partition string'?
> >>
> >> Maybe describe it after the parameters and relate it to the 'partition
> >> string' parameter.
> >>
> >> Please, describe all parameters (in this indented format):
> >>
> >> interface
> >>       interface for accessing the block device (mmc, sata, scsi, usb, ....)
> >>
> >> device no
> >>       device number
> >>
> >> ...
> >>
> >>> +
> >>> +The first descriptor can optionally be used to describe parameters for the
> >>> +whole disk with the following fields:
> >>> +
> >>> +* uuid_disk=UUID - Set the UUID for the disk
> >>> +
> >>> +Partition descriptors can have the following fields:
> >>> +* name=NAME - The partition name, required
> >>
> >> Maybe better
> >>
> >> name=<NAME>
> >>
> >> This is not rendered as an unordered list but everything is in one line.
> >> Please, add the missing blank lines.
> >>
> >> Please, generate the HTML documentation as described in
> >> https://u-boot.readthedocs.io/en/latest/build/documentation.html
> >> and check the output before resubmitting.
> >>
> >>> +* start=BYTES - The partition start offset in bytes, required
> >>> +* size=BYTES - The partition size, in bytes or "-" to expand it to the whole free area
> >>> +* bootable - Set the legacy bootable flag
> >>> +* uuid=UUID - Set the partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
> >>> +* type=UUID - Set the partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
> >>> +
> >>
> >> The following should be in a separate 'Examples' section to match the
> >> other man-pages.
> >>
> >>> +Here is an example how to create a 6 partitions, some of the predefined sizes:
> >>> +
> >>> +::
> >>> +
> >>> +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
> >>> +        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
> >>> +        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >>> +        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >>> +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >>> +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >>> +        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >>> +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
> >>> +    => gpt write mmc 0 $gpt_parts
> >>> +
> >>> +
> >>> +If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
> >>> +will be generated for the partition
> >>> +
> >>> +The 'gpt verify' command returns 0 if the layout matches the one on the storage
> >>> +device or 1 if not. To check if the layout on the MMC #0 storage device
> >>> +matches the provided text description one has to issue following command:
> >>
> >> The command can be used with and without partition parameter. This
> >> should be described here.
> >>
> >> I would prefer:
> >>
> >> sets the return value $? to 0 (true) if the layout
> >> or 1 (false) if not
> >>
> >>> +
> >>> +::
> >>> +
> >>> +    => gpt verify mmc 0 $gpt_parts
> >>> +
> >>> +The verify sub-command is especially useful in the system update scripts:
> >>> +
> >>> +::
> >>> +
> >>> +    => if gpt verify mmc 0 $gpt_parts; then
> >>> +         echo GPT layout needs to be updated
> >>> +         ...
> >>> +       fi
> >>> +
> >>> +The 'gpt write' command returns 0 on success write or 1 on failure.
> >>> +
> >>> +The 'gpt setenv' command will set a series of environment variables with
> >>> +information about a particular partition. The variables are:
> >>> +
> >>> +* gpt_partition_addr (the starting offset of the partition, in hexadecimal blocks)
> >>> +* gpt_partition_size (the size of the partition, in hexadecimal blocks)
> >>
> >> The blocks that are not hexadecimal, the numbers are.
> >>
> >> gpt_partition_addr (first block of the partition as hexadecimal number)
> >> gpt_partition_size (number of blocks as hexadecimal number)
> >>
> >>> +* gpt_partition_name (the name of the partition)
> >>> +* gpt_partition_entry (the partition number in the table, e.g. 1, 2, 3, etc.)
> >>
> >> This value is currently decimal but this seems to be a bug. We need a
> >> hexadecimal number to use this variable in a command like
> >>
> >>       load host 0:$gpt_partition_entry $loadaddr filename
> >>
> >> Another bug is that this command assumes that partitions are
> >> continuously numbered.
> >>
> >>> +
> >>> +To get the information about the partition named 'rootfs', issue the following
> >>> +command:
> >>> +
> >>> +::
> >>> +    => gpt setenv mmc 0 rootfs
> >>> +    => echo ${gpt_partition_addr}
> >>> +    2000
> >>> +    => echo ${gpt_partition_size}
> >>> +    14a000
> >>> +    => echo ${gpt_partition_name}
> >>> +    rootfs
> >>> +    => echo ${gpt_partition_entry}
> >>> +    2
> >>> +
> >>> +The 'gpt enumerate' command will set the variable 'gpt_partition_list' with the
> >>> +list of partition names on the device. For example:
> >>> +
> >>> +::
> >>> +    => gpt enumerate
> >>> +    => echo gpt_partition_list
> >>> +    boot rootfs system-data [ext] user modules ramdisk
> >>
> >> As we cannot see from the output if there is a partition 'user' and a
> >> partition 'modules' or only a single partition 'user modules' this
> >> sub-command seems to need some rework.
> >
> > Can be fixed later.
> >
> >>
> >> Best regards
> >>
> >> Heinrich
> >>
> >>> +
> >>> +The 'gpt guid' command will report the GUID of a disk. If 'varname' is
> >>> +specified, the command will set the variable to the GUID, otherwise it will be
> >>> +printed out. For example:
> >>> +
> >>> +::
> >>> +    => gpt guid mmc 0
> >>> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> >>> +    => gpt guid mmc gpt_disk_uuid
> >>> +    => echo ${gpt_disk_uuid}
> >>> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> >>> +
> >>> +The 'gpt read' command will print out the current state of the GPT partition
> >>> +table. If 'varname' is specified, the variable will be filled with a partition
> >>> +string as described above that is suitable for passing to other 'gpt' commands.
> >>> +If omitted, a human readable description is printed out.
> >>> +CONFIG_CMD_GPT_RENAME=y is required.
> >>> +
> >>> +The 'gpt swap' command changes the names of all partitions that are named
> >>> +'name1' to be 'name2', and all partitions named 'name2' to be 'name1'.
> >>> +CONFIG_CMD_GPT_RENAME=y is required.
> >>> +
> >>> +The 'gpt rename' command renames all partitions named 'part' to be 'name1'.
> >>> +CONFIG_CMD_GPT_RENAME=y is required.
> >>> +
> >>> +Configuration
> >>> +-------------
> >>> +
> >>> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
> >>> +read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
> >>> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> >>> index 3326ec82ff..4bfaabbd16 100644
> >>> --- a/doc/usage/index.rst
> >>> +++ b/doc/usage/index.rst
> >>> @@ -65,6 +65,7 @@ Shell commands
> >>>       cmd/for
> >>>       cmd/fwu_mdata
> >>>       cmd/gpio
> >>> +   cmd/gpt
> >>>       cmd/host
> >>>       cmd/imxtract
> >>>       cmd/load
> >>
>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v3 2/8] doc: Add gpt command documentation
  2023-08-25 23:53       ` Simon Glass
@ 2023-08-28 21:52         ` Joshua Watt
  0 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:52 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, Heinrich Schuchardt

On Fri, Aug 25, 2023 at 5:53 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joshua,
>
> On Fri, 25 Aug 2023 at 13:38, Joshua Watt <jpewhacker@gmail.com> wrote:
> >
> > Adds initial documentation for the gpt command
> >
> > Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> > ---
> >  doc/usage/cmd/gpt.rst | 141 ++++++++++++++++++++++++++++++++++++++++++
> >  doc/usage/index.rst   |   1 +
> >  2 files changed, 142 insertions(+)
> >  create mode 100644 doc/usage/cmd/gpt.rst
>
> I don't see a change log?

Sorry, I didn't realize patman was a thing until I just looked now;
I've just been using git send-email, and I'm not really sure how to
switch over to patman now; I'll start with it next time though.

>
> Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements
  2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                       ` (7 preceding siblings ...)
  2023-08-25 19:38     ` [PATCH v3 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
@ 2023-08-28 21:56     ` Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 1/8] cmd: gpt: Remove confusing help text Joshua Watt
                         ` (8 more replies)
  8 siblings, 9 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds several improvements and additions to the gpt command processing,
specifically (although not exclusively) for the purpose of supporting
"ping-pong" booting when doing A/B boot partitions with u-boot itself.

In this mechanism, u-boot must boot up, and then check if the correct
boot partition is active, and if not switch the GPT partition table to
the other boot partition and reboot to activate the other u-boot.

In order to facilitate this, the gpt command needs to be better at
preserving entry attributes when manipulating the partition table. It
also learns two new commands, one which can swap the order of partitions
in the table, and another that lets it change which partitions have the
bootable flag.

V2: Add documentation and tests
V3: Review Feedback
V4: More review feedback. Fixed 'gpt swap-partition' to work with
    missing partition indexes.

Joshua Watt (8):
  cmd: gpt: Remove confusing help text
  doc: Add gpt command documentation
  tests: gpt: Remove test order dependency
  cmd: gpt: Add gpt_partition_bootable variable
  cmd: gpt: Add command to set bootable flags
  cmd: gpt: Preserve type GUID if enabled
  cmd: gpt: Preserve bootable flag
  cmd: gpt: Add command to swap partition order

 cmd/gpt.c                 | 156 ++++++++++++++++++++++++--
 doc/usage/cmd/gpt.rst     | 226 ++++++++++++++++++++++++++++++++++++++
 doc/usage/index.rst       |   1 +
 test/py/tests/test_gpt.py | 160 +++++++++++++++++++++++++--
 4 files changed, 524 insertions(+), 19 deletions(-)
 create mode 100644 doc/usage/cmd/gpt.rst

-- 
2.33.0


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v4 1/8] cmd: gpt: Remove confusing help text
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 22:05         ` Heinrich Schuchardt
  2023-08-28 21:56       ` [PATCH v4 2/8] doc: Add gpt command documentation Joshua Watt
                         ` (7 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt

This help text appears to be a fragment of the text shown when
CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 964056bd28..fe9e06681c 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -1060,8 +1060,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      gpt_partition_name, gpt_partition_entry\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
-	" read <interface> <dev>\n"
-	"    - read GPT into a data structure for manipulation\n"
 	" gpt guid <interface> <dev>\n"
 	"    - print disk GUID\n"
 	" gpt guid <interface> <dev> <varname>\n"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 2/8] doc: Add gpt command documentation
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 1/8] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 22:45         ` Heinrich Schuchardt
  2023-08-28 21:56       ` [PATCH v4 3/8] tests: gpt: Remove test order dependency Joshua Watt
                         ` (6 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt

Adds initial documentation for the gpt command

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 doc/usage/cmd/gpt.rst | 184 ++++++++++++++++++++++++++++++++++++++++++
 doc/usage/index.rst   |   1 +
 2 files changed, 185 insertions(+)
 create mode 100644 doc/usage/cmd/gpt.rst

diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
new file mode 100644
index 0000000000..6387c8116f
--- /dev/null
+++ b/doc/usage/cmd/gpt.rst
@@ -0,0 +1,184 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+gpt command
+===========
+
+Synopsis
+--------
+
+::
+
+    gpt enumerate <interface> <dev>
+    gpt guid <interface> <dev> [<varname>]
+    gpt read <interface> <dev> [<varname>]
+    gpt rename <interface> <dev> <part> <name>
+    gpt repair <interface> <dev>
+    gpt setenv <interface> <dev> <partition name>
+    gpt swap <interface> <dev> <name1> <name2>
+    gpt verify <interface> <dev> [<partition string>]
+    gpt write <interface> <dev> <partition string>
+
+Description
+-----------
+
+The gpt command lets users read, create, modify, or verify the GPT (GUID
+Partition Table) partition layout.
+
+Common arguments:
+
+interface
+    interface for accessing the block device (mmc, sata, scsi, usb, ....)
+
+dev
+    device number
+
+partition string
+    Describes the GPT partition layout for a disk.  The syntax is similar to
+    the one used by the :doc:`mbr command <mbr>` command. The string contains
+    one or more partition descriptors, each separated by a ";". Each descriptor
+    contains one or more fields, with each field separated by a ",". Fields are
+    either of the form "key=value" to set a specific value, or simple "flag" to
+    set a boolean flag
+
+    The first descriptor can optionally be used to describe parameters for the
+    whole disk with the following fields:
+
+    * uuid_disk=UUID - Set the UUID for the disk
+
+    Partition descriptors can have the following fields:
+
+    * name=<NAME> - The partition name, required
+    * start=<BYTES> - The partition start offset in bytes, required
+    * size=<BYTES> - The partition size in bytes or "-" to expand it to the whole free area
+    * bootable - Set the legacy bootable flag
+    * uuid=<UUID> - The partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
+    * type=<UUID> - The partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
+
+
+    If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
+    will be generated for the partition
+
+gpt enumerate
+~~~~~~~~~~~~~
+
+Sets the variable 'gpt_partition_list' to be a list of all the partition names
+on the device.
+
+gpt guid
+~~~~~~~~
+
+Report the GUID of a disk. If 'varname' is specified, the command will set the
+variable to the GUID, otherwise it will be printed out.
+
+gpt read
+~~~~~~~~
+
+Prints the current state of the GPT partition table. If 'varname' is specified,
+the variable will be filled with a partition string in the same format as a
+'<partition string>', suitable for passing to other 'gpt' commands.  If the
+argument is omitted, a human readable description is printed out.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+gpt rename
+~~~~~~~~~~
+
+Renames all partitions named 'part' to be 'name'. CONFIG_CMD_GPT_RENAME=y is
+required.
+
+gpt repair
+~~~~~~~~~~
+
+Repairs the GPT partition tables if it they become corrupted.
+
+gpt setenv
+~~~~~~~~~~
+
+The 'gpt setenv' command will set a series of environment variables with
+information about the partition named '<partition name>'. The variables are:
+
+gpt_partition_addr
+    the starting offset of the partition in blocks as a hexadecimal number
+
+gpt_partition_size
+    the size of the partition in blocks as a hexadecimal number
+
+gpt_partition_name
+    the name of the partition
+
+gpt_partition_entry
+    the partition number in the table, e.g. 1, 2, 3, etc.
+
+gpt swap
+~~~~~~~~
+
+Changes the names of all partitions that are named 'name1' to be 'name2', and
+all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
+required.
+
+gpt verify
+~~~~~~~~~~
+
+Sets return value $? to 0 (true) if the partition layout on the
+specified disk matches the one in the provided partition string, and 1 (false)
+if it does not match. If no partition string is specified, the command will
+check if the disk is partitioned or not.
+
+gpt write
+~~~~~~~~~
+
+(Re)writes the partition table on the disk to match the provided
+partition string. It returns 0 on success or 1 on failure.
+
+Configuration
+-------------
+
+To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
+read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
+
+Examples
+~~~~~~~~
+Create 6 partitions on a disk::
+
+    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
+        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
+        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
+    => gpt write mmc 0 $gpt_parts
+
+
+Verify that the device matches the partition layout described in the variable
+$gpt_parts::
+
+    => gpt verify mmc 0 $gpt_parts
+
+
+Get the information about the partition named 'rootfs'::
+
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_addr}
+    2000
+    => echo ${gpt_partition_size}
+    14a000
+    => echo ${gpt_partition_name}
+    rootfs
+    => echo ${gpt_partition_entry}
+    2
+
+Get the list of partition names on the disk::
+
+    => gpt enumerate
+    => echo gpt_partition_list
+    boot rootfs system-data [ext] user modules ramdisk
+
+
+Get the GUID for a disk::
+
+    => gpt guid mmc 0
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
+    => gpt guid mmc gpt_disk_uuid
+    => echo ${gpt_disk_uuid}
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index f45a7f5502..fa702920fa 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -66,6 +66,7 @@ Shell commands
    cmd/for
    cmd/fwu_mdata
    cmd/gpio
+   cmd/gpt
    cmd/host
    cmd/imxtract
    cmd/load
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 3/8] tests: gpt: Remove test order dependency
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 1/8] cmd: gpt: Remove confusing help text Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
                         ` (5 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Re-create a clean disk image for each test to prevent modifications from
one test affecting another

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 test/py/tests/test_gpt.py | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 73bfbf77a2..339468bc12 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -61,18 +61,14 @@ class GptTestDiskImage(object):
         cmd = ('cp', persistent, self.path)
         u_boot_utils.run_and_log(u_boot_console, cmd)
 
-gtdi = None
 @pytest.fixture(scope='function')
 def state_disk_image(u_boot_console):
     """pytest fixture to provide a GptTestDiskImage object to tests.
     This is function-scoped because it uses u_boot_console, which is also
-    function-scoped. However, we don't need to actually do any function-scope
-    work, so this simply returns the same object over and over each time."""
+    function-scoped. A new disk is returned each time to prevent tests from
+    interfering with each other."""
 
-    global gtdi
-    if not gtdi:
-        gtdi = GptTestDiskImage(u_boot_console)
-    return gtdi
+    return GptTestDiskImage(u_boot_console)
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
@@ -186,12 +182,12 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
 
     u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"first"' in output
-    assert '0x00001000	0x00001bff	"second"' in output
-    u_boot_console.run_command('gpt swap host 0 first second')
+    assert '0x00000800	0x00000fff	"part1"' in output
+    assert '0x00001000	0x00001bff	"part2"' in output
+    u_boot_console.run_command('gpt swap host 0 part1 part2')
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"second"' in output
-    assert '0x00001000	0x00001bff	"first"' in output
+    assert '0x00000800	0x00000fff	"part2"' in output
+    assert '0x00001000	0x00001bff	"part1"' in output
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 4/8] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                         ` (2 preceding siblings ...)
  2023-08-28 21:56       ` [PATCH v4 3/8] tests: gpt: Remove test order dependency Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
                         ` (4 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt, Enric Balletbo i Serra

Adds an additional variable called gpt_partition_bootable that indicates
if the given partition is bootable or not.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 |  9 +++++++--
 doc/usage/cmd/gpt.rst     |  5 +++++
 test/py/tests/test_gpt.py | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index fe9e06681c..c6c8282ac9 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -725,7 +725,7 @@ static int gpt_enumerate(struct blk_desc *desc)
  * gpt_setenv_part_variables() - setup partition environmental variables
  *
  * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
- * and gpt_partition_size environment variables.
+ * and gpt_partition_size, gpt_partition_bootable environment variables.
  *
  * @pinfo: pointer to disk partition
  * @i: partition entry
@@ -752,6 +752,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
 	if (ret)
 		goto fail;
 
+	ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
+	if (ret)
+		goto fail;
+
 	return 0;
 
 fail:
@@ -1057,7 +1061,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt setenv mmc 0 $name\n"
 	"    - setup environment variables for partition $name:\n"
 	"      gpt_partition_addr, gpt_partition_size,\n"
-	"      gpt_partition_name, gpt_partition_entry\n"
+	"      gpt_partition_name, gpt_partition_entry,\n"
+	"      gpt_partition_bootable\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
 	" gpt guid <interface> <dev>\n"
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index 6387c8116f..b505b159d0 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -108,6 +108,9 @@ gpt_partition_name
 gpt_partition_entry
     the partition number in the table, e.g. 1, 2, 3, etc.
 
+gpt_partition_bootable
+    1 if the partition is marked as bootable, 0 if not
+
 gpt swap
 ~~~~~~~~
 
@@ -167,6 +170,8 @@ Get the information about the partition named 'rootfs'::
     rootfs
     => echo ${gpt_partition_entry}
     2
+    => echo ${gpt_partition_bootable}
+    0
 
 Get the list of partition names on the disk::
 
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 339468bc12..946858800d 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -49,6 +49,7 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
@@ -117,6 +118,38 @@ def test_gpt_guid(state_disk_image, u_boot_console):
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_setenv(state_disk_image, u_boot_console):
+    """Test the gpt setenv command."""
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt setenv host 0 part1')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part1'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == '1'
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == '1'
+
+    output = u_boot_console.run_command('gpt setenv host 0 part2')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '1000'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == 'c00'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part2'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == '2'
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                         ` (3 preceding siblings ...)
  2023-08-28 21:56       ` [PATCH v4 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 22:54         ` Heinrich Schuchardt
  2023-08-28 21:56       ` [PATCH v4 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
                         ` (3 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Heinrich Schuchardt, Simon Glass, Enric Balletbo i Serra

Adds a command that can be used to modify the GPT partition table to
indicate which partitions should have the bootable flag set

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 80 +++++++++++++++++++++++++++++++++++++++
 doc/usage/cmd/gpt.rst     | 12 ++++++
 test/py/tests/test_gpt.py | 22 +++++++++++
 3 files changed, 114 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index c6c8282ac9..45fbe07404 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -972,6 +972,81 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	free(partitions_list);
 	return ret;
 }
+
+/**
+ * gpt_set_bootable() - Set bootable flags for partitions
+ *
+ * Sets the bootable flag for any partition names in the comma separated list of
+ * partition names. Any partitions not in the list have their bootable flag
+ * cleared
+ *
+ * @desc: block device descriptor
+ * @name: Comma separated list of partition names
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const part_list)
+{
+	char *name;
+	char disk_guid[UUID_STR_LEN + 1];
+	struct list_head *pos;
+	struct disk_part *curr;
+	struct disk_partition *partitions = NULL;
+	int part_count = 0;
+	int ret = get_disk_guid(blk_dev_desc, disk_guid);
+
+	if (ret < 0)
+		return ret;
+
+	ret = get_gpt_info(blk_dev_desc);
+	if (ret <= 0)
+		goto out;
+
+	part_count = ret;
+	partitions = malloc(sizeof(*partitions) * part_count);
+	if (!partitions) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Copy partitions and clear bootable flag */
+	part_count = 0;
+	list_for_each(pos, &disk_partitions) {
+		curr = list_entry(pos, struct disk_part, list);
+		partitions[part_count] = curr->gpt_part_info;
+		partitions[part_count].bootable &= ~PART_BOOTABLE;
+		part_count++;
+	}
+
+	name = strtok(part_list, ",");
+	while (name) {
+		bool found = false;
+
+		for (int i = 0; i < part_count; i++) {
+			if (strcmp((char *)partitions[i].name, name) == 0) {
+				partitions[i].bootable |= PART_BOOTABLE;
+				found = true;
+			}
+		}
+
+		if (!found) {
+			printf("Warning: No partition matching '%s' found\n",
+			       name);
+		}
+
+		name = strtok(NULL, ",");
+	}
+
+	ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
+
+out:
+	del_gpt_info();
+
+	if (partitions)
+		free(partitions);
+
+	return ret;
+}
 #endif
 
 /**
@@ -1031,6 +1106,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if ((strcmp(argv[1], "swap") == 0) ||
 		   (strcmp(argv[1], "rename") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
+	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
+		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
 #endif
 	} else {
 		return CMD_RET_USAGE;
@@ -1082,8 +1159,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      and vice-versa\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
+	" gpt set-bootable <interface> <dev> <list>\n"
+	"    - make partition names in list bootable\n"
 	" Example usage:\n"
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
+	" gpt set-bootable mmc 0 boot_a,boot_b\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index b505b159d0..288dd365c0 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -13,6 +13,7 @@ Synopsis
     gpt read <interface> <dev> [<varname>]
     gpt rename <interface> <dev> <part> <name>
     gpt repair <interface> <dev>
+    gpt set-bootable <interface> <dev> <partition list>
     gpt setenv <interface> <dev> <partition name>
     gpt swap <interface> <dev> <name1> <name2>
     gpt verify <interface> <dev> [<partition string>]
@@ -90,6 +91,13 @@ gpt repair
 
 Repairs the GPT partition tables if it they become corrupted.
 
+gpt set-bootable
+~~~~~~~~~~~~~~~~
+
+Sets the bootable flag for all partitions in the table. If the partition name
+is in 'partition list' (separated by ','), the bootable flag is set, otherwise
+it is cleared. CONFIG_CMD_GPT_RENAME=y is required.
+
 gpt setenv
 ~~~~~~~~~~
 
@@ -187,3 +195,7 @@ Get the GUID for a disk::
     => gpt guid mmc gpt_disk_uuid
     => echo ${gpt_disk_uuid}
     bec9fc2a-86c1-483d-8a0e-0109732277d7
+
+Set the bootable flag for the 'boot' partition and clear it for all others::
+
+    => gpt set-bootable mmc 0 boot
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 946858800d..5d23f9b292 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -222,6 +222,28 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part2"' in output
     assert '0x00001000	0x00001bff	"part1"' in output
 
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_set_bootable(state_disk_image, u_boot_console):
+    """Test the gpt set-bootable command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    parts = ('part2', 'part1')
+    for bootable in parts:
+        output = u_boot_console.run_command(f'gpt set-bootable host 0 {bootable}')
+        assert 'success!' in output
+
+        for p in parts:
+            output = u_boot_console.run_command(f'gpt setenv host 0 {p}')
+            assert 'success!' in output
+            output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+            if p == bootable:
+                assert output.rstrip() == '1'
+            else:
+                assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_part')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                         ` (4 preceding siblings ...)
  2023-08-28 21:56       ` [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
                         ` (2 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt, Enric Balletbo i Serra

If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
preserved when writing out the partition string. It was already
respected when writing out partitions; this ensures that if you capture
the current partition layout and write it back (such as when renaming),
the type GUIDs are preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 16 ++++++++++
 test/py/tests/test_gpt.py | 65 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 45fbe07404..0090e02110 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
 	/* see part.h for definition of struct disk_partition */
 	partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
 	partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
+#endif
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
 		PART_TYPE_LEN);
 	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
 	newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
+		UUID_STR_LEN);
+	newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
 		UUID_STR_LEN);
@@ -252,6 +260,9 @@ static void print_gpt_info(void)
 		       curr->gpt_part_info.name);
 		printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
 		       curr->gpt_part_info.bootable & PART_BOOTABLE);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 		printf("UUID %s\n", curr->gpt_part_info.uuid);
 #endif
@@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 					    curr->gpt_part_info.blksz);
 		strncat(partitions_list, partstr, PART_NAME_LEN + 1);
 
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		strcat(partitions_list, ",type=");
+		strncat(partitions_list, curr->gpt_part_info.type_guid,
+			UUID_STR_LEN + 1);
+#endif
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 5d23f9b292..93007dee9a 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -16,6 +16,35 @@ the test.
 # Mark all tests here as slow
 pytestmark = pytest.mark.slow
 
+def parse_gpt_parts(disk_str):
+    """Parser a partition string into a list of partitions.
+
+    Args:
+        disk_str: The disk description string, as returned by `gpt read`
+
+    Returns:
+        A list of parsed partitions. Each partition is a dictionary with the
+        string value from each specified key in the partition description, or a
+        key with with the value True for a boolean flag
+    """
+    parts = []
+    for part_str in disk_str.split(';'):
+        part = {}
+        for option in part_str.split(","):
+            if not option:
+                continue
+
+            if "=" in option:
+                key, value = option.split("=")
+                part[key] = value
+            else:
+                part[option] = True
+
+        if part:
+            parts.append(part)
+
+    return parts
+
 class GptTestDiskImage(object):
     """Disk Image used by the GPT tests."""
 
@@ -49,11 +78,13 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
                     '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
+                    '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
                     persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--load-backup=' + persistent)
@@ -88,6 +119,40 @@ def test_gpt_read(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part1"' in output
     assert '0x00001000	0x00001bff	"part2"' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('partition_type_guid')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_read_var(state_disk_image, u_boot_console):
+    """Test the gpt read command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt read host 0 gpt_parts')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('echo ${gpt_parts}')
+    parts = parse_gpt_parts(output.rstrip())
+
+    assert parts == [
+        {
+            "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
+        },
+        {
+            "name": "part1",
+            "start": "0x100000",
+            "size": "0x100000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+        },
+        {
+            "name": "part2",
+            "start": "0x200000",
+            "size": "0x180000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
+        },
+    ]
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 7/8] cmd: gpt: Preserve bootable flag
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                         ` (5 preceding siblings ...)
  2023-08-28 21:56       ` [PATCH v4 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-28 21:56       ` [PATCH v4 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt, Enric Balletbo i Serra

Sets the bootable flag when constructing the partition string from the
current partition configuration. This ensures that when the partitions
are written back (for example, when renaming a partition), the flag is
preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 3 +++
 test/py/tests/test_gpt.py | 1 +
 2 files changed, 4 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 0090e02110..927b6afa68 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -176,6 +176,7 @@ static int calc_parts_list_len(int numparts)
 #ifdef CONFIG_PARTITION_TYPE_GUID
 	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
 #endif
+	partlistlen += numparts * strlen("bootable,");
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -318,6 +319,8 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
+		if (curr->gpt_part_info.bootable & PART_BOOTABLE)
+			strcat(partitions_list, ",bootable");
 		strcat(partitions_list, ";");
 	}
 	return 0;
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 93007dee9a..b4c03bc3a2 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -143,6 +143,7 @@ def test_gpt_read_var(state_disk_image, u_boot_console):
             "size": "0x100000",
             "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
             "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+            "bootable": True,
         },
         {
             "name": "part2",
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v4 8/8] cmd: gpt: Add command to swap partition order
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                         ` (6 preceding siblings ...)
  2023-08-28 21:56       ` [PATCH v4 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
@ 2023-08-28 21:56       ` Joshua Watt
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  8 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-28 21:56 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt, Enric Balletbo i Serra

Adds a command called "gpt swap-postition" which will swap the order two
partition table entries in the GPT partition table (but leaves them
pointing to the same locations on disk).

This can be useful for swapping bootloaders in systems that use an A/B
partitioning scheme where the bootrom is hard coded to look for the
bootloader in a specific index in the GPT partition table.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 46 ++++++++++++++++++++++++++++++++++++---
 doc/usage/cmd/gpt.rst     | 25 +++++++++++++++++++++
 test/py/tests/test_gpt.py | 19 ++++++++++++++++
 3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 927b6afa68..c7d3f65ff2 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -858,8 +858,9 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	u8 part_count = 0;
 	int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
 
-	if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
-	    (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
+	if (!subcomm || !name1 || !name2 ||
+	    (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") &&
+	     strcmp(subcomm, "swap-position")))
 		return -EINVAL;
 
 	ret = get_disk_guid(dev_desc, disk_guid);
@@ -920,6 +921,41 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 			ret = -EINVAL;
 			goto out;
 		}
+	} else if (!strcmp(subcomm, "swap-position")) {
+		int idx1, idx2;
+		struct disk_partition* first = NULL;
+		struct disk_partition* second= NULL;
+		struct disk_partition tmp_part;
+
+		idx1 = simple_strtoul(name1, NULL, 10);
+		idx2 = simple_strtoul(name2, NULL, 10);
+		if (idx1 == idx2) {
+			printf("Cannot swap partition with itself\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (curr->partnum == idx1)
+				first = &curr->gpt_part_info;
+			else if (curr->partnum == idx2)
+				second = &curr->gpt_part_info;
+		}
+		if (!first) {
+			printf("Illegal partition number %s\n", name1);
+			ret = -EINVAL;
+			goto out;
+		}
+		if (!second) {
+			printf("Illegal partition number %s\n", name2);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		tmp_part = *first;
+		*first = *second;
+		*second = tmp_part;
 	} else { /* rename */
 		if (strlen(name2) > PART_NAME_LEN) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
@@ -1123,7 +1159,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if (strcmp(argv[1], "read") == 0) {
 		ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
 	} else if ((strcmp(argv[1], "swap") == 0) ||
-		   (strcmp(argv[1], "rename") == 0)) {
+		   (strcmp(argv[1], "rename") == 0) ||
+		   (strcmp(argv[1], "swap-position") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
 	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
 		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
@@ -1176,6 +1213,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap <interface> <dev> <name1> <name2>\n"
 	"    - change all partitions named name1 to name2\n"
 	"      and vice-versa\n"
+	" gpt swap-position <interface> <dev> <part1> <part2>\n"
+	"    - Swap the order of the entries for part1 and part2 in the partition table\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
 	" gpt set-bootable <interface> <dev> <list>\n"
@@ -1184,5 +1223,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
 	" gpt set-bootable mmc 0 boot_a,boot_b\n"
+	" gpt swap-position mmc 0 1 2\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index 288dd365c0..b2aaf4a701 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -16,6 +16,7 @@ Synopsis
     gpt set-bootable <interface> <dev> <partition list>
     gpt setenv <interface> <dev> <partition name>
     gpt swap <interface> <dev> <name1> <name2>
+    gpt swap-position <interface> <dev> <part1> <part2>
     gpt verify <interface> <dev> [<partition string>]
     gpt write <interface> <dev> <partition string>
 
@@ -126,6 +127,13 @@ Changes the names of all partitions that are named 'name1' to be 'name2', and
 all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
 required.
 
+gpt swap-position
+~~~~~~~~~~~~~~~~~
+
+Swaps the order of two partition table entries with indexes 'part1' and 'part2'
+in the partition table, but otherwise leaves the actual partition data
+untouched.
+
 gpt verify
 ~~~~~~~~~~
 
@@ -199,3 +207,20 @@ Get the GUID for a disk::
 Set the bootable flag for the 'boot' partition and clear it for all others::
 
     => gpt set-bootable mmc 0 boot
+
+Swap the order of the 'boot' and 'rootfs' partition table entries::
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    2
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    1
+
+    => gpt swap-position mmc 0 1 2
+
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    1
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    2
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index b4c03bc3a2..5a106c038c 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -329,3 +329,22 @@ def test_gpt_write(state_disk_image, u_boot_console):
     assert '0x00001000	0x00001bff	"second"' in output
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
+
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_swap_position(state_disk_image, u_boot_console):
+    """Test the gpt swap-position command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('part list host 0')
+    assert '1\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '2\t0x00001000\t0x00001bff\t"part2"' in output
+
+    output = u_boot_console.run_command('gpt swap-position host 0 1 2')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('part list host 0')
+    assert '2\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '1\t0x00001000\t0x00001bff\t"part2"' in output
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH v4 1/8] cmd: gpt: Remove confusing help text
  2023-08-28 21:56       ` [PATCH v4 1/8] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-28 22:05         ` Heinrich Schuchardt
  0 siblings, 0 replies; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-28 22:05 UTC (permalink / raw)
  To: Joshua Watt, u-boot; +Cc: Simon Glass

On 8/28/23 23:56, Joshua Watt wrote:
> This help text appears to be a fragment of the text shown when
> CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

> ---
>   cmd/gpt.c | 2 --
>   1 file changed, 2 deletions(-)
>
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index 964056bd28..fe9e06681c 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -1060,8 +1060,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
>   	"      gpt_partition_name, gpt_partition_entry\n"
>   	" gpt enumerate mmc 0\n"
>   	"    - store list of partitions to gpt_partition_list environment variable\n"
> -	" read <interface> <dev>\n"
> -	"    - read GPT into a data structure for manipulation\n"
>   	" gpt guid <interface> <dev>\n"
>   	"    - print disk GUID\n"
>   	" gpt guid <interface> <dev> <varname>\n"


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v4 2/8] doc: Add gpt command documentation
  2023-08-28 21:56       ` [PATCH v4 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-28 22:45         ` Heinrich Schuchardt
  2023-08-28 22:59           ` Heinrich Schuchardt
  0 siblings, 1 reply; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-28 22:45 UTC (permalink / raw)
  To: Joshua Watt; +Cc: Simon Glass, u-boot

/On 8/28/23 23:56, Joshua Watt wrote:
> Adds initial documentation for the gpt command
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>   doc/usage/cmd/gpt.rst | 184 ++++++++++++++++++++++++++++++++++++++++++
>   doc/usage/index.rst   |   1 +
>   2 files changed, 185 insertions(+)
>   create mode 100644 doc/usage/cmd/gpt.rst
>
> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> new file mode 100644
> index 0000000000..6387c8116f
> --- /dev/null
> +++ b/doc/usage/cmd/gpt.rst
> @@ -0,0 +1,184 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +gpt command
> +===========
> +
> +Synopsis
> +--------
> +
> +::
> +
> +    gpt enumerate <interface> <dev>
> +    gpt guid <interface> <dev> [<varname>]
> +    gpt read <interface> <dev> [<varname>]
> +    gpt rename <interface> <dev> <part> <name>
> +    gpt repair <interface> <dev>
> +    gpt setenv <interface> <dev> <partition name>
> +    gpt swap <interface> <dev> <name1> <name2>
> +    gpt verify <interface> <dev> [<partition string>]
> +    gpt write <interface> <dev> <partition string>
> +
> +Description
> +-----------
> +
> +The gpt command lets users read, create, modify, or verify the GPT (GUID
> +Partition Table) partition layout.
> +
> +Common arguments:
> +
> +interface
> +    interface for accessing the block device (mmc, sata, scsi, usb, ....)
> +
> +dev
> +    device number
> +
> +partition string
> +    Describes the GPT partition layout for a disk.  The syntax is similar to
> +    the one used by the :doc:`mbr command <mbr>` command. The string contains
> +    one or more partition descriptors, each separated by a ";". Each descriptor
> +    contains one or more fields, with each field separated by a ",". Fields are
> +    either of the form "key=value" to set a specific value, or simple "flag" to
> +    set a boolean flag
> +
> +    The first descriptor can optionally be used to describe parameters for the
> +    whole disk with the following fields:
> +
> +    * uuid_disk=UUID - Set the UUID for the disk
> +
> +    Partition descriptors can have the following fields:
> +
> +    * name=<NAME> - The partition name, required
> +    * start=<BYTES> - The partition start offset in bytes, required

The code has this comment: "start address is optional".

> +    * size=<BYTES> - The partition size in bytes or "-" to expand it to the whole free area

This filed is mandatory.

> +    * bootable - Set the legacy bootable flag

This field is optional

> +    * uuid=<UUID> - The partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
> +    * type=<UUID> - The partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y

This field is optional

Thanks for all the updates. Looks much neater now.

The sequence expected in set_gpt_info() is:

uuid (optional if CONFIG_RANDOM_UUID=y),
type (optional, only usable for CONFIG_PARTITION_TYPE_GUID=y),
name (mandatory),
size (mandatory),
start (optional),
bootable (optional).

 From the description above it is not clear that:

* semicolons are used to separate partitions
* the exact sequence of fields must be kept
* commas are used to separate fields
* no extra white-space is allowed.

> +
> +
> +    If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
> +    will be generated for the partition
> +
> +gpt enumerate
> +~~~~~~~~~~~~~
> +
> +Sets the variable 'gpt_partition_list' to be a list of all the partition names
> +on the device.
> +
> +gpt guid
> +~~~~~~~~
> +
> +Report the GUID of a disk. If 'varname' is specified, the command will set the
> +variable to the GUID, otherwise it will be printed out.
> +
> +gpt read
> +~~~~~~~~
> +
> +Prints the current state of the GPT partition table. If 'varname' is specified,
> +the variable will be filled with a partition string in the same format as a
> +'<partition string>', suitable for passing to other 'gpt' commands.  If the
> +argument is omitted, a human readable description is printed out.
> +CONFIG_CMD_GPT_RENAME=y is required.
> +
> +gpt rename
> +~~~~~~~~~~
> +
> +Renames all partitions named 'part' to be 'name'. CONFIG_CMD_GPT_RENAME=y is
> +required.
> +
> +gpt repair
> +~~~~~~~~~~
> +
> +Repairs the GPT partition tables if it they become corrupted.
> +
> +gpt setenv
> +~~~~~~~~~~
> +
> +The 'gpt setenv' command will set a series of environment variables with
> +information about the partition named '<partition name>'. The variables are:
> +
> +gpt_partition_addr
> +    the starting offset of the partition in blocks as a hexadecimal number
> +
> +gpt_partition_size
> +    the size of the partition in blocks as a hexadecimal number
> +
> +gpt_partition_name
> +    the name of the partition
> +
> +gpt_partition_entry
> +    the partition number in the table, e.g. 1, 2, 3, etc.

Since eeef58401520 ("cmd: let gpt_partition_entry be hexadecimal") this
is a hexadecimal number. As partitions are not required to be numbered
start at 1:

%s/, e.g. 1, 2, 3, etc./as a hexadecimal number/

> +
> +gpt swap
> +~~~~~~~~
> +
> +Changes the names of all partitions that are named 'name1' to be 'name2', and
> +all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
> +required.
> +
> +gpt verify
> +~~~~~~~~~~
> +
> +Sets return value $? to 0 (true) if the partition layout on the
> +specified disk matches the one in the provided partition string, and 1 (false)
> +if it does not match. If no partition string is specified, the command will
> +check if the disk is partitioned or not.
> +
> +gpt write
> +~~~~~~~~~
> +
> +(Re)writes the partition table on the disk to match the provided
> +partition string. It returns 0 on success or 1 on failure.
> +
> +Configuration
> +-------------

All other man-pages have Configuration after Examples.

> +
> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
> +read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
> +
> +Examples
> +~~~~~~~~

An example for gpt read would be nice.

> +Create 6 partitions on a disk:: > +
> +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
> +        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
> +        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
> +    => gpt write mmc 0 $gpt_parts

There is a starting single quotation mark, but I don't see an ending
single quotation mark.

White-space is not allowed before 'name='. As ugly as it is, please, put
the whole setenv command into a single line.

You cannot use a comma before name=. It must be a semicolon.

Looking at the code the sequence in the partition descriptors seems to
be wrong. It should be

uuid (optional if CONFIG_RANDOM_UUID=y),
type (optional, only usable for CONFIG_PARTITION_TYPE_GUID=y),
name (mandatory),
size (mandatory),
start (optional),
bootable (optional).
.
Please, use a command that you have actually tested and copy it
verbatim. sandbox_defconfig has a host bind command to attach a file as
drive. That makes testing easy.

> +
> +
> +Verify that the device matches the partition layout described in the variable
> +$gpt_parts::
> +
> +    => gpt verify mmc 0 $gpt_parts

How about adding output here:

=> gpt verify mmc 0 $gpt_parts; echo $?
0

Best regards

Heinrich

> +
> +
> +Get the information about the partition named 'rootfs'::
> +
> +    => gpt setenv mmc 0 rootfs
> +    => echo ${gpt_partition_addr}
> +    2000
> +    => echo ${gpt_partition_size}
> +    14a000
> +    => echo ${gpt_partition_name}
> +    rootfs
> +    => echo ${gpt_partition_entry}
> +    2
> +
> +Get the list of partition names on the disk::
> +
> +    => gpt enumerate
> +    => echo gpt_partition_list
> +    boot rootfs system-data [ext] user modules ramdisk
> +
> +
> +Get the GUID for a disk::
> +
> +    => gpt guid mmc 0
> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> +    => gpt guid mmc gpt_disk_uuid
> +    => echo ${gpt_disk_uuid}
> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> index f45a7f5502..fa702920fa 100644
> --- a/doc/usage/index.rst
> +++ b/doc/usage/index.rst
> @@ -66,6 +66,7 @@ Shell commands
>      cmd/for
>      cmd/fwu_mdata
>      cmd/gpio
> +   cmd/gpt
>      cmd/host
>      cmd/imxtract
>      cmd/load


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-28 21:56       ` [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-28 22:54         ` Heinrich Schuchardt
  2023-08-29 13:24           ` Joshua Watt
  0 siblings, 1 reply; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-28 22:54 UTC (permalink / raw)
  To: Joshua Watt
  Cc: Heinrich Schuchardt, Simon Glass, Enric Balletbo i Serra, u-boot

On 8/28/23 23:56, Joshua Watt wrote:
> Adds a command that can be used to modify the GPT partition table to
> indicate which partitions should have the bootable flag set
>
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> ---
>   cmd/gpt.c                 | 80 +++++++++++++++++++++++++++++++++++++++
>   doc/usage/cmd/gpt.rst     | 12 ++++++
>   test/py/tests/test_gpt.py | 22 +++++++++++
>   3 files changed, 114 insertions(+)
>
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index c6c8282ac9..45fbe07404 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -972,6 +972,81 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
>   	free(partitions_list);
>   	return ret;
>   }
> +
> +/**
> + * gpt_set_bootable() - Set bootable flags for partitions
> + *
> + * Sets the bootable flag for any partition names in the comma separated list of
> + * partition names. Any partitions not in the list have their bootable flag
> + * cleared
> + *
> + * @desc: block device descriptor
> + * @name: Comma separated list of partition names
> + *
> + * @Return: '0' on success and -ve error on failure
> + */
> +static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const part_list)
> +{
> +	char *name;
> +	char disk_guid[UUID_STR_LEN + 1];
> +	struct list_head *pos;
> +	struct disk_part *curr;
> +	struct disk_partition *partitions = NULL;
> +	int part_count = 0;
> +	int ret = get_disk_guid(blk_dev_desc, disk_guid);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = get_gpt_info(blk_dev_desc);
> +	if (ret <= 0)
> +		goto out;
> +
> +	part_count = ret;
> +	partitions = malloc(sizeof(*partitions) * part_count);
> +	if (!partitions) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	/* Copy partitions and clear bootable flag */
> +	part_count = 0;
> +	list_for_each(pos, &disk_partitions) {
> +		curr = list_entry(pos, struct disk_part, list);
> +		partitions[part_count] = curr->gpt_part_info;
> +		partitions[part_count].bootable &= ~PART_BOOTABLE;
> +		part_count++;
> +	}
> +
> +	name = strtok(part_list, ",");
> +	while (name) {
> +		bool found = false;
> +
> +		for (int i = 0; i < part_count; i++) {
> +			if (strcmp((char *)partitions[i].name, name) == 0) {
> +				partitions[i].bootable |= PART_BOOTABLE;
> +				found = true;
> +			}
> +		}
> +
> +		if (!found) {
> +			printf("Warning: No partition matching '%s' found\n",
> +			       name);
> +		}
> +
> +		name = strtok(NULL, ",");
> +	}
> +
> +	ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
> +
> +out:
> +	del_gpt_info();
> +
> +	if (partitions)
> +		free(partitions);
> +
> +	return ret;
> +}
>   #endif
>
>   /**
> @@ -1031,6 +1106,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>   	} else if ((strcmp(argv[1], "swap") == 0) ||
>   		   (strcmp(argv[1], "rename") == 0)) {
>   		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
> +	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
> +		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
>   #endif
>   	} else {
>   		return CMD_RET_USAGE;
> @@ -1082,8 +1159,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
>   	"      and vice-versa\n"
>   	" gpt rename <interface> <dev> <part> <name>\n"
>   	"    - rename the specified partition\n"
> +	" gpt set-bootable <interface> <dev> <list>\n"
> +	"    - make partition names in list bootable\n"
>   	" Example usage:\n"
>   	" gpt swap mmc 0 foo bar\n"
>   	" gpt rename mmc 0 3 foo\n"
> +	" gpt set-bootable mmc 0 boot_a,boot_b\n"
>   #endif
>   );
> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> index b505b159d0..288dd365c0 100644
> --- a/doc/usage/cmd/gpt.rst
> +++ b/doc/usage/cmd/gpt.rst
> @@ -13,6 +13,7 @@ Synopsis
>       gpt read <interface> <dev> [<varname>]
>       gpt rename <interface> <dev> <part> <name>
>       gpt repair <interface> <dev>
> +    gpt set-bootable <interface> <dev> <partition list>
>       gpt setenv <interface> <dev> <partition name>
>       gpt swap <interface> <dev> <name1> <name2>
>       gpt verify <interface> <dev> [<partition string>]
> @@ -90,6 +91,13 @@ gpt repair
>
>   Repairs the GPT partition tables if it they become corrupted.
>
> +gpt set-bootable
> +~~~~~~~~~~~~~~~~
> +
> +Sets the bootable flag for all partitions in the table. If the partition name
> +is in 'partition list' (separated by ','), the bootable flag is set, otherwise
> +it is cleared. CONFIG_CMD_GPT_RENAME=y is required.

Why should this feature be related to CONFIG_CMD_GPT_RENAME?

Why do we need this sub-command? You can use gpt read and gpt write for
this rarely needed manipulation.

Best regards

Heinrich

> +
>   gpt setenv
>   ~~~~~~~~~~
>
> @@ -187,3 +195,7 @@ Get the GUID for a disk::
>       => gpt guid mmc gpt_disk_uuid
>       => echo ${gpt_disk_uuid}
>       bec9fc2a-86c1-483d-8a0e-0109732277d7
> +
> +Set the bootable flag for the 'boot' partition and clear it for all others::
> +
> +    => gpt set-bootable mmc 0 boot
> diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
> index 946858800d..5d23f9b292 100644
> --- a/test/py/tests/test_gpt.py
> +++ b/test/py/tests/test_gpt.py
> @@ -222,6 +222,28 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
>       assert '0x00000800	0x00000fff	"part2"' in output
>       assert '0x00001000	0x00001bff	"part1"' in output
>
> +@pytest.mark.buildconfigspec('cmd_gpt')
> +@pytest.mark.buildconfigspec('cmd_gpt_rename')
> +@pytest.mark.buildconfigspec('cmd_part')
> +@pytest.mark.requiredtool('sgdisk')
> +def test_gpt_set_bootable(state_disk_image, u_boot_console):
> +    """Test the gpt set-bootable command."""
> +
> +    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
> +    parts = ('part2', 'part1')
> +    for bootable in parts:
> +        output = u_boot_console.run_command(f'gpt set-bootable host 0 {bootable}')
> +        assert 'success!' in output
> +
> +        for p in parts:
> +            output = u_boot_console.run_command(f'gpt setenv host 0 {p}')
> +            assert 'success!' in output
> +            output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
> +            if p == bootable:
> +                assert output.rstrip() == '1'
> +            else:
> +                assert output.rstrip() == '0'
> +
>   @pytest.mark.boardspec('sandbox')
>   @pytest.mark.buildconfigspec('cmd_gpt')
>   @pytest.mark.buildconfigspec('cmd_part')


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v4 2/8] doc: Add gpt command documentation
  2023-08-28 22:45         ` Heinrich Schuchardt
@ 2023-08-28 22:59           ` Heinrich Schuchardt
  2023-08-29 13:22             ` Joshua Watt
  0 siblings, 1 reply; 74+ messages in thread
From: Heinrich Schuchardt @ 2023-08-28 22:59 UTC (permalink / raw)
  To: Joshua Watt; +Cc: Simon Glass, u-boot

On 8/29/23 00:45, Heinrich Schuchardt wrote:
> /On 8/28/23 23:56, Joshua Watt wrote:
>> Adds initial documentation for the gpt command
>>
>> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
>> ---
>>   doc/usage/cmd/gpt.rst | 184 ++++++++++++++++++++++++++++++++++++++++++
>>   doc/usage/index.rst   |   1 +
>>   2 files changed, 185 insertions(+)
>>   create mode 100644 doc/usage/cmd/gpt.rst
>>
>> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
>> new file mode 100644
>> index 0000000000..6387c8116f
>> --- /dev/null
>> +++ b/doc/usage/cmd/gpt.rst
>> @@ -0,0 +1,184 @@
>> +.. SPDX-License-Identifier: GPL-2.0+
>> +
>> +gpt command
>> +===========
>> +
>> +Synopsis
>> +--------
>> +
>> +::
>> +
>> +    gpt enumerate <interface> <dev>
>> +    gpt guid <interface> <dev> [<varname>]
>> +    gpt read <interface> <dev> [<varname>]
>> +    gpt rename <interface> <dev> <part> <name>
>> +    gpt repair <interface> <dev>
>> +    gpt setenv <interface> <dev> <partition name>
>> +    gpt swap <interface> <dev> <name1> <name2>
>> +    gpt verify <interface> <dev> [<partition string>]
>> +    gpt write <interface> <dev> <partition string>
>> +
>> +Description
>> +-----------
>> +
>> +The gpt command lets users read, create, modify, or verify the GPT (GUID
>> +Partition Table) partition layout.
>> +
>> +Common arguments:
>> +
>> +interface
>> +    interface for accessing the block device (mmc, sata, scsi, usb,
>> ....)
>> +
>> +dev
>> +    device number
>> +
>> +partition string
>> +    Describes the GPT partition layout for a disk.  The syntax is
>> similar to
>> +    the one used by the :doc:`mbr command <mbr>` command. The string
>> contains
>> +    one or more partition descriptors, each separated by a ";". Each
>> descriptor
>> +    contains one or more fields, with each field separated by a ",".
>> Fields are
>> +    either of the form "key=value" to set a specific value, or simple
>> "flag" to
>> +    set a boolean flag
>> +
>> +    The first descriptor can optionally be used to describe
>> parameters for the
>> +    whole disk with the following fields:
>> +
>> +    * uuid_disk=UUID - Set the UUID for the disk
>> +
>> +    Partition descriptors can have the following fields:
>> +
>> +    * name=<NAME> - The partition name, required
>> +    * start=<BYTES> - The partition start offset in bytes, required
>
> The code has this comment: "start address is optional".
>
>> +    * size=<BYTES> - The partition size in bytes or "-" to expand it
>> to the whole free area
>
> This filed is mandatory.
>
>> +    * bootable - Set the legacy bootable flag
>
> This field is optional
>
>> +    * uuid=<UUID> - The partition UUID, optional if
>> CONFIG_RANDOM_UUID=y is enabled
>> +    * type=<UUID> - The partition type GUID, requires
>> CONFIG_PARTITION_TYPE_GUID=y
>
> This field is optional
>
> Thanks for all the updates. Looks much neater now.
>
> The sequence expected in set_gpt_info() is:
>
> uuid (optional if CONFIG_RANDOM_UUID=y),
> type (optional, only usable for CONFIG_PARTITION_TYPE_GUID=y),
> name (mandatory),
> size (mandatory),
> start (optional),
> bootable (optional).

A gross bug in the gpt command is that 'gpt read' creates a different
sequence than 'gpt write' needs.

Furthermore 'gpt read' does not write all fields needed by 'gpt write'
to recreate the partition table: bootable and type are missing.

Best regards

Heinrich

>
>  From the description above it is not clear that:
>
> * semicolons are used to separate partitions
> * the exact sequence of fields must be kept
> * commas are used to separate fields
> * no extra white-space is allowed.
>
>> +
>> +
>> +    If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a
>> random UUID
>> +    will be generated for the partition
>> +
>> +gpt enumerate
>> +~~~~~~~~~~~~~
>> +
>> +Sets the variable 'gpt_partition_list' to be a list of all the
>> partition names
>> +on the device.
>> +
>> +gpt guid
>> +~~~~~~~~
>> +
>> +Report the GUID of a disk. If 'varname' is specified, the command
>> will set the
>> +variable to the GUID, otherwise it will be printed out.
>> +
>> +gpt read
>> +~~~~~~~~
>> +
>> +Prints the current state of the GPT partition table. If 'varname' is
>> specified,
>> +the variable will be filled with a partition string in the same
>> format as a
>> +'<partition string>', suitable for passing to other 'gpt' commands.
>> If the
>> +argument is omitted, a human readable description is printed out.
>> +CONFIG_CMD_GPT_RENAME=y is required.
>> +
>> +gpt rename
>> +~~~~~~~~~~
>> +
>> +Renames all partitions named 'part' to be 'name'.
>> CONFIG_CMD_GPT_RENAME=y is
>> +required.
>> +
>> +gpt repair
>> +~~~~~~~~~~
>> +
>> +Repairs the GPT partition tables if it they become corrupted.
>> +
>> +gpt setenv
>> +~~~~~~~~~~
>> +
>> +The 'gpt setenv' command will set a series of environment variables with
>> +information about the partition named '<partition name>'. The
>> variables are:
>> +
>> +gpt_partition_addr
>> +    the starting offset of the partition in blocks as a hexadecimal
>> number
>> +
>> +gpt_partition_size
>> +    the size of the partition in blocks as a hexadecimal number
>> +
>> +gpt_partition_name
>> +    the name of the partition
>> +
>> +gpt_partition_entry
>> +    the partition number in the table, e.g. 1, 2, 3, etc.
>
> Since eeef58401520 ("cmd: let gpt_partition_entry be hexadecimal") this
> is a hexadecimal number. As partitions are not required to be numbered
> start at 1:
>
> %s/, e.g. 1, 2, 3, etc./as a hexadecimal number/
>
>> +
>> +gpt swap
>> +~~~~~~~~
>> +
>> +Changes the names of all partitions that are named 'name1' to be
>> 'name2', and
>> +all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
>> +required.
>> +
>> +gpt verify
>> +~~~~~~~~~~
>> +
>> +Sets return value $? to 0 (true) if the partition layout on the
>> +specified disk matches the one in the provided partition string, and
>> 1 (false)
>> +if it does not match. If no partition string is specified, the
>> command will
>> +check if the disk is partitioned or not.
>> +
>> +gpt write
>> +~~~~~~~~~
>> +
>> +(Re)writes the partition table on the disk to match the provided
>> +partition string. It returns 0 on success or 1 on failure.
>> +
>> +Configuration
>> +-------------
>
> All other man-pages have Configuration after Examples.
>
>> +
>> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable
>> 'gpt
>> +read', 'gpt swap' and 'gpt rename', you must specify
>> CONFIG_CMD_GPT_RENAME=y.
>> +
>> +Examples
>> +~~~~~~~~
>
> An example for gpt read would be nice.
>
>> +Create 6 partitions on a disk:: > +
>> +    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
>> +
>> name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
>> +
>> name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>> +
>> name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>> +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>> +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>> +
>> name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
>> +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
>> +    => gpt write mmc 0 $gpt_parts
>
> There is a starting single quotation mark, but I don't see an ending
> single quotation mark.
>
> White-space is not allowed before 'name='. As ugly as it is, please, put
> the whole setenv command into a single line.
>
> You cannot use a comma before name=. It must be a semicolon.
>
> Looking at the code the sequence in the partition descriptors seems to
> be wrong. It should be
>
> uuid (optional if CONFIG_RANDOM_UUID=y),
> type (optional, only usable for CONFIG_PARTITION_TYPE_GUID=y),
> name (mandatory),
> size (mandatory),
> start (optional),
> bootable (optional).
> .
> Please, use a command that you have actually tested and copy it
> verbatim. sandbox_defconfig has a host bind command to attach a file as
> drive. That makes testing easy.
>
>> +
>> +
>> +Verify that the device matches the partition layout described in the
>> variable
>> +$gpt_parts::
>> +
>> +    => gpt verify mmc 0 $gpt_parts
>
> How about adding output here:
>
> => gpt verify mmc 0 $gpt_parts; echo $?
> 0
>
> Best regards
>
> Heinrich
>
>> +
>> +
>> +Get the information about the partition named 'rootfs'::
>> +
>> +    => gpt setenv mmc 0 rootfs
>> +    => echo ${gpt_partition_addr}
>> +    2000
>> +    => echo ${gpt_partition_size}
>> +    14a000
>> +    => echo ${gpt_partition_name}
>> +    rootfs
>> +    => echo ${gpt_partition_entry}
>> +    2
>> +
>> +Get the list of partition names on the disk::
>> +
>> +    => gpt enumerate
>> +    => echo gpt_partition_list
>> +    boot rootfs system-data [ext] user modules ramdisk
>> +
>> +
>> +Get the GUID for a disk::
>> +
>> +    => gpt guid mmc 0
>> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
>> +    => gpt guid mmc gpt_disk_uuid
>> +    => echo ${gpt_disk_uuid}
>> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
>> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
>> index f45a7f5502..fa702920fa 100644
>> --- a/doc/usage/index.rst
>> +++ b/doc/usage/index.rst
>> @@ -66,6 +66,7 @@ Shell commands
>>      cmd/for
>>      cmd/fwu_mdata
>>      cmd/gpio
>> +   cmd/gpt
>>      cmd/host
>>      cmd/imxtract
>>      cmd/load
>


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v4 2/8] doc: Add gpt command documentation
  2023-08-28 22:59           ` Heinrich Schuchardt
@ 2023-08-29 13:22             ` Joshua Watt
  0 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-29 13:22 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: Simon Glass, U-Boot Mailing List

On Mon, Aug 28, 2023, 4:58 PM Heinrich Schuchardt <xypron.glpk@gmx.de>
wrote:

> On 8/29/23 00:45, Heinrich Schuchardt wrote:
> > /On 8/28/23 23:56, Joshua Watt wrote:
> >> Adds initial documentation for the gpt command
> >>
> >> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> >> ---
> >>   doc/usage/cmd/gpt.rst | 184 ++++++++++++++++++++++++++++++++++++++++++
> >>   doc/usage/index.rst   |   1 +
> >>   2 files changed, 185 insertions(+)
> >>   create mode 100644 doc/usage/cmd/gpt.rst
> >>
> >> diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> >> new file mode 100644
> >> index 0000000000..6387c8116f
> >> --- /dev/null
> >> +++ b/doc/usage/cmd/gpt.rst
> >> @@ -0,0 +1,184 @@
> >> +.. SPDX-License-Identifier: GPL-2.0+
> >> +
> >> +gpt command
> >> +===========
> >> +
> >> +Synopsis
> >> +--------
> >> +
> >> +::
> >> +
> >> +    gpt enumerate <interface> <dev>
> >> +    gpt guid <interface> <dev> [<varname>]
> >> +    gpt read <interface> <dev> [<varname>]
> >> +    gpt rename <interface> <dev> <part> <name>
> >> +    gpt repair <interface> <dev>
> >> +    gpt setenv <interface> <dev> <partition name>
> >> +    gpt swap <interface> <dev> <name1> <name2>
> >> +    gpt verify <interface> <dev> [<partition string>]
> >> +    gpt write <interface> <dev> <partition string>
> >> +
> >> +Description
> >> +-----------
> >> +
> >> +The gpt command lets users read, create, modify, or verify the GPT
> (GUID
> >> +Partition Table) partition layout.
> >> +
> >> +Common arguments:
> >> +
> >> +interface
> >> +    interface for accessing the block device (mmc, sata, scsi, usb,
> >> ....)
> >> +
> >> +dev
> >> +    device number
> >> +
> >> +partition string
> >> +    Describes the GPT partition layout for a disk.  The syntax is
> >> similar to
> >> +    the one used by the :doc:`mbr command <mbr>` command. The string
> >> contains
> >> +    one or more partition descriptors, each separated by a ";". Each
> >> descriptor
> >> +    contains one or more fields, with each field separated by a ",".
> >> Fields are
> >> +    either of the form "key=value" to set a specific value, or simple
> >> "flag" to
> >> +    set a boolean flag
> >> +
> >> +    The first descriptor can optionally be used to describe
> >> parameters for the
> >> +    whole disk with the following fields:
> >> +
> >> +    * uuid_disk=UUID - Set the UUID for the disk
> >> +
> >> +    Partition descriptors can have the following fields:
> >> +
> >> +    * name=<NAME> - The partition name, required
> >> +    * start=<BYTES> - The partition start offset in bytes, required
> >
> > The code has this comment: "start address is optional".
> >
> >> +    * size=<BYTES> - The partition size in bytes or "-" to expand it
> >> to the whole free area
> >
> > This filed is mandatory.
> >
> >> +    * bootable - Set the legacy bootable flag
> >
> > This field is optional
> >
> >> +    * uuid=<UUID> - The partition UUID, optional if
> >> CONFIG_RANDOM_UUID=y is enabled
> >> +    * type=<UUID> - The partition type GUID, requires
> >> CONFIG_PARTITION_TYPE_GUID=y
> >
> > This field is optional
> >
> > Thanks for all the updates. Looks much neater now.
> >
> > The sequence expected in set_gpt_info() is:
> >
> > uuid (optional if CONFIG_RANDOM_UUID=y),
> > type (optional, only usable for CONFIG_PARTITION_TYPE_GUID=y),
> > name (mandatory),
> > size (mandatory),
> > start (optional),
> > bootable (optional).
>
> A gross bug in the gpt command is that 'gpt read' creates a different
> sequence than 'gpt write' needs.
>
> Furthermore 'gpt read' does not write all fields needed by 'gpt write'
> to recreate the partition table: bootable and type are missing.
>

This is fixed in later patches in this series


> Best regards
>
> Heinrich
>
> >
> >  From the description above it is not clear that:
> >
> > * semicolons are used to separate partitions
> > * the exact sequence of fields must be kept
> > * commas are used to separate fields
> > * no extra white-space is allowed.
> >
> >> +
> >> +
> >> +    If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a
> >> random UUID
> >> +    will be generated for the partition
> >> +
> >> +gpt enumerate
> >> +~~~~~~~~~~~~~
> >> +
> >> +Sets the variable 'gpt_partition_list' to be a list of all the
> >> partition names
> >> +on the device.
> >> +
> >> +gpt guid
> >> +~~~~~~~~
> >> +
> >> +Report the GUID of a disk. If 'varname' is specified, the command
> >> will set the
> >> +variable to the GUID, otherwise it will be printed out.
> >> +
> >> +gpt read
> >> +~~~~~~~~
> >> +
> >> +Prints the current state of the GPT partition table. If 'varname' is
> >> specified,
> >> +the variable will be filled with a partition string in the same
> >> format as a
> >> +'<partition string>', suitable for passing to other 'gpt' commands.
> >> If the
> >> +argument is omitted, a human readable description is printed out.
> >> +CONFIG_CMD_GPT_RENAME=y is required.
> >> +
> >> +gpt rename
> >> +~~~~~~~~~~
> >> +
> >> +Renames all partitions named 'part' to be 'name'.
> >> CONFIG_CMD_GPT_RENAME=y is
> >> +required.
> >> +
> >> +gpt repair
> >> +~~~~~~~~~~
> >> +
> >> +Repairs the GPT partition tables if it they become corrupted.
> >> +
> >> +gpt setenv
> >> +~~~~~~~~~~
> >> +
> >> +The 'gpt setenv' command will set a series of environment variables
> with
> >> +information about the partition named '<partition name>'. The
> >> variables are:
> >> +
> >> +gpt_partition_addr
> >> +    the starting offset of the partition in blocks as a hexadecimal
> >> number
> >> +
> >> +gpt_partition_size
> >> +    the size of the partition in blocks as a hexadecimal number
> >> +
> >> +gpt_partition_name
> >> +    the name of the partition
> >> +
> >> +gpt_partition_entry
> >> +    the partition number in the table, e.g. 1, 2, 3, etc.
> >
> > Since eeef58401520 ("cmd: let gpt_partition_entry be hexadecimal") this
> > is a hexadecimal number. As partitions are not required to be numbered
> > start at 1:
> >
> > %s/, e.g. 1, 2, 3, etc./as a hexadecimal number/
> >
> >> +
> >> +gpt swap
> >> +~~~~~~~~
> >> +
> >> +Changes the names of all partitions that are named 'name1' to be
> >> 'name2', and
> >> +all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
> >> +required.
> >> +
> >> +gpt verify
> >> +~~~~~~~~~~
> >> +
> >> +Sets return value $? to 0 (true) if the partition layout on the
> >> +specified disk matches the one in the provided partition string, and
> >> 1 (false)
> >> +if it does not match. If no partition string is specified, the
> >> command will
> >> +check if the disk is partitioned or not.
> >> +
> >> +gpt write
> >> +~~~~~~~~~
> >> +
> >> +(Re)writes the partition table on the disk to match the provided
> >> +partition string. It returns 0 on success or 1 on failure.
> >> +
> >> +Configuration
> >> +-------------
> >
> > All other man-pages have Configuration after Examples.
> >
> >> +
> >> +To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable
> >> 'gpt
> >> +read', 'gpt swap' and 'gpt rename', you must specify
> >> CONFIG_CMD_GPT_RENAME=y.
> >> +
> >> +Examples
> >> +~~~~~~~~
> >
> > An example for gpt read would be nice.
> >
> >> +Create 6 partitions on a disk:: > +
> >> +    => setenv gpt_parts
> 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
> >> +
> >>
> name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
> >> +
> >> name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >> +
> >> name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >> +        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >> +        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >> +
> >> name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
> >> +        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
> >> +    => gpt write mmc 0 $gpt_parts
> >
> > There is a starting single quotation mark, but I don't see an ending
> > single quotation mark.
> >
> > White-space is not allowed before 'name='. As ugly as it is, please, put
> > the whole setenv command into a single line.
> >
> > You cannot use a comma before name=. It must be a semicolon.
> >
> > Looking at the code the sequence in the partition descriptors seems to
> > be wrong. It should be
> >
> > uuid (optional if CONFIG_RANDOM_UUID=y),
> > type (optional, only usable for CONFIG_PARTITION_TYPE_GUID=y),
> > name (mandatory),
> > size (mandatory),
> > start (optional),
> > bootable (optional).
> > .
> > Please, use a command that you have actually tested and copy it
> > verbatim. sandbox_defconfig has a host bind command to attach a file as
> > drive. That makes testing easy.
> >
> >> +
> >> +
> >> +Verify that the device matches the partition layout described in the
> >> variable
> >> +$gpt_parts::
> >> +
> >> +    => gpt verify mmc 0 $gpt_parts
> >
> > How about adding output here:
> >
> > => gpt verify mmc 0 $gpt_parts; echo $?
> > 0
> >
> > Best regards
> >
> > Heinrich
> >
> >> +
> >> +
> >> +Get the information about the partition named 'rootfs'::
> >> +
> >> +    => gpt setenv mmc 0 rootfs
> >> +    => echo ${gpt_partition_addr}
> >> +    2000
> >> +    => echo ${gpt_partition_size}
> >> +    14a000
> >> +    => echo ${gpt_partition_name}
> >> +    rootfs
> >> +    => echo ${gpt_partition_entry}
> >> +    2
> >> +
> >> +Get the list of partition names on the disk::
> >> +
> >> +    => gpt enumerate
> >> +    => echo gpt_partition_list
> >> +    boot rootfs system-data [ext] user modules ramdisk
> >> +
> >> +
> >> +Get the GUID for a disk::
> >> +
> >> +    => gpt guid mmc 0
> >> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> >> +    => gpt guid mmc gpt_disk_uuid
> >> +    => echo ${gpt_disk_uuid}
> >> +    bec9fc2a-86c1-483d-8a0e-0109732277d7
> >> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> >> index f45a7f5502..fa702920fa 100644
> >> --- a/doc/usage/index.rst
> >> +++ b/doc/usage/index.rst
> >> @@ -66,6 +66,7 @@ Shell commands
> >>      cmd/for
> >>      cmd/fwu_mdata
> >>      cmd/gpio
> >> +   cmd/gpt
> >>      cmd/host
> >>      cmd/imxtract
> >>      cmd/load
> >
>
>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-28 22:54         ` Heinrich Schuchardt
@ 2023-08-29 13:24           ` Joshua Watt
  0 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-29 13:24 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Simon Glass, Enric Balletbo i Serra, U-Boot Mailing List

On Mon, Aug 28, 2023, 4:53 PM Heinrich Schuchardt <xypron.glpk@gmx.de>
wrote:

> On 8/28/23 23:56, Joshua Watt wrote:
> > Adds a command that can be used to modify the GPT partition table to
> > indicate which partitions should have the bootable flag set
> >
> > Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
> > ---
> >   cmd/gpt.c                 | 80 +++++++++++++++++++++++++++++++++++++++
> >   doc/usage/cmd/gpt.rst     | 12 ++++++
> >   test/py/tests/test_gpt.py | 22 +++++++++++
> >   3 files changed, 114 insertions(+)
> >
> > diff --git a/cmd/gpt.c b/cmd/gpt.c
> > index c6c8282ac9..45fbe07404 100644
> > --- a/cmd/gpt.c
> > +++ b/cmd/gpt.c
> > @@ -972,6 +972,81 @@ static int do_rename_gpt_parts(struct blk_desc
> *dev_desc, char *subcomm,
> >       free(partitions_list);
> >       return ret;
> >   }
> > +
> > +/**
> > + * gpt_set_bootable() - Set bootable flags for partitions
> > + *
> > + * Sets the bootable flag for any partition names in the comma
> separated list of
> > + * partition names. Any partitions not in the list have their bootable
> flag
> > + * cleared
> > + *
> > + * @desc: block device descriptor
> > + * @name: Comma separated list of partition names
> > + *
> > + * @Return: '0' on success and -ve error on failure
> > + */
> > +static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const
> part_list)
> > +{
> > +     char *name;
> > +     char disk_guid[UUID_STR_LEN + 1];
> > +     struct list_head *pos;
> > +     struct disk_part *curr;
> > +     struct disk_partition *partitions = NULL;
> > +     int part_count = 0;
> > +     int ret = get_disk_guid(blk_dev_desc, disk_guid);
> > +
> > +     if (ret < 0)
> > +             return ret;
> > +
> > +     ret = get_gpt_info(blk_dev_desc);
> > +     if (ret <= 0)
> > +             goto out;
> > +
> > +     part_count = ret;
> > +     partitions = malloc(sizeof(*partitions) * part_count);
> > +     if (!partitions) {
> > +             ret = -ENOMEM;
> > +             goto out;
> > +     }
> > +
> > +     /* Copy partitions and clear bootable flag */
> > +     part_count = 0;
> > +     list_for_each(pos, &disk_partitions) {
> > +             curr = list_entry(pos, struct disk_part, list);
> > +             partitions[part_count] = curr->gpt_part_info;
> > +             partitions[part_count].bootable &= ~PART_BOOTABLE;
> > +             part_count++;
> > +     }
> > +
> > +     name = strtok(part_list, ",");
> > +     while (name) {
> > +             bool found = false;
> > +
> > +             for (int i = 0; i < part_count; i++) {
> > +                     if (strcmp((char *)partitions[i].name, name) == 0)
> {
> > +                             partitions[i].bootable |= PART_BOOTABLE;
> > +                             found = true;
> > +                     }
> > +             }
> > +
> > +             if (!found) {
> > +                     printf("Warning: No partition matching '%s'
> found\n",
> > +                            name);
> > +             }
> > +
> > +             name = strtok(NULL, ",");
> > +     }
> > +
> > +     ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
> > +
> > +out:
> > +     del_gpt_info();
> > +
> > +     if (partitions)
> > +             free(partitions);
> > +
> > +     return ret;
> > +}
> >   #endif
> >
> >   /**
> > @@ -1031,6 +1106,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag,
> int argc, char *const argv[])
> >       } else if ((strcmp(argv[1], "swap") == 0) ||
> >                  (strcmp(argv[1], "rename") == 0)) {
> >               ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4],
> argv[5]);
> > +     } else if ((strcmp(argv[1], "set-bootable") == 0)) {
> > +             ret = gpt_set_bootable(blk_dev_desc, argv[4]);
> >   #endif
> >       } else {
> >               return CMD_RET_USAGE;
> > @@ -1082,8 +1159,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
> >       "      and vice-versa\n"
> >       " gpt rename <interface> <dev> <part> <name>\n"
> >       "    - rename the specified partition\n"
> > +     " gpt set-bootable <interface> <dev> <list>\n"
> > +     "    - make partition names in list bootable\n"
> >       " Example usage:\n"
> >       " gpt swap mmc 0 foo bar\n"
> >       " gpt rename mmc 0 3 foo\n"
> > +     " gpt set-bootable mmc 0 boot_a,boot_b\n"
> >   #endif
> >   );
> > diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
> > index b505b159d0..288dd365c0 100644
> > --- a/doc/usage/cmd/gpt.rst
> > +++ b/doc/usage/cmd/gpt.rst
> > @@ -13,6 +13,7 @@ Synopsis
> >       gpt read <interface> <dev> [<varname>]
> >       gpt rename <interface> <dev> <part> <name>
> >       gpt repair <interface> <dev>
> > +    gpt set-bootable <interface> <dev> <partition list>
> >       gpt setenv <interface> <dev> <partition name>
> >       gpt swap <interface> <dev> <name1> <name2>
> >       gpt verify <interface> <dev> [<partition string>]
> > @@ -90,6 +91,13 @@ gpt repair
> >
> >   Repairs the GPT partition tables if it they become corrupted.
> >
> > +gpt set-bootable
> > +~~~~~~~~~~~~~~~~
> > +
> > +Sets the bootable flag for all partitions in the table. If the
> partition name
> > +is in 'partition list' (separated by ','), the bootable flag is set,
> otherwise
> > +it is cleared. CONFIG_CMD_GPT_RENAME=y is required.
>
> Why should this feature be related to CONFIG_CMD_GPT_RENAME?


Commands that write to the partition table seem to need this (probably
poorly named) config.


> Why do we need this sub-command? You can use gpt read and gpt write for
> this rarely needed manipulation.
>

Dealing with the string parsing in a script is cantankerous and annoying,
unless I'm missing something that magically makes it easy


> Best regards
>
> Heinrich
>
> > +
> >   gpt setenv
> >   ~~~~~~~~~~
> >
> > @@ -187,3 +195,7 @@ Get the GUID for a disk::
> >       => gpt guid mmc gpt_disk_uuid
> >       => echo ${gpt_disk_uuid}
> >       bec9fc2a-86c1-483d-8a0e-0109732277d7
> > +
> > +Set the bootable flag for the 'boot' partition and clear it for all
> others::
> > +
> > +    => gpt set-bootable mmc 0 boot
> > diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
> > index 946858800d..5d23f9b292 100644
> > --- a/test/py/tests/test_gpt.py
> > +++ b/test/py/tests/test_gpt.py
> > @@ -222,6 +222,28 @@ def test_gpt_swap_partitions(state_disk_image,
> u_boot_console):
> >       assert '0x00000800      0x00000fff      "part2"' in output
> >       assert '0x00001000      0x00001bff      "part1"' in output
> >
> > +@pytest.mark.buildconfigspec('cmd_gpt')
> > +@pytest.mark.buildconfigspec('cmd_gpt_rename')
> > +@pytest.mark.buildconfigspec('cmd_part')
> > +@pytest.mark.requiredtool('sgdisk')
> > +def test_gpt_set_bootable(state_disk_image, u_boot_console):
> > +    """Test the gpt set-bootable command."""
> > +
> > +    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
> > +    parts = ('part2', 'part1')
> > +    for bootable in parts:
> > +        output = u_boot_console.run_command(f'gpt set-bootable host 0
> {bootable}')
> > +        assert 'success!' in output
> > +
> > +        for p in parts:
> > +            output = u_boot_console.run_command(f'gpt setenv host 0
> {p}')
> > +            assert 'success!' in output
> > +            output = u_boot_console.run_command('echo
> ${gpt_partition_bootable}')
> > +            if p == bootable:
> > +                assert output.rstrip() == '1'
> > +            else:
> > +                assert output.rstrip() == '0'
> > +
> >   @pytest.mark.boardspec('sandbox')
> >   @pytest.mark.buildconfigspec('cmd_gpt')
> >   @pytest.mark.buildconfigspec('cmd_part')
>
>

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements
  2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                         ` (7 preceding siblings ...)
  2023-08-28 21:56       ` [PATCH v4 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
@ 2023-08-31 16:51       ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 1/8] cmd: gpt: Remove confusing help text Joshua Watt
                           ` (7 more replies)
  8 siblings, 8 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt

Adds several improvements and additions to the gpt command processing,
specifically (although not exclusively) for the purpose of supporting
"ping-pong" booting when doing A/B boot partitions with u-boot itself.

In this mechanism, u-boot must boot up, and then check if the correct
boot partition is active, and if not switch the GPT partition table to
the other boot partition and reboot to activate the other u-boot.

In order to facilitate this, the gpt command needs to be better at
preserving entry attributes when manipulating the partition table. It
also learns two new commands, one which can swap the order of partitions
in the table, and another that lets it change which partitions have the
bootable flag.

V2: Add documentation and tests
V3: Review Feedback
V4: More review feedback. Fixed 'gpt swap-position' to work with
    missing partition indexes.
V5: Rename 'gpt swap-position' -> 'gpt transpose', taking inspiration
    from `sgdisk --transpose`

Joshua Watt (8):
  cmd: gpt: Remove confusing help text
  doc: Add gpt command documentation
  tests: gpt: Remove test order dependency
  cmd: gpt: Add gpt_partition_bootable variable
  cmd: gpt: Add command to set bootable flags
  cmd: gpt: Preserve type GUID if enabled
  cmd: gpt: Preserve bootable flag
  cmd: gpt: Add command to swap partition order

 cmd/gpt.c                 | 156 ++++++++++++++++++++++++--
 doc/usage/cmd/gpt.rst     | 226 ++++++++++++++++++++++++++++++++++++++
 doc/usage/index.rst       |   1 +
 test/py/tests/test_gpt.py | 160 +++++++++++++++++++++++++--
 4 files changed, 524 insertions(+), 19 deletions(-)
 create mode 100644 doc/usage/cmd/gpt.rst

-- 
2.34.1


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH v5 1/8] cmd: gpt: Remove confusing help text
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 2/8] doc: Add gpt command documentation Joshua Watt
                           ` (6 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt

This help text appears to be a fragment of the text shown when
CONFIG_CMD_GPT_RENAME is enabled, but is confusing so remove it.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 964056bd28..fe9e06681c 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -1060,8 +1060,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      gpt_partition_name, gpt_partition_entry\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
-	" read <interface> <dev>\n"
-	"    - read GPT into a data structure for manipulation\n"
 	" gpt guid <interface> <dev>\n"
 	"    - print disk GUID\n"
 	" gpt guid <interface> <dev> <varname>\n"
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 2/8] doc: Add gpt command documentation
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 1/8] cmd: gpt: Remove confusing help text Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 3/8] tests: gpt: Remove test order dependency Joshua Watt
                           ` (5 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt

Adds initial documentation for the gpt command

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 doc/usage/cmd/gpt.rst | 184 ++++++++++++++++++++++++++++++++++++++++++
 doc/usage/index.rst   |   1 +
 2 files changed, 185 insertions(+)
 create mode 100644 doc/usage/cmd/gpt.rst

diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
new file mode 100644
index 0000000000..6387c8116f
--- /dev/null
+++ b/doc/usage/cmd/gpt.rst
@@ -0,0 +1,184 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+gpt command
+===========
+
+Synopsis
+--------
+
+::
+
+    gpt enumerate <interface> <dev>
+    gpt guid <interface> <dev> [<varname>]
+    gpt read <interface> <dev> [<varname>]
+    gpt rename <interface> <dev> <part> <name>
+    gpt repair <interface> <dev>
+    gpt setenv <interface> <dev> <partition name>
+    gpt swap <interface> <dev> <name1> <name2>
+    gpt verify <interface> <dev> [<partition string>]
+    gpt write <interface> <dev> <partition string>
+
+Description
+-----------
+
+The gpt command lets users read, create, modify, or verify the GPT (GUID
+Partition Table) partition layout.
+
+Common arguments:
+
+interface
+    interface for accessing the block device (mmc, sata, scsi, usb, ....)
+
+dev
+    device number
+
+partition string
+    Describes the GPT partition layout for a disk.  The syntax is similar to
+    the one used by the :doc:`mbr command <mbr>` command. The string contains
+    one or more partition descriptors, each separated by a ";". Each descriptor
+    contains one or more fields, with each field separated by a ",". Fields are
+    either of the form "key=value" to set a specific value, or simple "flag" to
+    set a boolean flag
+
+    The first descriptor can optionally be used to describe parameters for the
+    whole disk with the following fields:
+
+    * uuid_disk=UUID - Set the UUID for the disk
+
+    Partition descriptors can have the following fields:
+
+    * name=<NAME> - The partition name, required
+    * start=<BYTES> - The partition start offset in bytes, required
+    * size=<BYTES> - The partition size in bytes or "-" to expand it to the whole free area
+    * bootable - Set the legacy bootable flag
+    * uuid=<UUID> - The partition UUID, optional if CONFIG_RANDOM_UUID=y is enabled
+    * type=<UUID> - The partition type GUID, requires CONFIG_PARTITION_TYPE_GUID=y
+
+
+    If 'uuid' is not specified, but CONFIG_RANDOM_UUID is enabled, a random UUID
+    will be generated for the partition
+
+gpt enumerate
+~~~~~~~~~~~~~
+
+Sets the variable 'gpt_partition_list' to be a list of all the partition names
+on the device.
+
+gpt guid
+~~~~~~~~
+
+Report the GUID of a disk. If 'varname' is specified, the command will set the
+variable to the GUID, otherwise it will be printed out.
+
+gpt read
+~~~~~~~~
+
+Prints the current state of the GPT partition table. If 'varname' is specified,
+the variable will be filled with a partition string in the same format as a
+'<partition string>', suitable for passing to other 'gpt' commands.  If the
+argument is omitted, a human readable description is printed out.
+CONFIG_CMD_GPT_RENAME=y is required.
+
+gpt rename
+~~~~~~~~~~
+
+Renames all partitions named 'part' to be 'name'. CONFIG_CMD_GPT_RENAME=y is
+required.
+
+gpt repair
+~~~~~~~~~~
+
+Repairs the GPT partition tables if it they become corrupted.
+
+gpt setenv
+~~~~~~~~~~
+
+The 'gpt setenv' command will set a series of environment variables with
+information about the partition named '<partition name>'. The variables are:
+
+gpt_partition_addr
+    the starting offset of the partition in blocks as a hexadecimal number
+
+gpt_partition_size
+    the size of the partition in blocks as a hexadecimal number
+
+gpt_partition_name
+    the name of the partition
+
+gpt_partition_entry
+    the partition number in the table, e.g. 1, 2, 3, etc.
+
+gpt swap
+~~~~~~~~
+
+Changes the names of all partitions that are named 'name1' to be 'name2', and
+all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
+required.
+
+gpt verify
+~~~~~~~~~~
+
+Sets return value $? to 0 (true) if the partition layout on the
+specified disk matches the one in the provided partition string, and 1 (false)
+if it does not match. If no partition string is specified, the command will
+check if the disk is partitioned or not.
+
+gpt write
+~~~~~~~~~
+
+(Re)writes the partition table on the disk to match the provided
+partition string. It returns 0 on success or 1 on failure.
+
+Configuration
+-------------
+
+To use the 'gpt' command you must specify CONFIG_CMD_GPT=y. To enable 'gpt
+read', 'gpt swap' and 'gpt rename', you must specify CONFIG_CMD_GPT_RENAME=y.
+
+Examples
+~~~~~~~~
+Create 6 partitions on a disk::
+
+    => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
+        name=boot,start=4M,size=128M,bootable,type=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7,
+        name=rootfs,size=3072M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=system-data,size=512M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=[ext],size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=user,size=-,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=modules,size=100M,type=0fc63daf-8483-4772-8e79-3d69d8477de4;
+        name=ramdisk,size=8M,type=0fc63daf-8483-4772-8e79-3d69d8477de4
+    => gpt write mmc 0 $gpt_parts
+
+
+Verify that the device matches the partition layout described in the variable
+$gpt_parts::
+
+    => gpt verify mmc 0 $gpt_parts
+
+
+Get the information about the partition named 'rootfs'::
+
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_addr}
+    2000
+    => echo ${gpt_partition_size}
+    14a000
+    => echo ${gpt_partition_name}
+    rootfs
+    => echo ${gpt_partition_entry}
+    2
+
+Get the list of partition names on the disk::
+
+    => gpt enumerate
+    => echo gpt_partition_list
+    boot rootfs system-data [ext] user modules ramdisk
+
+
+Get the GUID for a disk::
+
+    => gpt guid mmc 0
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
+    => gpt guid mmc gpt_disk_uuid
+    => echo ${gpt_disk_uuid}
+    bec9fc2a-86c1-483d-8a0e-0109732277d7
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index f45a7f5502..fa702920fa 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -66,6 +66,7 @@ Shell commands
    cmd/for
    cmd/fwu_mdata
    cmd/gpio
+   cmd/gpt
    cmd/host
    cmd/imxtract
    cmd/load
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 3/8] tests: gpt: Remove test order dependency
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 1/8] cmd: gpt: Remove confusing help text Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 2/8] doc: Add gpt command documentation Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-09-12 15:17           ` Tom Rini
  2023-08-31 16:51         ` [PATCH v5 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
                           ` (4 subsequent siblings)
  7 siblings, 1 reply; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot; +Cc: Joshua Watt, Enric Balletbo i Serra, Simon Glass

Re-create a clean disk image for each test to prevent modifications from
one test affecting another

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 test/py/tests/test_gpt.py | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 73bfbf77a2..339468bc12 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -61,18 +61,14 @@ class GptTestDiskImage(object):
         cmd = ('cp', persistent, self.path)
         u_boot_utils.run_and_log(u_boot_console, cmd)
 
-gtdi = None
 @pytest.fixture(scope='function')
 def state_disk_image(u_boot_console):
     """pytest fixture to provide a GptTestDiskImage object to tests.
     This is function-scoped because it uses u_boot_console, which is also
-    function-scoped. However, we don't need to actually do any function-scope
-    work, so this simply returns the same object over and over each time."""
+    function-scoped. A new disk is returned each time to prevent tests from
+    interfering with each other."""
 
-    global gtdi
-    if not gtdi:
-        gtdi = GptTestDiskImage(u_boot_console)
-    return gtdi
+    return GptTestDiskImage(u_boot_console)
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
@@ -186,12 +182,12 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
 
     u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"first"' in output
-    assert '0x00001000	0x00001bff	"second"' in output
-    u_boot_console.run_command('gpt swap host 0 first second')
+    assert '0x00000800	0x00000fff	"part1"' in output
+    assert '0x00001000	0x00001bff	"part2"' in output
+    u_boot_console.run_command('gpt swap host 0 part1 part2')
     output = u_boot_console.run_command('part list host 0')
-    assert '0x00000800	0x00000fff	"second"' in output
-    assert '0x00001000	0x00001bff	"first"' in output
+    assert '0x00000800	0x00000fff	"part2"' in output
+    assert '0x00001000	0x00001bff	"part1"' in output
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 4/8] cmd: gpt: Add gpt_partition_bootable variable
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                           ` (2 preceding siblings ...)
  2023-08-31 16:51         ` [PATCH v5 3/8] tests: gpt: Remove test order dependency Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
                           ` (3 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Heinrich Schuchardt, Simon Glass, Enric Balletbo i Serra

Adds an additional variable called gpt_partition_bootable that indicates
if the given partition is bootable or not.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 |  9 +++++++--
 doc/usage/cmd/gpt.rst     |  5 +++++
 test/py/tests/test_gpt.py | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index fe9e06681c..c6c8282ac9 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -725,7 +725,7 @@ static int gpt_enumerate(struct blk_desc *desc)
  * gpt_setenv_part_variables() - setup partition environmental variables
  *
  * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
- * and gpt_partition_size environment variables.
+ * and gpt_partition_size, gpt_partition_bootable environment variables.
  *
  * @pinfo: pointer to disk partition
  * @i: partition entry
@@ -752,6 +752,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
 	if (ret)
 		goto fail;
 
+	ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
+	if (ret)
+		goto fail;
+
 	return 0;
 
 fail:
@@ -1057,7 +1061,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt setenv mmc 0 $name\n"
 	"    - setup environment variables for partition $name:\n"
 	"      gpt_partition_addr, gpt_partition_size,\n"
-	"      gpt_partition_name, gpt_partition_entry\n"
+	"      gpt_partition_name, gpt_partition_entry,\n"
+	"      gpt_partition_bootable\n"
 	" gpt enumerate mmc 0\n"
 	"    - store list of partitions to gpt_partition_list environment variable\n"
 	" gpt guid <interface> <dev>\n"
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index 6387c8116f..b505b159d0 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -108,6 +108,9 @@ gpt_partition_name
 gpt_partition_entry
     the partition number in the table, e.g. 1, 2, 3, etc.
 
+gpt_partition_bootable
+    1 if the partition is marked as bootable, 0 if not
+
 gpt swap
 ~~~~~~~~
 
@@ -167,6 +170,8 @@ Get the information about the partition named 'rootfs'::
     rootfs
     => echo ${gpt_partition_entry}
     2
+    => echo ${gpt_partition_bootable}
+    0
 
 Get the list of partition names on the disk::
 
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 339468bc12..946858800d 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -49,6 +49,7 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
@@ -117,6 +118,38 @@ def test_gpt_guid(state_disk_image, u_boot_console):
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_setenv(state_disk_image, u_boot_console):
+    """Test the gpt setenv command."""
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt setenv host 0 part1')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == '800'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part1'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == '1'
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == '1'
+
+    output = u_boot_console.run_command('gpt setenv host 0 part2')
+    assert 'success!' in output
+    output = u_boot_console.run_command('echo ${gpt_partition_addr}')
+    assert output.rstrip() == '1000'
+    output = u_boot_console.run_command('echo ${gpt_partition_size}')
+    assert output.rstrip() == 'c00'
+    output = u_boot_console.run_command('echo ${gpt_partition_name}')
+    assert output.rstrip() == 'part2'
+    output = u_boot_console.run_command('echo ${gpt_partition_entry}')
+    assert output.rstrip() == '2'
+    output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+    assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 5/8] cmd: gpt: Add command to set bootable flags
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                           ` (3 preceding siblings ...)
  2023-08-31 16:51         ` [PATCH v5 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
                           ` (2 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Simon Glass, Heinrich Schuchardt, Enric Balletbo i Serra

Adds a command that can be used to modify the GPT partition table to
indicate which partitions should have the bootable flag set

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 80 +++++++++++++++++++++++++++++++++++++++
 doc/usage/cmd/gpt.rst     | 12 ++++++
 test/py/tests/test_gpt.py | 22 +++++++++++
 3 files changed, 114 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index c6c8282ac9..45fbe07404 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -972,6 +972,81 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	free(partitions_list);
 	return ret;
 }
+
+/**
+ * gpt_set_bootable() - Set bootable flags for partitions
+ *
+ * Sets the bootable flag for any partition names in the comma separated list of
+ * partition names. Any partitions not in the list have their bootable flag
+ * cleared
+ *
+ * @desc: block device descriptor
+ * @name: Comma separated list of partition names
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_set_bootable(struct blk_desc *blk_dev_desc, char *const part_list)
+{
+	char *name;
+	char disk_guid[UUID_STR_LEN + 1];
+	struct list_head *pos;
+	struct disk_part *curr;
+	struct disk_partition *partitions = NULL;
+	int part_count = 0;
+	int ret = get_disk_guid(blk_dev_desc, disk_guid);
+
+	if (ret < 0)
+		return ret;
+
+	ret = get_gpt_info(blk_dev_desc);
+	if (ret <= 0)
+		goto out;
+
+	part_count = ret;
+	partitions = malloc(sizeof(*partitions) * part_count);
+	if (!partitions) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Copy partitions and clear bootable flag */
+	part_count = 0;
+	list_for_each(pos, &disk_partitions) {
+		curr = list_entry(pos, struct disk_part, list);
+		partitions[part_count] = curr->gpt_part_info;
+		partitions[part_count].bootable &= ~PART_BOOTABLE;
+		part_count++;
+	}
+
+	name = strtok(part_list, ",");
+	while (name) {
+		bool found = false;
+
+		for (int i = 0; i < part_count; i++) {
+			if (strcmp((char *)partitions[i].name, name) == 0) {
+				partitions[i].bootable |= PART_BOOTABLE;
+				found = true;
+			}
+		}
+
+		if (!found) {
+			printf("Warning: No partition matching '%s' found\n",
+			       name);
+		}
+
+		name = strtok(NULL, ",");
+	}
+
+	ret = gpt_restore(blk_dev_desc, disk_guid, partitions, part_count);
+
+out:
+	del_gpt_info();
+
+	if (partitions)
+		free(partitions);
+
+	return ret;
+}
 #endif
 
 /**
@@ -1031,6 +1106,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if ((strcmp(argv[1], "swap") == 0) ||
 		   (strcmp(argv[1], "rename") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
+	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
+		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
 #endif
 	} else {
 		return CMD_RET_USAGE;
@@ -1082,8 +1159,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	"      and vice-versa\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
+	" gpt set-bootable <interface> <dev> <list>\n"
+	"    - make partition names in list bootable\n"
 	" Example usage:\n"
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
+	" gpt set-bootable mmc 0 boot_a,boot_b\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index b505b159d0..288dd365c0 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -13,6 +13,7 @@ Synopsis
     gpt read <interface> <dev> [<varname>]
     gpt rename <interface> <dev> <part> <name>
     gpt repair <interface> <dev>
+    gpt set-bootable <interface> <dev> <partition list>
     gpt setenv <interface> <dev> <partition name>
     gpt swap <interface> <dev> <name1> <name2>
     gpt verify <interface> <dev> [<partition string>]
@@ -90,6 +91,13 @@ gpt repair
 
 Repairs the GPT partition tables if it they become corrupted.
 
+gpt set-bootable
+~~~~~~~~~~~~~~~~
+
+Sets the bootable flag for all partitions in the table. If the partition name
+is in 'partition list' (separated by ','), the bootable flag is set, otherwise
+it is cleared. CONFIG_CMD_GPT_RENAME=y is required.
+
 gpt setenv
 ~~~~~~~~~~
 
@@ -187,3 +195,7 @@ Get the GUID for a disk::
     => gpt guid mmc gpt_disk_uuid
     => echo ${gpt_disk_uuid}
     bec9fc2a-86c1-483d-8a0e-0109732277d7
+
+Set the bootable flag for the 'boot' partition and clear it for all others::
+
+    => gpt set-bootable mmc 0 boot
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 946858800d..5d23f9b292 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -222,6 +222,28 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part2"' in output
     assert '0x00001000	0x00001bff	"part1"' in output
 
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_set_bootable(state_disk_image, u_boot_console):
+    """Test the gpt set-bootable command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    parts = ('part2', 'part1')
+    for bootable in parts:
+        output = u_boot_console.run_command(f'gpt set-bootable host 0 {bootable}')
+        assert 'success!' in output
+
+        for p in parts:
+            output = u_boot_console.run_command(f'gpt setenv host 0 {p}')
+            assert 'success!' in output
+            output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
+            if p == bootable:
+                assert output.rstrip() == '1'
+            else:
+                assert output.rstrip() == '0'
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_part')
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 6/8] cmd: gpt: Preserve type GUID if enabled
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                           ` (4 preceding siblings ...)
  2023-08-31 16:51         ` [PATCH v5 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Heinrich Schuchardt, Simon Glass, Enric Balletbo i Serra

If CONFIG_PARTITION_TYPE_GUID is enabled, the type GUID will be
preserved when writing out the partition string. It was already
respected when writing out partitions; this ensures that if you capture
the current partition layout and write it back (such as when renaming),
the type GUIDs are preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 16 ++++++++++
 test/py/tests/test_gpt.py | 65 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 45fbe07404..0090e02110 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -173,6 +173,9 @@ static int calc_parts_list_len(int numparts)
 	/* see part.h for definition of struct disk_partition */
 	partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
 	partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
+#endif
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -211,6 +214,11 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
 		PART_TYPE_LEN);
 	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
 	newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+	strncpy(newpart->gpt_part_info.type_guid, (const char *)info->type_guid,
+		UUID_STR_LEN);
+	newpart->gpt_part_info.type_guid[UUID_STR_LEN] = '\0';
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
 		UUID_STR_LEN);
@@ -252,6 +260,9 @@ static void print_gpt_info(void)
 		       curr->gpt_part_info.name);
 		printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
 		       curr->gpt_part_info.bootable & PART_BOOTABLE);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		printf("Type GUID %s\n", curr->gpt_part_info.type_guid);
+#endif
 #ifdef CONFIG_PARTITION_UUIDS
 		printf("UUID %s\n", curr->gpt_part_info.uuid);
 #endif
@@ -299,6 +310,11 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 					    curr->gpt_part_info.blksz);
 		strncat(partitions_list, partstr, PART_NAME_LEN + 1);
 
+#ifdef CONFIG_PARTITION_TYPE_GUID
+		strcat(partitions_list, ",type=");
+		strncat(partitions_list, curr->gpt_part_info.type_guid,
+			UUID_STR_LEN + 1);
+#endif
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 5d23f9b292..93007dee9a 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -16,6 +16,35 @@ the test.
 # Mark all tests here as slow
 pytestmark = pytest.mark.slow
 
+def parse_gpt_parts(disk_str):
+    """Parser a partition string into a list of partitions.
+
+    Args:
+        disk_str: The disk description string, as returned by `gpt read`
+
+    Returns:
+        A list of parsed partitions. Each partition is a dictionary with the
+        string value from each specified key in the partition description, or a
+        key with with the value True for a boolean flag
+    """
+    parts = []
+    for part_str in disk_str.split(';'):
+        part = {}
+        for option in part_str.split(","):
+            if not option:
+                continue
+
+            if "=" in option:
+                key, value = option.split("=")
+                part[key] = value
+            else:
+                part[option] = True
+
+        if part:
+            parts.append(part)
+
+    return parts
+
 class GptTestDiskImage(object):
     """Disk Image used by the GPT tests."""
 
@@ -49,11 +78,13 @@ class GptTestDiskImage(object):
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
                 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
                     '-A 1:set:2',
                     persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
+                    '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
                     persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 cmd = ('sgdisk', '--load-backup=' + persistent)
@@ -88,6 +119,40 @@ def test_gpt_read(state_disk_image, u_boot_console):
     assert '0x00000800	0x00000fff	"part1"' in output
     assert '0x00001000	0x00001bff	"part2"' in output
 
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('partition_type_guid')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_read_var(state_disk_image, u_boot_console):
+    """Test the gpt read command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('gpt read host 0 gpt_parts')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('echo ${gpt_parts}')
+    parts = parse_gpt_parts(output.rstrip())
+
+    assert parts == [
+        {
+            "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
+        },
+        {
+            "name": "part1",
+            "start": "0x100000",
+            "size": "0x100000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+        },
+        {
+            "name": "part2",
+            "start": "0x200000",
+            "size": "0x180000",
+            "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+            "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
+        },
+    ]
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.requiredtool('sgdisk')
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 7/8] cmd: gpt: Preserve bootable flag
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                           ` (5 preceding siblings ...)
  2023-08-31 16:51         ` [PATCH v5 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  2023-08-31 16:51         ` [PATCH v5 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Heinrich Schuchardt, Simon Glass, Enric Balletbo i Serra

Sets the bootable flag when constructing the partition string from the
current partition configuration. This ensures that when the partitions
are written back (for example, when renaming a partition), the flag is
preserved.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 3 +++
 test/py/tests/test_gpt.py | 1 +
 2 files changed, 4 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 0090e02110..927b6afa68 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -176,6 +176,7 @@ static int calc_parts_list_len(int numparts)
 #ifdef CONFIG_PARTITION_TYPE_GUID
 	partlistlen += numparts * (strlen("type=,") + UUID_STR_LEN + 1);
 #endif
+	partlistlen += numparts * strlen("bootable,");
 	partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
 	/* for the terminating null */
 	partlistlen++;
@@ -318,6 +319,8 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
 		strcat(partitions_list, ",uuid=");
 		strncat(partitions_list, curr->gpt_part_info.uuid,
 			UUID_STR_LEN + 1);
+		if (curr->gpt_part_info.bootable & PART_BOOTABLE)
+			strcat(partitions_list, ",bootable");
 		strcat(partitions_list, ";");
 	}
 	return 0;
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index 93007dee9a..b4c03bc3a2 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -143,6 +143,7 @@ def test_gpt_read_var(state_disk_image, u_boot_console):
             "size": "0x100000",
             "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
             "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
+            "bootable": True,
         },
         {
             "name": "part2",
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH v5 8/8] cmd: gpt: Add command to swap partition order
  2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
                           ` (6 preceding siblings ...)
  2023-08-31 16:51         ` [PATCH v5 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
@ 2023-08-31 16:51         ` Joshua Watt
  7 siblings, 0 replies; 74+ messages in thread
From: Joshua Watt @ 2023-08-31 16:51 UTC (permalink / raw)
  To: u-boot
  Cc: Joshua Watt, Heinrich Schuchardt, Simon Glass, Enric Balletbo i Serra

Adds a command called "gpt transpose" which will swap the order two
partition table entries in the GPT partition table (but leaves them
pointing to the same locations on disk).

This can be useful for swapping bootloaders in systems that use an A/B
partitioning scheme where the bootrom is hard coded to look for the
bootloader in a specific index in the GPT partition table.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 cmd/gpt.c                 | 46 ++++++++++++++++++++++++++++++++++++---
 doc/usage/cmd/gpt.rst     | 25 +++++++++++++++++++++
 test/py/tests/test_gpt.py | 19 ++++++++++++++++
 3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 927b6afa68..58b2c904a1 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -858,8 +858,9 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 	u8 part_count = 0;
 	int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
 
-	if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
-	    (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
+	if (!subcomm || !name1 || !name2 ||
+	    (strcmp(subcomm, "swap") && strcmp(subcomm, "rename") &&
+	     strcmp(subcomm, "transpose")))
 		return -EINVAL;
 
 	ret = get_disk_guid(dev_desc, disk_guid);
@@ -920,6 +921,41 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 			ret = -EINVAL;
 			goto out;
 		}
+	} else if (!strcmp(subcomm, "transpose")) {
+		int idx1, idx2;
+		struct disk_partition* first = NULL;
+		struct disk_partition* second= NULL;
+		struct disk_partition tmp_part;
+
+		idx1 = simple_strtoul(name1, NULL, 10);
+		idx2 = simple_strtoul(name2, NULL, 10);
+		if (idx1 == idx2) {
+			printf("Cannot swap partition with itself\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		list_for_each(pos, &disk_partitions) {
+			curr = list_entry(pos, struct disk_part, list);
+			if (curr->partnum == idx1)
+				first = &curr->gpt_part_info;
+			else if (curr->partnum == idx2)
+				second = &curr->gpt_part_info;
+		}
+		if (!first) {
+			printf("Illegal partition number %s\n", name1);
+			ret = -EINVAL;
+			goto out;
+		}
+		if (!second) {
+			printf("Illegal partition number %s\n", name2);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		tmp_part = *first;
+		*first = *second;
+		*second = tmp_part;
 	} else { /* rename */
 		if (strlen(name2) > PART_NAME_LEN) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
@@ -1123,7 +1159,8 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	} else if (strcmp(argv[1], "read") == 0) {
 		ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
 	} else if ((strcmp(argv[1], "swap") == 0) ||
-		   (strcmp(argv[1], "rename") == 0)) {
+		   (strcmp(argv[1], "rename") == 0) ||
+		   (strcmp(argv[1], "transpose") == 0)) {
 		ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
 	} else if ((strcmp(argv[1], "set-bootable") == 0)) {
 		ret = gpt_set_bootable(blk_dev_desc, argv[4]);
@@ -1176,6 +1213,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap <interface> <dev> <name1> <name2>\n"
 	"    - change all partitions named name1 to name2\n"
 	"      and vice-versa\n"
+	" gpt transpose <interface> <dev> <part1> <part2>\n"
+	"    - Swap the order of the entries for part1 and part2 in the partition table\n"
 	" gpt rename <interface> <dev> <part> <name>\n"
 	"    - rename the specified partition\n"
 	" gpt set-bootable <interface> <dev> <list>\n"
@@ -1184,5 +1223,6 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
 	" gpt swap mmc 0 foo bar\n"
 	" gpt rename mmc 0 3 foo\n"
 	" gpt set-bootable mmc 0 boot_a,boot_b\n"
+	" gpt transpose mmc 0 1 2\n"
 #endif
 );
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index 288dd365c0..f6115ecb0e 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -16,6 +16,7 @@ Synopsis
     gpt set-bootable <interface> <dev> <partition list>
     gpt setenv <interface> <dev> <partition name>
     gpt swap <interface> <dev> <name1> <name2>
+    gpt transpose <interface> <dev> <part1> <part2>
     gpt verify <interface> <dev> [<partition string>]
     gpt write <interface> <dev> <partition string>
 
@@ -126,6 +127,13 @@ Changes the names of all partitions that are named 'name1' to be 'name2', and
 all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
 required.
 
+gpt transpose
+~~~~~~~~~~~~~
+
+Swaps the order of two partition table entries with indexes 'part1' and 'part2'
+in the partition table, but otherwise leaves the actual partition data
+untouched.
+
 gpt verify
 ~~~~~~~~~~
 
@@ -199,3 +207,20 @@ Get the GUID for a disk::
 Set the bootable flag for the 'boot' partition and clear it for all others::
 
     => gpt set-bootable mmc 0 boot
+
+Swap the order of the 'boot' and 'rootfs' partition table entries::
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    2
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    1
+
+    => gpt transpose mmc 0 1 2
+
+    => gpt setenv mmc 0 rootfs
+    => echo ${gpt_partition_entry}
+    1
+    => gpt setenv mmc 0 boot
+    => echo ${gpt_partition_entry}
+    2
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index b4c03bc3a2..6e135b663e 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -329,3 +329,22 @@ def test_gpt_write(state_disk_image, u_boot_console):
     assert '0x00001000	0x00001bff	"second"' in output
     output = u_boot_console.run_command('gpt guid host 0')
     assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
+
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_transpose(state_disk_image, u_boot_console):
+    """Test the gpt transpose command."""
+
+    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+    output = u_boot_console.run_command('part list host 0')
+    assert '1\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '2\t0x00001000\t0x00001bff\t"part2"' in output
+
+    output = u_boot_console.run_command('gpt transpose host 0 1 2')
+    assert 'success!' in output
+
+    output = u_boot_console.run_command('part list host 0')
+    assert '2\t0x00000800\t0x00000fff\t"part1"' in output
+    assert '1\t0x00001000\t0x00001bff\t"part2"' in output
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH v5 3/8] tests: gpt: Remove test order dependency
  2023-08-31 16:51         ` [PATCH v5 3/8] tests: gpt: Remove test order dependency Joshua Watt
@ 2023-09-12 15:17           ` Tom Rini
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Rini @ 2023-09-12 15:17 UTC (permalink / raw)
  To: Joshua Watt; +Cc: u-boot, Enric Balletbo i Serra, Simon Glass

[-- Attachment #1: Type: text/plain, Size: 290 bytes --]

On Thu, Aug 31, 2023 at 10:51:36AM -0600, Joshua Watt wrote:

> Re-create a clean disk image for each test to prevent modifications from
> one test affecting another
> 
> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>

For the series, applied to u-boot/next, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

end of thread, other threads:[~2023-09-12 15:17 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-15 16:26 [PATCH 0/6] cmd: gpt: GPT manipulation improvements Joshua Watt
2023-08-15 16:26 ` [PATCH 1/6] cmd: gpt: Remove confusing help text Joshua Watt
2023-08-18 14:23   ` Tom Rini
2023-08-23 23:57   ` Simon Glass
2023-08-15 16:26 ` [PATCH 2/6] cmd: gpt: Add command to set bootable flags Joshua Watt
2023-08-15 18:39   ` Simon Glass
2023-08-15 16:26 ` [PATCH 3/6] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
2023-08-15 16:26 ` [PATCH 4/6] cmd: gpt: Preserve type GUID if enabled Joshua Watt
2023-08-15 16:26 ` [PATCH 5/6] cmd: gpt: Preserve bootable flag Joshua Watt
2023-08-15 16:27 ` [PATCH 6/6] cmd: gpt: Add command to swap partition order Joshua Watt
2023-08-23 23:57   ` Simon Glass
2023-08-23 16:47 ` [PATCH v2 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
2023-08-23 16:47   ` [PATCH v2 1/8] cmd: gpt: Remove confusing help text Joshua Watt
2023-08-23 18:15     ` Tom Rini
2023-08-23 16:47   ` [PATCH v2 2/8] doc: Add gpt command documentation Joshua Watt
2023-08-23 18:15     ` Tom Rini
2023-08-23 23:57     ` Simon Glass
2023-08-23 16:47   ` [PATCH v2 3/8] tests: gpt: Remove test order dependency Joshua Watt
2023-08-23 23:57     ` Simon Glass
2023-08-24  3:29       ` Joshua Watt
2023-08-23 16:47   ` [PATCH v2 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
2023-08-23 23:57     ` Simon Glass
2023-08-23 16:47   ` [PATCH v2 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
2023-08-23 23:57     ` Simon Glass
2023-08-23 16:47   ` [PATCH v2 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
2023-08-23 23:57     ` Simon Glass
2023-08-23 16:47   ` [PATCH v2 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
2023-08-23 23:57     ` Simon Glass
2023-08-23 16:47   ` [PATCH v2 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
2023-08-25 19:38   ` [PATCH v3 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
2023-08-25 19:38     ` [PATCH v3 1/8] cmd: gpt: Remove confusing help text Joshua Watt
2023-08-25 19:38     ` [PATCH v3 2/8] doc: Add gpt command documentation Joshua Watt
2023-08-25 23:53       ` Simon Glass
2023-08-28 21:52         ` Joshua Watt
2023-08-26  1:57       ` Heinrich Schuchardt
2023-08-28 19:29         ` Joshua Watt
2023-08-28 20:01           ` Heinrich Schuchardt
2023-08-28 21:01             ` Joshua Watt
2023-08-25 19:38     ` [PATCH v3 3/8] tests: gpt: Remove test order dependency Joshua Watt
2023-08-25 19:38     ` [PATCH v3 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
2023-08-25 23:53       ` Simon Glass
2023-08-25 19:38     ` [PATCH v3 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
2023-08-25 19:38     ` [PATCH v3 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
2023-08-25 23:53       ` Simon Glass
2023-08-26  0:37       ` Heinrich Schuchardt
2023-08-25 19:38     ` [PATCH v3 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
2023-08-25 19:38     ` [PATCH v3 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
2023-08-25 23:53       ` Simon Glass
2023-08-26  1:00       ` Heinrich Schuchardt
2023-08-28 21:56     ` [PATCH v4 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
2023-08-28 21:56       ` [PATCH v4 1/8] cmd: gpt: Remove confusing help text Joshua Watt
2023-08-28 22:05         ` Heinrich Schuchardt
2023-08-28 21:56       ` [PATCH v4 2/8] doc: Add gpt command documentation Joshua Watt
2023-08-28 22:45         ` Heinrich Schuchardt
2023-08-28 22:59           ` Heinrich Schuchardt
2023-08-29 13:22             ` Joshua Watt
2023-08-28 21:56       ` [PATCH v4 3/8] tests: gpt: Remove test order dependency Joshua Watt
2023-08-28 21:56       ` [PATCH v4 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
2023-08-28 21:56       ` [PATCH v4 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
2023-08-28 22:54         ` Heinrich Schuchardt
2023-08-29 13:24           ` Joshua Watt
2023-08-28 21:56       ` [PATCH v4 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
2023-08-28 21:56       ` [PATCH v4 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
2023-08-28 21:56       ` [PATCH v4 8/8] cmd: gpt: Add command to swap partition order Joshua Watt
2023-08-31 16:51       ` [PATCH v5 0/8] cmd: gpt: GPT manipulation improvements Joshua Watt
2023-08-31 16:51         ` [PATCH v5 1/8] cmd: gpt: Remove confusing help text Joshua Watt
2023-08-31 16:51         ` [PATCH v5 2/8] doc: Add gpt command documentation Joshua Watt
2023-08-31 16:51         ` [PATCH v5 3/8] tests: gpt: Remove test order dependency Joshua Watt
2023-09-12 15:17           ` Tom Rini
2023-08-31 16:51         ` [PATCH v5 4/8] cmd: gpt: Add gpt_partition_bootable variable Joshua Watt
2023-08-31 16:51         ` [PATCH v5 5/8] cmd: gpt: Add command to set bootable flags Joshua Watt
2023-08-31 16:51         ` [PATCH v5 6/8] cmd: gpt: Preserve type GUID if enabled Joshua Watt
2023-08-31 16:51         ` [PATCH v5 7/8] cmd: gpt: Preserve bootable flag Joshua Watt
2023-08-31 16:51         ` [PATCH v5 8/8] cmd: gpt: Add command to swap partition order Joshua Watt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.