From: Joshua Watt Date: Thu, 31 Aug 2023 16:51:38 +0000 (-0600) Subject: cmd: gpt: Add command to set bootable flags X-Git-Url: http://git.dujemihanovic.xyz/login.html?a=commitdiff_plain;h=a1e793add5dd21c2a1b08bc57ac99e43183913b6;p=u-boot.git 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 --- diff --git a/cmd/gpt.c b/cmd/gpt.c index ce85632377..42e289c872 100644 --- a/cmd/gpt.c +++ b/cmd/gpt.c @@ -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 \n" " - rename the specified partition\n" + " gpt set-bootable \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 [] gpt rename gpt repair + gpt set-bootable gpt setenv gpt swap gpt verify [] @@ -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')