mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 05:08:24 +00:00
Merge branch '2023-09-12-gpt-improvements' into next
Bring in two series to improve GPT support. For the first series from Joshua: 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. For the second series from Heinrich: To partition a block device the partition type GUIDs are needed but 'gpt read' does not provide these. Add the missing parts. There is some overlap in these two series but I believe I have merged things correctly.
This commit is contained in:
commit
ce67ba1e30
5 changed files with 391 additions and 43 deletions
204
cmd/gpt.c
204
cmd/gpt.c
|
@ -162,22 +162,31 @@ static bool found_key(const char *str, const char *key)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calc_parts_list_len() - get size of partition table description
|
||||||
|
*
|
||||||
|
* @numparts: number of partitions
|
||||||
|
* Return: string size including terminating NUL
|
||||||
|
*/
|
||||||
static int calc_parts_list_len(int numparts)
|
static int calc_parts_list_len(int numparts)
|
||||||
{
|
{
|
||||||
int partlistlen = UUID_STR_LEN + 1 + strlen("uuid_disk=");
|
/* number of hexadecimal digits of the lbaint_t representation */
|
||||||
/* for the comma */
|
const int lbaint_size = 2 * sizeof(lbaint_t);
|
||||||
partlistlen++;
|
int partlistlen;
|
||||||
|
|
||||||
/* per-partition additions; numparts starts at 1, so this should be correct */
|
/* media description including terminating NUL */
|
||||||
partlistlen += numparts * (strlen("name=,") + PART_NAME_LEN + 1);
|
partlistlen = strlen("uuid_disk=;") + UUID_STR_LEN + 1;
|
||||||
|
/* per-partition descriptions; numparts */
|
||||||
|
partlistlen += numparts * (strlen("name=,") + PART_NAME_LEN);
|
||||||
/* see part.h for definition of struct disk_partition */
|
/* see part.h for definition of struct disk_partition */
|
||||||
partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
|
partlistlen += numparts * (strlen("start=0x,") + lbaint_size);
|
||||||
partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
|
partlistlen += numparts * (strlen("size=0x,") + lbaint_size);
|
||||||
partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
|
if (IS_ENABLED(CONFIG_PARTITION_UUIDS))
|
||||||
/* for the terminating null */
|
partlistlen += numparts * (strlen("uuid=,") + UUID_STR_LEN);
|
||||||
partlistlen++;
|
if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID))
|
||||||
debug("Length of partitions_list is %d for %d partitions\n", partlistlen,
|
partlistlen += numparts * (strlen("type=;") + UUID_STR_LEN);
|
||||||
numparts);
|
debug("Length of partitions_list is %d for %d partitions\n",
|
||||||
|
partlistlen, numparts);
|
||||||
return partlistlen;
|
return partlistlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,10 +220,12 @@ static struct disk_part *allocate_disk_part(struct disk_partition *info,
|
||||||
PART_TYPE_LEN);
|
PART_TYPE_LEN);
|
||||||
newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
|
newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
|
||||||
newpart->gpt_part_info.bootable = info->bootable;
|
newpart->gpt_part_info.bootable = info->bootable;
|
||||||
if (IS_ENABLED(CONFIG_PARTITION_UUIDS)) {
|
if (IS_ENABLED(CONFIG_PARTITION_UUIDS))
|
||||||
strlcpy(newpart->gpt_part_info.uuid, disk_partition_uuid(info),
|
disk_partition_set_uuid(&newpart->gpt_part_info,
|
||||||
UUID_STR_LEN + 1);
|
disk_partition_uuid(info));
|
||||||
}
|
if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID))
|
||||||
|
disk_partition_set_type_guid(&newpart->gpt_part_info,
|
||||||
|
disk_partition_type_guid(info));
|
||||||
newpart->partnum = partnum;
|
newpart->partnum = partnum;
|
||||||
|
|
||||||
return newpart;
|
return newpart;
|
||||||
|
@ -250,9 +261,12 @@ static void print_gpt_info(void)
|
||||||
curr->gpt_part_info.name);
|
curr->gpt_part_info.name);
|
||||||
printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
|
printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
|
||||||
curr->gpt_part_info.bootable & PART_BOOTABLE);
|
curr->gpt_part_info.bootable & PART_BOOTABLE);
|
||||||
#ifdef CONFIG_PARTITION_UUIDS
|
if (CONFIG_IS_ENABLED(PARTITION_UUIDS))
|
||||||
printf("UUID %s\n", curr->gpt_part_info.uuid);
|
printf("UUID %s\n",
|
||||||
#endif
|
disk_partition_uuid(&curr->gpt_part_info));
|
||||||
|
if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID))
|
||||||
|
printf("Type GUID %s\n",
|
||||||
|
disk_partition_type_guid(&curr->gpt_part_info));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,9 +311,20 @@ static int create_gpt_partitions_list(int numparts, const char *guid,
|
||||||
curr->gpt_part_info.blksz);
|
curr->gpt_part_info.blksz);
|
||||||
strncat(partitions_list, partstr, PART_NAME_LEN + 1);
|
strncat(partitions_list, partstr, PART_NAME_LEN + 1);
|
||||||
|
|
||||||
strcat(partitions_list, ",uuid=");
|
if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID)) {
|
||||||
strncat(partitions_list, curr->gpt_part_info.uuid,
|
strcat(partitions_list, ",type=");
|
||||||
UUID_STR_LEN + 1);
|
strncat(partitions_list,
|
||||||
|
disk_partition_type_guid(&curr->gpt_part_info),
|
||||||
|
UUID_STR_LEN + 1);
|
||||||
|
}
|
||||||
|
if (CONFIG_IS_ENABLED(PARTITION_UUIDS)) {
|
||||||
|
strcat(partitions_list, ",uuid=");
|
||||||
|
strncat(partitions_list,
|
||||||
|
disk_partition_uuid(&curr->gpt_part_info),
|
||||||
|
UUID_STR_LEN + 1);
|
||||||
|
}
|
||||||
|
if (curr->gpt_part_info.bootable & PART_BOOTABLE)
|
||||||
|
strcat(partitions_list, ",bootable");
|
||||||
strcat(partitions_list, ";");
|
strcat(partitions_list, ";");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -723,7 +748,7 @@ static int gpt_enumerate(struct blk_desc *desc)
|
||||||
* gpt_setenv_part_variables() - setup partition environmental variables
|
* gpt_setenv_part_variables() - setup partition environmental variables
|
||||||
*
|
*
|
||||||
* Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
|
* 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
|
* @pinfo: pointer to disk partition
|
||||||
* @i: partition entry
|
* @i: partition entry
|
||||||
|
@ -750,6 +775,10 @@ static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
ret = env_set_ulong("gpt_partition_bootable", !!(pinfo->bootable & PART_BOOTABLE));
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -833,8 +862,9 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
|
||||||
u8 part_count = 0;
|
u8 part_count = 0;
|
||||||
int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
|
int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
|
||||||
|
|
||||||
if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
|
if (!subcomm || !name1 || !name2 ||
|
||||||
(strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
|
(strcmp(subcomm, "swap") && strcmp(subcomm, "rename") &&
|
||||||
|
strcmp(subcomm, "transpose")))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = get_disk_guid(dev_desc, disk_guid);
|
ret = get_disk_guid(dev_desc, disk_guid);
|
||||||
|
@ -895,6 +925,41 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
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 */
|
} else { /* rename */
|
||||||
if (strlen(name2) > PART_NAME_LEN) {
|
if (strlen(name2) > PART_NAME_LEN) {
|
||||||
printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
|
printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
|
||||||
|
@ -966,6 +1031,81 @@ static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
|
||||||
free(partitions_list);
|
free(partitions_list);
|
||||||
return ret;
|
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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1023,8 +1163,11 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||||
} else if (strcmp(argv[1], "read") == 0) {
|
} else if (strcmp(argv[1], "read") == 0) {
|
||||||
ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
|
ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
|
||||||
} else if ((strcmp(argv[1], "swap") == 0) ||
|
} 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]);
|
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
|
#endif
|
||||||
} else {
|
} else {
|
||||||
return CMD_RET_USAGE;
|
return CMD_RET_USAGE;
|
||||||
|
@ -1055,7 +1198,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
|
||||||
" gpt setenv mmc 0 $name\n"
|
" gpt setenv mmc 0 $name\n"
|
||||||
" - setup environment variables for partition $name:\n"
|
" - setup environment variables for partition $name:\n"
|
||||||
" gpt_partition_addr, gpt_partition_size,\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"
|
" gpt enumerate mmc 0\n"
|
||||||
" - store list of partitions to gpt_partition_list environment variable\n"
|
" - store list of partitions to gpt_partition_list environment variable\n"
|
||||||
" gpt guid <interface> <dev>\n"
|
" gpt guid <interface> <dev>\n"
|
||||||
|
@ -1073,10 +1217,16 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
|
||||||
" gpt swap <interface> <dev> <name1> <name2>\n"
|
" gpt swap <interface> <dev> <name1> <name2>\n"
|
||||||
" - change all partitions named name1 to name2\n"
|
" - change all partitions named name1 to name2\n"
|
||||||
" and vice-versa\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"
|
" gpt rename <interface> <dev> <part> <name>\n"
|
||||||
" - rename the specified partition\n"
|
" - rename the specified partition\n"
|
||||||
|
" gpt set-bootable <interface> <dev> <list>\n"
|
||||||
|
" - make partition names in list bootable\n"
|
||||||
" Example usage:\n"
|
" Example usage:\n"
|
||||||
" gpt swap mmc 0 foo bar\n"
|
" gpt swap mmc 0 foo bar\n"
|
||||||
" gpt rename mmc 0 3 foo\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
|
#endif
|
||||||
);
|
);
|
||||||
|
|
|
@ -299,7 +299,7 @@ int part_get_info_efi(struct blk_desc *desc, int part,
|
||||||
}
|
}
|
||||||
if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID)) {
|
if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID)) {
|
||||||
uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b,
|
uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b,
|
||||||
(char *)disk_partition_type_uuid(info),
|
(char *)disk_partition_type_guid(info),
|
||||||
UUID_STR_FORMAT_GUID);
|
UUID_STR_FORMAT_GUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,10 @@ Synopsis
|
||||||
gpt read <interface> <dev> [<varname>]
|
gpt read <interface> <dev> [<varname>]
|
||||||
gpt rename <interface> <dev> <part> <name>
|
gpt rename <interface> <dev> <part> <name>
|
||||||
gpt repair <interface> <dev>
|
gpt repair <interface> <dev>
|
||||||
|
gpt set-bootable <interface> <dev> <partition list>
|
||||||
gpt setenv <interface> <dev> <partition name>
|
gpt setenv <interface> <dev> <partition name>
|
||||||
gpt swap <interface> <dev> <name1> <name2>
|
gpt swap <interface> <dev> <name1> <name2>
|
||||||
|
gpt transpose <interface> <dev> <part1> <part2>
|
||||||
gpt verify <interface> <dev> [<partition string>]
|
gpt verify <interface> <dev> [<partition string>]
|
||||||
gpt write <interface> <dev> <partition string>
|
gpt write <interface> <dev> <partition string>
|
||||||
|
|
||||||
|
@ -90,6 +92,13 @@ gpt repair
|
||||||
|
|
||||||
Repairs the GPT partition tables if it they become corrupted.
|
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
|
gpt setenv
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -108,6 +117,9 @@ gpt_partition_name
|
||||||
gpt_partition_entry
|
gpt_partition_entry
|
||||||
the partition number in the table, e.g. 1, 2, 3, etc.
|
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
|
gpt swap
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
|
@ -115,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
|
all partitions named 'name2' to be 'name1'. CONFIG_CMD_GPT_RENAME=y is
|
||||||
required.
|
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
|
gpt verify
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -167,6 +186,8 @@ Get the information about the partition named 'rootfs'::
|
||||||
rootfs
|
rootfs
|
||||||
=> echo ${gpt_partition_entry}
|
=> echo ${gpt_partition_entry}
|
||||||
2
|
2
|
||||||
|
=> echo ${gpt_partition_bootable}
|
||||||
|
0
|
||||||
|
|
||||||
Get the list of partition names on the disk::
|
Get the list of partition names on the disk::
|
||||||
|
|
||||||
|
@ -182,3 +203,24 @@ Get the GUID for a disk::
|
||||||
=> gpt guid mmc gpt_disk_uuid
|
=> gpt guid mmc gpt_disk_uuid
|
||||||
=> echo ${gpt_disk_uuid}
|
=> echo ${gpt_disk_uuid}
|
||||||
bec9fc2a-86c1-483d-8a0e-0109732277d7
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -108,18 +108,38 @@ static inline void disk_partition_clr_uuid(struct disk_partition *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accessors for struct disk_partition field ->type_guid */
|
/* Accessors for struct disk_partition field ->type_guid */
|
||||||
extern char *__invalid_use_of_disk_partition_type_uuid;
|
extern char *__invalid_use_of_disk_partition_type_guid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disk_partition_type_guid() - get partition type GUID
|
||||||
|
*
|
||||||
|
* By using this function to get the partition type GUID we can use
|
||||||
|
* 'if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID))' instead of
|
||||||
|
* '#ifdef CONFIG_PARTITION_TYPE_GUID'.
|
||||||
|
*
|
||||||
|
* @info: partition information
|
||||||
|
* Return: partition type GUID
|
||||||
|
*/
|
||||||
static inline const
|
static inline const
|
||||||
char *disk_partition_type_uuid(const struct disk_partition *info)
|
char *disk_partition_type_guid(const struct disk_partition *info)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PARTITION_TYPE_GUID
|
#ifdef CONFIG_PARTITION_TYPE_GUID
|
||||||
return info->type_guid;
|
return info->type_guid;
|
||||||
#else
|
#else
|
||||||
return __invalid_use_of_disk_partition_type_uuid;
|
return __invalid_use_of_disk_partition_type_guid;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disk_partition_set_type_guid() - set partition type GUID
|
||||||
|
*
|
||||||
|
* By using this function to set the partition type GUID we can use
|
||||||
|
* 'if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID))' instead of
|
||||||
|
* '#ifdef CONFIG_PARTITION_TYPE_GUID'.
|
||||||
|
*
|
||||||
|
* @info: partition information
|
||||||
|
* @val: partition type GUID as string
|
||||||
|
*/
|
||||||
static inline void disk_partition_set_type_guid(struct disk_partition *info,
|
static inline void disk_partition_set_type_guid(struct disk_partition *info,
|
||||||
const char *val)
|
const char *val)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,35 @@ the test.
|
||||||
# Mark all tests here as slow
|
# Mark all tests here as slow
|
||||||
pytestmark = pytest.mark.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):
|
class GptTestDiskImage(object):
|
||||||
"""Disk Image used by the GPT tests."""
|
"""Disk Image used by the GPT tests."""
|
||||||
|
|
||||||
|
@ -49,10 +78,13 @@ class GptTestDiskImage(object):
|
||||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||||
# part1 offset 1MB size 1MB
|
# part1 offset 1MB size 1MB
|
||||||
cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
|
cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
|
||||||
|
'--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
|
||||||
|
'-A 1:set:2',
|
||||||
persistent)
|
persistent)
|
||||||
# part2 offset 2MB size 1.5MB
|
# part2 offset 2MB size 1.5MB
|
||||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||||
cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
|
cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
|
||||||
|
'--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
|
||||||
persistent)
|
persistent)
|
||||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||||
cmd = ('sgdisk', '--load-backup=' + persistent)
|
cmd = ('sgdisk', '--load-backup=' + persistent)
|
||||||
|
@ -61,18 +93,14 @@ class GptTestDiskImage(object):
|
||||||
cmd = ('cp', persistent, self.path)
|
cmd = ('cp', persistent, self.path)
|
||||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||||
|
|
||||||
gtdi = None
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def state_disk_image(u_boot_console):
|
def state_disk_image(u_boot_console):
|
||||||
"""pytest fixture to provide a GptTestDiskImage object to tests.
|
"""pytest fixture to provide a GptTestDiskImage object to tests.
|
||||||
This is function-scoped because it uses u_boot_console, which is also
|
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
|
function-scoped. A new disk is returned each time to prevent tests from
|
||||||
work, so this simply returns the same object over and over each time."""
|
interfering with each other."""
|
||||||
|
|
||||||
global gtdi
|
return GptTestDiskImage(u_boot_console)
|
||||||
if not gtdi:
|
|
||||||
gtdi = GptTestDiskImage(u_boot_console)
|
|
||||||
return gtdi
|
|
||||||
|
|
||||||
@pytest.mark.boardspec('sandbox')
|
@pytest.mark.boardspec('sandbox')
|
||||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||||
|
@ -91,6 +119,41 @@ def test_gpt_read(state_disk_image, u_boot_console):
|
||||||
assert '0x00000800 0x00000fff "part1"' in output
|
assert '0x00000800 0x00000fff "part1"' in output
|
||||||
assert '0x00001000 0x00001bff "part2"' 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",
|
||||||
|
"bootable": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "part2",
|
||||||
|
"start": "0x200000",
|
||||||
|
"size": "0x180000",
|
||||||
|
"type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
|
||||||
|
"uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
@pytest.mark.boardspec('sandbox')
|
@pytest.mark.boardspec('sandbox')
|
||||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||||
@pytest.mark.requiredtool('sgdisk')
|
@pytest.mark.requiredtool('sgdisk')
|
||||||
|
@ -121,6 +184,38 @@ def test_gpt_guid(state_disk_image, u_boot_console):
|
||||||
output = u_boot_console.run_command('gpt guid host 0')
|
output = u_boot_console.run_command('gpt guid host 0')
|
||||||
assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
|
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.boardspec('sandbox')
|
||||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||||
@pytest.mark.requiredtool('sgdisk')
|
@pytest.mark.requiredtool('sgdisk')
|
||||||
|
@ -186,12 +281,34 @@ def test_gpt_swap_partitions(state_disk_image, u_boot_console):
|
||||||
|
|
||||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||||
output = u_boot_console.run_command('part list host 0')
|
output = u_boot_console.run_command('part list host 0')
|
||||||
assert '0x00000800 0x00000fff "first"' in output
|
assert '0x00000800 0x00000fff "part1"' in output
|
||||||
assert '0x00001000 0x00001bff "second"' in output
|
assert '0x00001000 0x00001bff "part2"' in output
|
||||||
u_boot_console.run_command('gpt swap host 0 first second')
|
u_boot_console.run_command('gpt swap host 0 part1 part2')
|
||||||
output = u_boot_console.run_command('part list host 0')
|
output = u_boot_console.run_command('part list host 0')
|
||||||
assert '0x00000800 0x00000fff "second"' in output
|
assert '0x00000800 0x00000fff "part2"' in output
|
||||||
assert '0x00001000 0x00001bff "first"' 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.boardspec('sandbox')
|
||||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||||
|
@ -212,3 +329,22 @@ def test_gpt_write(state_disk_image, u_boot_console):
|
||||||
assert '0x00001000 0x00001bff "second"' in output
|
assert '0x00001000 0x00001bff "second"' in output
|
||||||
output = u_boot_console.run_command('gpt guid host 0')
|
output = u_boot_console.run_command('gpt guid host 0')
|
||||||
assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
|
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
|
||||||
|
|
Loading…
Add table
Reference in a new issue