cmd: gpt: Add command to set bootable flags

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>
This commit is contained in:
Joshua Watt 2023-08-31 10:51:38 -06:00 committed by Tom Rini
parent b1433affd9
commit a1e793add5
3 changed files with 114 additions and 0 deletions

View file

@ -970,6 +970,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
/**
@ -1029,6 +1104,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;
@ -1080,8 +1157,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
);

View file

@ -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

View file

@ -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')