
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)) {
#endif } else { return CMD_RET_USAGE;ret = gpt_set_bootable(blk_dev_desc, argv[4]);
@@ -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"
#endif );" gpt set-bootable mmc 0 boot_a,boot_b\n"
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')