add support for GPT partition name manipulation
cover add support for GPT partition name manipulation
From: Alison Chaiken <[email protected]>
One way for userspace and the bootloader to exchange information about dynamic image selection is via the storage device partition table, as described at
https://source.android.com/devices/tech/ota/ab_updates
The scheme described there relies on setting partitions' "boot" flag. When no partition on a device is bootable since the kernel and U-Boot are stored elsewhere, the name field in the GPT partition table offers another logical place to store information. These patches allow users to easily modify GPT partition names via bootscripts that can select different images based on a boot-failure counter, or when userspace installs a software update.
These patches have been tested on a TI DRA7xx-based SOM with U-Boot 2015.07. The storage device is an eMMC.
Alison Chaiken (3):
GPT: add accessor function for disk GUID
GPT: read partition table from device into a data structure rename GPT partitions to detect boot failure
cmd/gpt.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- disk/part_efi.c | 31 ++++++ include/part.h | 24 ++++ 3 files changed, 392 insertions(+), 2 deletions(-)
Signature · 1 line
2.1.4
PATCH 1/3 GPT: add accessor function for disk GUID
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
--- cmd/gpt.c | 29 ++++++++++++++++++++++++++++- disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ include/part.h | 15 +++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-)
cmd/gpt.c +28 -1
@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return 1 ; + +if (namestr !=NULL ) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return 0 ; +} +/** * do_gpt(): Perform GPT operations *
@@ -412,7 +429,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {int ret =CMD_RET_SUCCESS ;int dev =0 ; -char *ep; +char *ep, *varname =NULL ;struct blk_desc *blk_dev_desc =NULL ;if (argc <4 || argc >5 )
@@ -436,6 +453,9 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +if (argc ==5 )strcpy (varname, argv[4 ]); +return do_disk_guid (blk_dev_desc, varname); }else {return CMD_RET_USAGE ; }
@@ -458,4 +478,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );
disk/part_efi.c +31 -0
@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)* Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +*/ +int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{ +ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz); +gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */ +if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); +if (is_gpt_valid (dev_desc, (dev_desc->lba -1 ), + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid Backup GPT ***\n" , + __func__); +return -1 ; + }else { +printf ("%s: *** Using Backup GPT ***\n" , + __func__); + } + } + + guid_bin = (unsigned char *)(gpt_head->disk_guid.b); +uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc) {ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);
include/part.h +15 -0
@@ -367,6 +367,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,int gpt_verify_partitions (struct blk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT +* +* This function reads the GUID string from a block device whose descriptor +* is provided. +* +* @param dev_desc - block device descriptor +* @param guid - pre-allocated string in which to return the GUID +* +* @return - '0' on success, otherwise error +*/ +int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Signature · 1 line
2.1.4
PATCH 1/3 GPT: add accessor function for disk GUID
Quoted 8 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Signed-off-by Alison Chaiken <[email protected]>
Overall looks good, a few style things:
cmd/gpt.c static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part) · line 411
Quoted 2 lines
cmd/gpt.c +2
-0+if (namestr !=NULL ) +setenv (namestr, disk_guid);
You can just if (namestr) here
[snip]
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 457
Quoted 2 lines
cmd/gpt.c +2
-0+ }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +if (argc ==5 )strcpy (varname, argv[4 ]);
Go ahead and do this on multiple lines please. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170526/649a855f/attachment.sig>
PATCH 2/3 GPT: read partition table from device into a data structure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
--- cmd/gpt.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 9 +++++ 2 files changed, 122 insertions(+)
cmd/gpt.c +113 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,112 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); + +if (!newpart) +return ERR_PTR (-ENOMEM ); + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +/* +* 33 rather than 32, as each string must be null-terminated; +* other extract_val() above will fail. +*/ +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,33 ); +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,33 ); + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN +1 ); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as u-boot does */ +int valid_parts =1 , p, ret =0 ; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && (valid_parts >=2 )) +return -1 ; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -1 ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -456,6 +565,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if (strcmp (argv[1 ],"guid" ) ==0 ) {if (argc ==5 )strcpy (varname, argv[4 ]);return do_disk_guid (blk_dev_desc, varname); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -478,6 +589,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +9 -0
@@ -9,6 +9,7 @@#include <blk.h> #include <ide.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -46,6 +47,8 @@ struct block_drvr {#define DEV_TYPE_CDROM 0x05/* CD-ROM */ #define DEV_TYPE_OPDISK 0x07/* optical disk */ +#define MAX_SEARCH_PARTITIONS 16 + typedef struct disk_partition { lbaint_t start; /* # of first block in partition */ lbaint_t size; /* number of blocks in partition */
@@ -64,6 +67,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH 2/3 GPT: read partition table from device into a data structure
Quoted 7 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Signed-off-by Alison Chaiken <[email protected]>
[snip]
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 183
Quoted 6 lines
cmd/gpt.c +6
-0+/* +* 33 rather than 32, as each string must be null-terminated; +* other extract_val() above will fail. +*/ +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,33 ); +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,33 );
This isn't right. We have name[32]/type[32] so we're overflowing. I'm not quite sure where 32 came from and if we should be defining a name for it as well. But to make sure it is null-terminated we should be here memset'ing after malloc.
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 188
Quoted 5 lines
cmd/gpt.c +5
-0+ newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN +1 ); +#endif
Then this should just be copying UUID_STR_LEN over.
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 244
Quoted 4 lines
cmd/gpt.c +4
-0+if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -1 ;
We should return something from errno here rather than -1. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170526/569fea78/attachment.sig>
PATCH 3/3 rename GPT partitions to detect boot failure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it renames it failed’ and renames the ‘backup’ partition as ‘candidate’.
Logic:
-- Partitions can go to ‘failed’ only from ‘candidate’ and only
via u-boot. Partitions can go to ‘backup’ only from ‘primary’ and vice-versa, only via Linux. Partitions go to ‘candidate’ from ‘primary’ or ‘backup’ only via u-boot. Only system update software will rename 'failed' partitions.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
--- cmd/gpt.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 201 insertions(+), 6 deletions(-)
cmd/gpt.c +201 -6
@@ -21,6 +21,9 @@#include <memalign.h> #include <linux/compat.h> +/* ONEMIB is 2**20 */ +#define ONEMIB 1024*1024 +static LIST_HEAD (disk_partitions);/**
@@ -114,7 +117,6 @@ static char *extract_val(const char *str, const char *key)break ; } } -free (strcopy);return new;
@@ -158,6 +160,7 @@ static void del_gpt_info(void) {struct list_head *pos = &disk_partitions;struct disk_part *curr; +while (!list_empty (pos)) { curr = list_entry(pos->next, struct disk_part, list);list_del (pos->next);
@@ -165,6 +168,11 @@ static void del_gpt_info(void) } } +/* +* The number '33' comes from the '32' in the definition of disk_partition_t +* in include/part.h. That file has '37' rather than UUID_STR_LEN + 1, from +* include/uuid.h +*/ static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) {struct disk_part *newpart;
@@ -191,16 +199,33 @@ static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum)return newpart; } +static void prettyprint_part_size (char *sizestr,unsigned long partsize, +unsigned long blksize) +{ +unsigned long long partbytes; +unsigned long partmegabytes; + + partbytes = partsize * blksize; + partmegabytes =lldiv (partbytes,ONEMIB ); +snprintf (sizestr,16 ,"%luMiB" , partmegabytes); +} +static void print_gpt_info (void ) {struct list_head *pos;struct disk_part *curr; +char partstartstr[16 ]; +char partsizestr[16 ];list_for_each (pos, &disk_partitions) { curr = list_entry(pos, struct disk_part, list); +prettyprint_part_size (partstartstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +prettyprint_part_size (partsizestr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +printf ("Partition %d:\n" , curr->partnum); -printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, - (unsigned )curr->gpt_part_info.size); +printf ("Start %s, size %s\n" , partstartstr, partsizestr);printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, curr->gpt_part_info.name); printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
@@ -212,6 +237,89 @@ static void print_gpt_info(void) } } +static int calc_parts_list_len (int numparts) +{ +/* +* prefatory string: +* doc/README.GPT, suggests that +* int partlistlen = UUID_STR_LEN + 1 + strlen("partitions=uuid_disk="); +* is correct, but extract_val() expects "uuid_disk" first. +*/ +int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" ); +/* for the comma */ + partlistlen++; + +/* per-partition additions; numparts starts at 1, so this should be correct */ + partlistlen += numparts * (strlen ("name=," ) +33 ); +/* 17 because partstr below is 16 chars */ + partlistlen += numparts * (strlen ("start=MiB," ) +17 ); + partlistlen += numparts * (strlen ("size=MiB," ) +17 ); + partlistlen += numparts * (strlen ("uuid=;" ) +UUID_STR_LEN +1 ); +/* for the terminating null */ + partlistlen ++; +debug ("Length of partitions_list is %d for %d partitions\n" , partlistlen, + numparts); +return partlistlen; +} + +/* +* create the string that upstream 'gpt write' command will accept as an +* argument +* +* From doc/README.gpt, Format of partitions layout: +* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* name=kernel,size=60MiB,uuid=...;" +* The fields 'name' and 'size' are mandatory for every partition. +* The field 'start' is optional. The fields 'uuid' and 'uuid_disk' +* are optional if CONFIG_RANDOM_UUID is enabled. +*/ +static int create_gpt_partitions_list (int numparts,const char *guid,char *partitions_list) +{ +struct list_head *pos; +struct disk_part *curr; +char partstr[16 ]; + +if (!partitions_list) +return -1 ; + +/* +* README.gpt specifies starting with "partitions=" like so: +* strcpy(partitions_list, "partitions=uuid_disk="); +* but that breaks extract_val, which doesn't skip over 'partitions='. +*/ +strcpy (partitions_list,"uuid_disk=" ); +strncat (partitions_list, guid,UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +strcat (partitions_list,"name=" ); +/* +* name is 32 chars long, per definition of disk_partition_t in part.h, +* plus one extra byte for NULL +*/ +strncat (partitions_list, (const char *)curr->gpt_part_info.name,33 ); + +strcat (partitions_list,",start=" ); +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +strncat (partitions_list, partstr,17 ); + +strcat (partitions_list,",size=" ); +/* lbaint_t is unsigned long, per include/ide.h */ +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +/* one extra byte for NULL */ +strncat (partitions_list, partstr,17 ); + +strcat (partitions_list,",uuid=" ); +strncat (partitions_list, (const char *)curr->gpt_part_info.uuid, +UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + } +return 0 ; +} +/* * read partition info into disk_partitions list where * it can be printed or modified
@@ -223,8 +331,11 @@ static int get_gpt_info(struct blk_desc *dev_desc)disk_partition_t info;struct disk_part *new_disk_part; -if (disk_partitions.next ==NULL ) -INIT_LIST_HEAD (&disk_partitions); +/* +* Always re-read partition info from device, in case +* it has changed +*/ +INIT_LIST_HEAD (&disk_partitions);for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { ret =part_get_info (dev_desc, p, &info);
@@ -241,7 +352,6 @@ static int get_gpt_info(struct blk_desc *dev_desc)if (!valid_parts) {printf ("** No valid partitions found **\n" );del_gpt_info (); -return -1 ; }return --valid_parts; }
@@ -295,10 +405,13 @@ static int set_gpt_info(struct blk_desc *dev_desc,return -1 ; str =strdup (str_part); +if (str ==NULL ) +return -ENOMEM ;/* extract disk guid */ s = str; val =extract_val (str,"uuid_disk" ); +if (!val) {#ifdef CONFIG_RANDOM_UUID *str_disk_guid =malloc (UUID_STR_LEN +1 );
@@ -312,6 +425,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,if (extract_env (val, &p)) p = val; *str_disk_guid =strdup (p); +free (val);/* Move s to first partition */ strsep (&s,";" );
@@ -524,6 +638,83 @@ static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)return 0 ; } +static int do_flip_gpt_parts (struct blk_desc *dev_desc) +{ +struct list_head *pos; +struct disk_part *curr; +disk_partition_t *new_partitions =NULL ; +char disk_guid[UUID_STR_LEN +1 ]; +char *partitions_list, *str_disk_guid; +u8 part_count =0 ; +int partlistlen, ret, numparts =0 ; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return ret; + + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; +printf ("Current partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + + partlistlen =calc_parts_list_len (numparts); + partitions_list = (char *)malloc (partlistlen); + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, + partitions_list); +if (ret <0 ) +return ret; +debug ("OLD partitions_list is %s with %d chars\n" , partitions_list,strlen (partitions_list)); + + ret =set_gpt_info (dev_desc, (const char *)partitions_list, &str_disk_guid, + &new_partitions, &part_count); +if (ret <0 ) +return ret; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +if (!strcmp ((char *)curr->gpt_part_info.name,"backup_kernel" )) +strcpy ((char *)curr->gpt_part_info.name,"candidate_kernel" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"primary_kernel" )) +strcpy ((char *)curr->gpt_part_info.name,"backup_kernel" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"backup_rootfs" )) +strcpy ((char *)curr->gpt_part_info.name,"candidate_rootfs" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"primary_rootfs" )) +strcpy ((char *)curr->gpt_part_info.name,"backup_rootfs" ); + } + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, partitions_list); +if (ret <0 ) +return ret; +debug ("NEW partitions_list is %s with %d chars\n" , partitions_list,strlen (partitions_list)); + + ret =set_gpt_info (dev_desc, (const char *)partitions_list, &str_disk_guid, + &new_partitions, &part_count); +if (ret <0 ) +return ret; + +debug ("Writing new partition table\n" ); + ret =gpt_restore (dev_desc, disk_guid, new_partitions, numparts); +if (ret <0 ) { +printf ("Writing new partition table failed\n" ); +return ret; + } + +debug ("Reading back new partition table\n" ); + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; +printf ("new partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + +del_gpt_info (); +free (partitions_list); +free (str_disk_guid); +free (new_partitions); +return ret; +} +/** * do_gpt(): Perform GPT operations *
@@ -567,6 +758,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return do_disk_guid (blk_dev_desc, varname); }else if (strcmp (argv[1 ],"read" ) ==0 ) {return do_get_gpt_info (blk_dev_desc); + }else if (strcmp (argv[1 ],"flip" ) ==0 ) { +return do_flip_gpt_parts (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -591,6 +784,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," gpt verify mmc 0 $partitions\n" " read <interface> <dev>\n" " - read GPT into a data structure for manipulation\n" +" flip <interface> <dev>\n" +" - exchange 'primary' and 'backup' partition names in GPT" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
Signature · 1 line
2.1.4
PATCH 3/3 rename GPT partitions to detect boot failure
Quoted 5 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
[snip]
Quoted 4 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 201 insertions(+), 6 deletions(-)
There's some whitespace-only chunks, please drop. Also:
[snip]
cmd/gpt.c line 25
Quoted 2 lines
cmd/gpt.c +2
-0+/* ONEMIB is 2**20 */ +#define ONEMIB 1024*1024
SZ_1MB from <linux/sizes.h>
Quoted 5 lines
+/*
+ * The number '33' comes from the '32' in the definition ofdisk_partition_t
+ * ininclude/part.h. That file has '37' rather thanUUID_STR_LEN+ 1, from
+ *include/uuid.h
+ */
Lets update include/part.h in a new patch earlier in the series, possibly as part of addressing the problems I mention with the previous patch. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170526/8de83231/attachment.sig>
PATCH 3/3 rename GPT partitions to detect boot failure
In reply to alison at peloton-tech.comQuoted 38 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it renames it failed’ and renames the ‘backup’ partition as ‘candidate’.Logic:
-- Partitions can go to ‘failed’ only from ‘candidate’ and only
via u-boot. Partitions can go to ‘backup’ only from ‘primary’ and vice-versa, only via Linux. Partitions go to ‘candidate’ from ‘primary’ or ‘backup’ only via u-boot. Only system update software will rename 'failed' partitions.Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 201 insertions(+), 6 deletions(-)cmd/gpt.c +0
-0
cmd/gpt.c line 26
Quoted 6 lines
cmd/gpt.c +2
-0@@ -21,6 +21,9 @@#include <memalign.h> #include <linux/compat.h> +/* ONEMIB is 2**20 */ +#define ONEMIB 1024*1024
'()' are missing around the expression!
But anyway, there is no need to reinvent the wheel, since SZ_1M exists in include/linux/sizes.h.
Quoted 83 lines
cmd/gpt.c +1
-0+static LIST_HEAD (disk_partitions);/**
cmd/gpt.c +36
-3@@ -114,7 +117,6 @@ static char *extract_val(const char *str, const char *key)break ; } } -free (strcopy);return new;@@ -158,6 +160,7 @@ static void del_gpt_info(void) {struct list_head *pos = &disk_partitions;struct disk_part *curr; +while (!list_empty (pos)) { curr = list_entry(pos->next, struct disk_part, list);list_del (pos->next);@@ -165,6 +168,11 @@ static void del_gpt_info(void) } } +/* +* The number '33' comes from the '32' in the definition of disk_partition_t +* in include/part.h. That file has '37' rather than UUID_STR_LEN + 1, from +* include/uuid.h +*/ static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) {struct disk_part *newpart;@@ -191,16 +199,33 @@ static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum)return newpart; } +static void prettyprint_part_size (char *sizestr,unsigned long partsize, +unsigned long blksize) +{ +unsigned long long partbytes; +unsigned long partmegabytes; + + partbytes = partsize * blksize; + partmegabytes =lldiv (partbytes,ONEMIB ); +snprintf (sizestr,16 ,"%luMiB" , partmegabytes); +} +static void print_gpt_info (void ) {struct list_head *pos;struct disk_part *curr; +char partstartstr[16 ]; +char partsizestr[16 ];list_for_each (pos, &disk_partitions) { curr = list_entry(pos, struct disk_part, list); +prettyprint_part_size (partstartstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +prettyprint_part_size (partsizestr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +printf ("Partition %d:\n" , curr->partnum); -printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, - (unsigned )curr->gpt_part_info.size); +printf ("Start %s, size %s\n" , partstartstr, partsizestr);printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, curr->gpt_part_info.name); printf("Type %s, bootable %d\n", curr->gpt_part_info.type,@@ -212,6 +237,89 @@ static void print_gpt_info(void) } } +static int calc_parts_list_len (int numparts) +{ +/* +* prefatory string: +* doc/README.GPT, suggests that +* int partlistlen = UUID_STR_LEN + 1 + strlen("partitions=uuid_disk="); +* is correct, but extract_val() expects "uuid_disk" first. +*/ +int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" ); +/* for the comma */ + partlistlen++;
cmd/gpt.c static void print_gpt_info(void) · line 260
Quoted 10 lines
cmd/gpt.c +9
-0+ +/* per-partition additions; numparts starts at 1, so this should be correct */ + partlistlen += numparts * (strlen ("name=," ) +33 ); +/* 17 because partstr below is 16 chars */ + partlistlen += numparts * (strlen ("start=MiB," ) +17 ); + partlistlen += numparts * (strlen ("size=MiB," ) +17 ); + partlistlen += numparts * (strlen ("uuid=;" ) +UUID_STR_LEN +1 ); +/* for the terminating null */ + partlistlen ++;
partlistlen++;
Quoted 33 lines
cmd/gpt.c +33
-0+debug ("Length of partitions_list is %d for %d partitions\n" , partlistlen, + numparts); +return partlistlen; +} + +/* +* create the string that upstream 'gpt write' command will accept as an +* argument +* +* From doc/README.gpt, Format of partitions layout: +* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* name=kernel,size=60MiB,uuid=...;" +* The fields 'name' and 'size' are mandatory for every partition. +* The field 'start' is optional. The fields 'uuid' and 'uuid_disk' +* are optional if CONFIG_RANDOM_UUID is enabled. +*/ +static int create_gpt_partitions_list (int numparts,const char *guid,char *partitions_list) +{ +struct list_head *pos; +struct disk_part *curr; +char partstr[16 ]; + +if (!partitions_list) +return -1 ; + +/* +* README.gpt specifies starting with "partitions=" like so: +* strcpy(partitions_list, "partitions=uuid_disk="); +* but that breaks extract_val, which doesn't skip over 'partitions='. +*/ +strcpy (partitions_list,"uuid_disk=" ); +strncat (partitions_list, guid,UUID_STR_LEN +1 ); +strcat (partitions_list,";" );
cmd/gpt.c static void print_gpt_info(void)
Quoted 10 lines
cmd/gpt.c +9
-0+ +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +strcat (partitions_list,"name=" ); +/* +* name is 32 chars long, per definition of disk_partition_t in part.h, +* plus one extra byte for NULL +*/ +strncat (partitions_list, (const char *)curr->gpt_part_info.name,33 );
unnecessary cast. The same holds for all the other (const char *) casts in this patch.
Quoted 85 lines
cmd/gpt.c +21
-0+ +strcat (partitions_list,",start=" ); +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +strncat (partitions_list, partstr,17 ); + +strcat (partitions_list,",size=" ); +/* lbaint_t is unsigned long, per include/ide.h */ +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +/* one extra byte for NULL */ +strncat (partitions_list, partstr,17 ); + +strcat (partitions_list,",uuid=" ); +strncat (partitions_list, (const char *)curr->gpt_part_info.uuid, +UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + } +return 0 ; +} +/* * read partition info into
disk_partitionslist where
* it can be printed or modifiedcmd/gpt.c +22
-3@@ -223,8 +331,11 @@ static int get_gpt_info(struct blk_desc *dev_desc)disk_partition_t info;struct disk_part *new_disk_part; -if (disk_partitions.next ==NULL ) -INIT_LIST_HEAD (&disk_partitions); +/* +* Always re-read partition info from device, in case +* it has changed +*/ +INIT_LIST_HEAD (&disk_partitions);for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { ret =part_get_info (dev_desc, p, &info);@@ -241,7 +352,6 @@ static int get_gpt_info(struct blk_desc *dev_desc)if (!valid_parts) {printf ("** No valid partitions found **\n" );del_gpt_info (); -return -1 ; }return --valid_parts; }@@ -295,10 +405,13 @@ static int set_gpt_info(struct blk_desc *dev_desc,return -1 ; str =strdup (str_part); +if (str ==NULL ) +return -ENOMEM ;/* extract disk guid */ s = str; val =extract_val (str,"uuid_disk" ); +if (!val) {#ifdef CONFIG_RANDOM_UUID *str_disk_guid =malloc (UUID_STR_LEN +1 );@@ -312,6 +425,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,if (extract_env (val, &p)) p = val; *str_disk_guid =strdup (p); +free (val);/* Move s to first partition */ strsep (&s,";" );@@ -524,6 +638,83 @@ static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)return 0 ; } +static int do_flip_gpt_parts (struct blk_desc *dev_desc) +{ +struct list_head *pos; +struct disk_part *curr; +disk_partition_t *new_partitions =NULL ; +char disk_guid[UUID_STR_LEN +1 ]; +char *partitions_list, *str_disk_guid; +u8 part_count =0 ; +int partlistlen, ret, numparts =0 ; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return ret;
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 663
Quoted 10 lines
cmd/gpt.c +9
-0+ + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; +printf ("Current partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + + partlistlen =calc_parts_list_len (numparts); + partitions_list = (char *)malloc (partlistlen);
Useless cast.
Lothar Waßmann
Signature · 31 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________ -- ___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________ -- ___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
cover add support for GPT partition name manipulation
In reply to alison at peloton-tech.comQuoted 24 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
One way for userspace and the bootloader to exchange information about dynamic image selection is via the storage device partition table, as described at
https://source.android.com/devices/tech/ota/ab_updates
The scheme described there relies on setting partitions' "boot" flag. When no partition on a device is bootable since the kernel and U-Boot are stored elsewhere, the name field in the GPT partition table offers another logical place to store information. These patches allow users to easily modify GPT partition names via bootscripts that can select different images based on a boot-failure counter, or when userspace installs a software update.
These patches have been tested on a TI DRA7xx-based SOM with U-Boot 2015.07. The storage device is an eMMC.
Alison Chaiken (3):
GPT: add accessor function for disk GUID
GPT: read partition table from device into a data structure rename GPT partitions to detect boot failure
Quoted 4 lines
cmd/gpt.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- disk/part_efi.c | 31 ++++++ include/part.h | 24 ++++ 3 files changed, 392 insertions(+), 2 deletions(-)
Interesting. Adding Lukasz for comments as well. I was thinking perhaps the final patch in the series might want to be guarded with some Kconfig option as it's rather specific to this update mechanism and probably causes a noticeable size increase due to the strings. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170526/8de5c53d/attachment.sig>
v2 cover add support for GPT partition name manipulation
From: Alison Chaiken <[email protected]>
One way for userspace and the bootloader to exchange information about dynamic image selection is via the storage device partition table, as described at
https://source.android.com/devices/tech/ota/ab_updates
The scheme described there relies on setting partitions' "boot" flag. When no partition on a device is bootable since the kernel and U-Boot are stored elsewhere, the name field in the GPT partition table offers another logical place to store information. These patches allow users to easily modify GPT partition names via bootscripts that can select different images based on a boot-failure counter, or when userspace installs a software update.
These patches have been tested on a TI DRA7xx-based SOM with U-Boot 2015.07. The storage device is an eMMC.
Significant changes since v1:
-- Put the gpt_flip() function and auxiliary ones inside a new
CONFIG_CMD_GPT_FLIP option that depends on CMD_GPT.
-- Replace intentional overwriting of name and type string arrays with
memset() instead.
-- Move part.h changes earlier in the patchset.
-- Add a few lines to README.gpt about the new gpt subcommands.
Added a few simple patches to do the following:
-- Replace remaining occurrences of '37' with UUID_STR_LEN+1; -- Introduce new macros to get rid of the similar '32'; -- fix a smaller error in doc/README.gpt.
There are also some fixups of whitespace and formatting errors (plus usual inevitable addition of new ones).
To do in future:
-- Add support for preserving the type flag for partitions. The u-boot
version on which this patchset is based did not have this feature, and it's easy to add, but I need to figure how to test it first.
Alison Chaiken (6):
EFI: replace number with UUID_STR_LEN macro
disk_partition: introduce macros for description string lengths
GPT: add accessor function for disk GUID
GPT: read partition table from device into a data structure rename GPT partitions to detect boot failure
GPT: fix error in partitions string doc
cmd/Kconfig | 7 ++ cmd/gpt.c | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- disk/part_efi.c | 33 +++++- doc/README.gpt | 24 ++++- include/part.h | 35 +++++- 5 files changed, 410 insertions(+), 11 deletions(-)
Signature · 1 line
2.1.4
PATCH v2 1/6 EFI: replace number with UUID_STR_LEN macro
From: Alison Chaiken <[email protected]>
--- disk/part_efi.c | 2 +- include/part.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-)
disk/part_efi.c +1 -1
@@ -183,7 +183,7 @@ void part_print_efi(struct blk_desc *dev_desc)ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);gpt_entry *gpt_pte =NULL ;int i =0 ; -char uuid[37 ]; +char uuid[UUID_STR_LEN +1 ];unsigned char *uuid_bin;/* This function validates AND fills in the GPT header and PTE */
include/part.h +3 -2
@@ -9,6 +9,7 @@#include <blk.h> #include <ide.h> +#include <uuid.h> struct block_drvr {char *name;
@@ -54,10 +55,10 @@ typedef struct disk_partition {uchar type[32 ];/* string type description */ int bootable;/* Active/Bootable flag is set */ #if CONFIG_IS_ENABLED (PARTITION_UUIDS ) -char uuid[37 ];/* filesystem UUID as string, if exists */ +char uuid[UUID_STR_LEN +1 ];/* filesystem UUID as string, if exists */ #endif #ifdef CONFIG_PARTITION_TYPE_GUID -char type_guid[37 ];/* type GUID as string, if exists */ +char type_guid[UUID_STR_LEN +1 ];/* type GUID as string, if exists */ #endif #ifdef CONFIG_DOS_PARTITION uchar sys_ind;/* partition type */
Signature · 1 line
2.1.4
PATCH v2 1/6 EFI: replace number with UUID_STR_LEN macro
Quoted 3 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
Signed-off-by Alison Chaiken <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170530/17d50781/attachment.sig>
PATCH v2 1/6 EFI: replace number with UUID_STR_LEN macro
In reply to alison at peloton-tech.comHi Alison,
Quoted 3 lines
From: Alison Chaiken <[email protected]>
Signed-off-by Alison Chaiken <[email protected]>
Quoted 46 lines
--- disk/part_efi.c | 2 +- include/part.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-)disk/part_efi.c +1
-1@@ -183,7 +183,7 @@ void part_print_efi(struct blk_desc *dev_desc)ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);gpt_entry *gpt_pte =NULL ;int i =0 ; -char uuid[37 ]; +char uuid[UUID_STR_LEN +1 ];unsigned char *uuid_bin;/* This function validates AND fills in the GPT header and PTE */ diff --git
a/include/part.hb/include/part.hindex 83bce05..6ace09f 100644include/part.h +1
-0@@ -9,6 +9,7 @@#include <blk.h> #include <ide.h> +#include <uuid.h> struct block_drvr {char *name;@@ -54,10 +55,10 @@ typedef struct disk_partition {uchar type[32 ];/* string type description */ int bootable; /*
Active/Bootable flag is set */ #ifCONFIG_IS_ENABLED(PARTITION_UUIDS)include/part.h +0
-1-char uuid[37 ];/* filesystem UUID as string, if exists */
include/part.h +1
-0+char uuid[UUID_STR_LEN +1 ];/* filesystem UUID as string, if exists */ #endif
#ifdefCONFIG_PARTITION_TYPE_GUIDinclude/part.h +0
-1-char type_guid[37 ];/* type GUID as string, if exists */
include/part.h +1
-0+char type_guid[UUID_STR_LEN +1 ];/* type GUID as string, if exists */ #endif
#ifdefCONFIG_DOS_PARTITION
ucharsys_ind; /* partition type
Quoted 1 line
*/
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 2/6 disk_partition: introduce macros for description string lengths
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
--- include/part.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
include/part.h +5 -2
@@ -47,12 +47,15 @@ struct block_drvr {#define DEV_TYPE_CDROM 0x05/* CD-ROM */ #define DEV_TYPE_OPDISK 0x07/* optical disk */ +#define PART_NAME_LEN 32 +#define PART_TYPE_LEN 32 + typedef struct disk_partition { lbaint_t start; /* # of first block in partition */ lbaint_t size; /* number of blocks in partition */ ulong blksz; /* block size in bytes */ - uchar name[32]; /* partition name */ - uchar type[32]; /* string type description */ + uchar name[PART_NAME_LEN]; /* partition name */ + uchar type[PART_TYPE_LEN]; /* string type description */ int bootable; /* Active/Bootable flag is set */ #if CONFIG_IS_ENABLED(PARTITION_UUIDS) char uuid[UUID_STR_LEN + 1]; /* filesystem UUID as string, if exists */
Signature · 1 line
2.1.4
PATCH v2 2/6 disk_partition: introduce macros for description string lengths
Hi Alison,
Quoted 30 lines
From: Alison Chaiken <[email protected]>
Signed-off-by Alison Chaiken <[email protected]>--- include/part.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)include/part.h +3
-0@@ -47,12 +47,15 @@ struct block_drvr {#define DEV_TYPE_CDROM 0x05/* CD-ROM */ #define DEV_TYPE_OPDISK 0x07/* optical disk */ +#define PART_NAME_LEN 32 +#define PART_TYPE_LEN 32 + typedef struct disk_partition { lbaint_t start; /* # of first block inpartition */
lbaint_tsize; /* number of blocks
in partition */ ulong blksz; /* block
size in bytes */include/part.h +0
-1-uchar name[32 ];/* partition name */
include/part.h +0
-1-uchar type[32 ];/* string type description */
include/part.h +1
-0+uchar name[PART_NAME_LEN ];/* partition name */
include/part.h +1
-0+uchar type[PART_TYPE_LEN ];/* string type
Quoted 4 lines
description */ int bootable; /*
Active/Bootable flag is set */ #ifCONFIG_IS_ENABLED(PARTITION_UUIDS)char uuid[UUID_STR_LEN +
1]; /* filesystem UUID as string, if exists */
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 2/6 disk_partition: introduce macros for description string lengths
In reply to alison at peloton-tech.comQuoted 3 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
Signed-off-by Alison Chaiken <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170531/f0de67f3/attachment.sig>
PATCH v2 3/6 GPT: add accessor function for disk GUID
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
--- cmd/gpt.c | 30 +++++++++++++++++++++++++++++- disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-)
cmd/gpt.c +29 -1
@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return 1 ; + +if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return 0 ; +} +/** * do_gpt(): Perform GPT operations *
@@ -412,7 +429,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {int ret =CMD_RET_SUCCESS ;int dev =0 ; -char *ep; +char *ep, *varname =NULL ;struct blk_desc *blk_dev_desc =NULL ;if (argc <4 || argc >5 )
@@ -436,6 +453,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +if (argc ==5 ) +strcpy (varname, argv[4 ]); +return do_disk_guid (blk_dev_desc, varname); }else {return CMD_RET_USAGE ; }
@@ -458,4 +479,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );
disk/part_efi.c +31 -0
@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)* Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +*/ +int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{ +ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz); +gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */ +if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); +if (is_gpt_valid (dev_desc, (dev_desc->lba -1 ), + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid Backup GPT ***\n" , + __func__); +return -1 ; + }else { +printf ("%s: *** Using Backup GPT ***\n" , + __func__); + } + } + + guid_bin = (unsigned char *)(gpt_head->disk_guid.b); +uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc) {ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);
doc/README.gpt +2 -1
@@ -171,7 +171,8 @@ To restore GUID partition table one needs to: The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set to - the generated UUID. + the generated UUID. The 'gpt guid' command reads the current value of the + uuid_disk from the GPT. The field 'bootable' is optional, it is used to mark the GPT partition bootable (set attribute flags "Legacy BIOS bootable").
include/part.h +15 -0
@@ -371,6 +371,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,int gpt_verify_partitions (struct blk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT +* +* This function reads the GUID string from a block device whose descriptor +* is provided. +* +* @param dev_desc - block device descriptor +* @param guid - pre-allocated string in which to return the GUID +* +* @return - '0' on success, otherwise error +*/ +int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Signature · 1 line
2.1.4
PATCH v2 3/6 GPT: add accessor function for disk GUID
Quoted 22 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 30 +++++++++++++++++++++++++++++- disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-)cmd/gpt.c +0
-0@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; }
cmd/gpt.c static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part) · line 409
Quoted 10 lines
cmd/gpt.c +9
-0+static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return 1 ; +
Since you are calling this function from a CMD handler and passing its return value as the CMD handlers exit code this should be:
return CMD_RET_FAILURE;
cmd/gpt.c static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)
Quoted 7 lines
cmd/gpt.c +6
-0+if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return 0 ;
... and this:
return CMD_RET_SUCCESS;
Quoted 13 lines
cmd/gpt.c +1
-1/** * do_gpt(): Perform GPT operations * @@ -412,7 +429,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {int ret =CMD_RET_SUCCESS ;int dev =0 ; -char *ep; +char *ep, *varname =NULL ;struct blk_desc *blk_dev_desc =NULL ;if (argc <4 || argc >5 )
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 459
Quoted 7 lines
cmd/gpt.c +3
-0@@ -436,6 +453,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +if (argc ==5 ) +strcpy (varname, argv[4 ]);
You didn't allocate any memory for varname and copy the argument string to a NULL pointer!
Maybe use strdup() and free varname after use?
Quoted 30 lines
cmd/gpt.c +1
-0+return do_disk_guid (blk_dev_desc, varname); }else {return CMD_RET_USAGE ;cmd/gpt.c +7
-0}@@ -458,4 +479,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );disk/part_efi.c +6
-0@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)* Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +*/ +int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{
disk/part_efi.c static void prepare_backup_gpt_header(gpt_header *gpt_h) · line 196
Quoted 10 lines
disk/part_efi.c +9
-0+ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz); +gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */ +if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); + if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
useless '()'
disk/part_efi.c static void prepare_backup_gpt_header(gpt_header *gpt_h) · line 199
Quoted 4 lines
disk/part_efi.c +4
-0+ gpt_head, &gpt_pte) != 1) { +printf ("%s: *** ERROR: Invalid Backup GPT ***\n" , + __func__); +return -1 ;
return -EINVAL;?
disk/part_efi.c static void prepare_backup_gpt_header(gpt_header *gpt_h)
Quoted 8 lines
disk/part_efi.c +7
-0+ }else { +printf ("%s: *** Using Backup GPT ***\n" , + __func__); + } + } + + guid_bin = (unsigned char *)(gpt_head->disk_guid.b);
disk_guid.b is of type u8 which is the same as unsigned char. No need for a type cast here (and the () around gpt_head->... are unnecessary).
Quoted 48 lines
disk/part_efi.c +5
-0+uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc){
disk/part_efi.c +0
-0ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);doc/README.gpt +2
-1@@ -171,7 +171,8 @@ To restore GUID partition table one needs to: The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set to - the generated UUID. + the generated UUID. The 'gpt guid' command reads the current value of the + uuid_disk from the GPT. The field 'bootable' is optional, it is used to mark the GPT partition bootable (set attribute flags "Legacy BIOS bootable").include/part.h +15
-0@@ -371,6 +371,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,int gpt_verify_partitions (struct blk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT +* +* This function reads the GUID string from a block device whose descriptor +* is provided. +* +* @param dev_desc - block device descriptor +* @param guid - pre-allocated string in which to return the GUID +* +* @return - '0' on success, otherwise error +*/ +int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Signature · 9 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
v3 cover add support for GPT partition name manipulation
From: Alison Chaiken <[email protected]>
One way for userspace and the bootloader to exchange information about dynamic image selection is via the storage device partition table, as described at
https://source.android.com/devices/tech/ota/ab_updates
The scheme described there relies on setting partitions' "boot" flag. When no partition on a device is bootable since the kernel and U-Boot are stored elsewhere, the name field in the GPT partition table offers another logical place to store information. These patches allow users to easily modify GPT partition names via bootscripts that can select different images based on a boot-failure counter, or when userspace installs a software update.
These patches have been (re)tested on a TI DRA7xx-based SOM with U-Boot 2015.07. The storage device is an eMMC.
Significant changes since v2:
-- Got rid of the need to allocate memory for the GUID string in
do_gpt();
-- Fixed the problems with string NULL termination in
allocate_disk_part();
-- Removed duplicate definition of MAX_SEARCH_PARTITIONS from
disk/part.c and increased the value in include/part.h to 64;
-- Improved the commit message for "rename GPT partitions to detect
boot failure" to better describe the version of the patch I submitted;
-- Fixed numerous small problems with function return values.
Significant changes since v1:
-- Put the gpt_flip() function and auxiliary ones inside a new
CONFIG_CMD_GPT_FLIP option that depends on CMD_GPT.
-- Replace intentional overwriting of name and type string arrays with
memset() instead.
-- Move part.h changes earlier in the patchset.
-- Add a few lines to README.gpt about the new gpt subcommands.
Added a few simple patches to do the following:
-- Replace remaining occurrences of '37' with UUID_STR_LEN+1; -- Introduce new macros to get rid of the similar '32'; -- fix a smaller error in doc/README.gpt.
There are also some fixups of whitespace and formatting errors (plus usual inevitable addition of new ones).
To do in future:
-- Add support for preserving the type flag for partitions. The u-boot
version on which this patchset is based did not have this feature, and it's easy to add, but I need to figure how to test it first.
-- Add tests for the new gpt commands to the sandbox.
Alison Chaiken (5):
GPT: add accessor function for disk GUID
partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
GPT: read partition table from device into a data structure rename GPT partitions to detect boot failure
GPT: fix error in partitions string doc
cmd/Kconfig | 7 ++ cmd/gpt.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ disk/part.c | 1 - disk/part_efi.c | 31 ++++++ doc/README.gpt | 24 ++++- include/part.h | 23 ++++ 6 files changed, 398 insertions(+), 6 deletions(-)
Signature · 1 line
2.1.4
PATCH v3 1/5 GPT: add accessor function for disk GUID
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
--- cmd/gpt.c | 26 ++++++++++++++++++++++++++ disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-)
cmd/gpt.c +26 -0
@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return CMD_RET_FAILURE ; + +if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return ret; +} +/** * do_gpt(): Perform GPT operations *
@@ -436,6 +453,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +return do_disk_guid (blk_dev_desc, argv[4 ]); }else {return CMD_RET_USAGE ; }
@@ -458,4 +477,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );
disk/part_efi.c +31 -0
@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)* Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +*/ +int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{ +ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz); +gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */ +if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); +if (is_gpt_valid (dev_desc, dev_desc->lba -1 , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid Backup GPT ***\n" , + __func__); +return -EINVAL ; + }else { +printf ("%s: *** Using Backup GPT ***\n" , + __func__); + } + } + + guid_bin = gpt_head->disk_guid.b; +uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc) {ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);
doc/README.gpt +2 -1
@@ -171,7 +171,8 @@ To restore GUID partition table one needs to: The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set to - the generated UUID. + the generated UUID. The 'gpt guid' command reads the current value of the + uuid_disk from the GPT. The field 'bootable' is optional, it is used to mark the GPT partition bootable (set attribute flags "Legacy BIOS bootable").
include/part.h +15 -0
@@ -371,6 +371,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,int gpt_verify_partitions (struct blk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT +* +* This function reads the GUID string from a block device whose descriptor +* is provided. +* +* @param dev_desc - block device descriptor +* @param guid - pre-allocated string in which to return the GUID +* +* @return - '0' on success, otherwise error +*/ +int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Signature · 1 line
2.1.4
PATCH v3 1/5 GPT: add accessor function for disk GUID
Hi,
Quoted 29 lines · On Fri, 2 Jun 2017 19:22:30 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 26 ++++++++++++++++++++++++++ disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-)cmd/gpt.c +6
-0@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid);
cmd/gpt.c static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part) · line 416
Quoted 10 lines
cmd/gpt.c +9
-0+if (ret <0 ) +return CMD_RET_FAILURE ; + +if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return ret;
For consistency this should be:
return CMD_RET_SUCCESS;
but see below.
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 460
Quoted 12 lines
cmd/gpt.c +2
-0/** * do_gpt(): Perform GPT operations * @@ -436,6 +453,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +return do_disk_guid (blk_dev_desc, argv[4 ]); }else {return CMD_RET_USAGE ; }
IMO you should use the existing error handling infrastructure lateron in this file and just assign the return value of the subcommand handlers to 'ret' and let the existing code sort out the return code of this function (just like the gpt_verify() call above does it).
Lothar Waßmann
PATCH v5 1/3 GPT: add accessor function for disk GUID
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Changes since v4:
-- Made do_disk_guid() return 0 upon success so that now, in the
sandbox, u-boot prints a "success!" exit message.
--- cmd/gpt.c | 26 ++++++++++++++++++++++++++ disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-)
cmd/gpt.c +26 -0
@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return CMD_RET_FAILURE ; + +if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return ret; +} +/** * do_gpt(): Perform GPT operations *
@@ -436,6 +453,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { + ret =do_disk_guid (blk_dev_desc, argv[4 ]); }else {return CMD_RET_USAGE ; }
@@ -458,4 +477,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );
disk/part_efi.c +31 -0
@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)* Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +*/ +int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{ +ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz); +gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */ +if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); +if (is_gpt_valid (dev_desc, dev_desc->lba -1 , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid Backup GPT ***\n" , + __func__); +return -EINVAL ; + }else { +printf ("%s: *** Using Backup GPT ***\n" , + __func__); + } + } + + guid_bin = gpt_head->disk_guid.b; +uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc) {ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);
doc/README.gpt +2 -1
@@ -171,7 +171,8 @@ To restore GUID partition table one needs to: The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set to - the generated UUID. + the generated UUID. The 'gpt guid' command reads the current value of the + uuid_disk from the GPT. The field 'bootable' is optional, it is used to mark the GPT partition bootable (set attribute flags "Legacy BIOS bootable").
include/part.h +15 -0
@@ -371,6 +371,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,int gpt_verify_partitions (struct blk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT +* +* This function reads the GUID string from a block device whose descriptor +* is provided. +* +* @param dev_desc - block device descriptor +* @param guid - pre-allocated string in which to return the GUID +* +* @return - '0' on success, otherwise error +*/ +int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Signature · 1 line
2.1.4
PATCH v5 1/3 GPT: add accessor function for disk GUID
Quoted 7 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Quoted 5 lines
Changes since v4:
-- Madedo_disk_guid()return 0 upon success so that now, in the
sandbox, u-boot prints a "success!" exit message.Signed-off-by Alison Chaiken <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170611/67a2326e/attachment.sig>
PATCH v3 2/5 partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Move MAX_SEARCH_PARTITIONS to part.h so that functions in cmd directory can find it. At the same time, increase the value to 64 since some operating systems use many, and the resources consumed by a larger value are minimal.
--- disk/part.c | 1 - include/part.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
disk/part.c +0 -1
@@ -388,7 +388,6 @@ cleanup:#define PART_UNSPECIFIED -2#define PART_AUTO -1 -#define MAX_SEARCH_PARTITIONS 16int blk_get_device_part_str (const char *ifname,const char *dev_part_str,struct blk_desc **dev_desc,disk_partition_t *info,int allow_whole_dev)
include/part.h +1 -0
@@ -49,6 +49,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 64 typedef struct disk_partition { lbaint_t start; /* # of first block in partition */
Signature · 1 line
2.1.4
PATCH v3 2/5 partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
Hi Alison,
Quoted 37 lines
From: Alison Chaiken <[email protected]>
Move
MAX_SEARCH_PARTITIONStopart.hso that functions in cmd directory can find it. At the same time, increase the value to 64 since some operating systems use many, and the resources consumed by a larger value are minimal.Signed-off-by Alison Chaiken <[email protected]>--- disk/part.c | 1 - include/part.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)disk/part.c +0
-1@@ -388,7 +388,6 @@ cleanup:#define PART_UNSPECIFIED -2#define PART_AUTO -1 -#define MAX_SEARCH_PARTITIONS 16int blk_get_device_part_str (const char *ifname,const char *dev_part_str,struct blk_desc **dev_desc, disk_partition_t *info, int
allow_whole_dev) diff --gita/include/part.hb/include/part.hindex 16c4a46..c41aa6a 100644include/part.h +1
-0@@ -49,6 +49,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 64 typedef struct disk_partition { lbaint_t start; /* # of first block in
Quoted 1 line
partition */
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v3 3/5 GPT: read partition table from device into a data structure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
--- cmd/gpt.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 119 insertions(+)
cmd/gpt.c +112 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && valid_parts >=2 ) +return -ENODEV ; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -455,6 +563,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("Verify GPT: " ); }else if (strcmp (argv[1 ],"guid" ) ==0 ) {return do_disk_guid (blk_dev_desc, argv[4 ]); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -477,6 +587,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +7 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH v3 3/5 GPT: read partition table from device into a data structure
Hi,
Quoted 100 lines · On Fri, 2 Jun 2017 19:22:32 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 119 insertions(+)cmd/gpt.c +73
-0@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}' @@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions);
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 236
Quoted 10 lines
cmd/gpt.c +9
-0+ +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && valid_parts >=2 ) +return -ENODEV ;
del_gpt_info()? This calls for a common error exit which does the cleanup.
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 247
Quoted 12 lines
cmd/gpt.c +12
-0+ +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} +
Lothar Waßmann
PATCH v5 2/3 GPT: read partition table from device into a data structure
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
Changes since v4:
-- Made do_get_gpt_info() return 0 upon success so that now, in the
sandbox, u-boot prints a "success!" exit message.
-- Created a single exit point for get_gpt_info(), with the
result that after an error, del_gpt_info() always removes the list.
--- cmd/gpt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 127 insertions(+)
cmd/gpt.c +120 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,119 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name, +PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type, +PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +/* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ + newpart->gpt_part_info.uuid[UUID_STR_LEN ] ='\0' ; +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part)) + goto out; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); + goto out; + } +return --valid_parts; + out: +if (valid_parts >=2 ) +del_gpt_info (); +return -ENODEV ; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); +return 0 ; + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -455,6 +571,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("Verify GPT: " ); }else if (strcmp (argv[1 ],"guid" ) ==0 ) { ret =do_disk_guid (blk_dev_desc, argv[4 ]); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { + ret =do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -477,6 +595,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +7 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH v5 2/3 GPT: read partition table from device into a data structure
Quoted 6 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
Quoted 8 lines
Changes since v4:
-- Madedo_get_gpt_info()return 0 upon success so that now, in the
sandbox, u-boot prints a "success!" exit message.
-- Created a single exit point forget_gpt_info(), with the
result that after an error,del_gpt_info()always removes the list.Signed-off-by Alison Chaiken <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170611/99ef27ba/attachment.sig>
PATCH v3 3/5 GPT: read partition table from device into a data structure
In reply to alison at peloton-tech.comHi,
Quoted 139 lines · On Fri, 2 Jun 2017 19:22:32 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 119 insertions(+)cmd/gpt.c +108
-0@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}' @@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && valid_parts >=2 ) +return -ENODEV ; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 568
Quoted 6 lines
cmd/gpt.c +2
-0@@ -455,6 +563,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("Verify GPT: " ); }else if (strcmp (argv[1 ],"guid" ) ==0 ) {return do_disk_guid (blk_dev_desc, argv[4 ]); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc);
See my comment to your patch 1/5
Quoted 28 lines
cmd/gpt.c +0
-0}else {return CMD_RET_USAGE ;cmd/gpt.c +2
-0}@@ -477,6 +587,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n" include/part.h +1
-0@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t;
include/part.h typedef struct disk_partition { · line 81
Quoted 10 lines
include/part.h +6
-0+struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Lothar Waßmann
PATCH v3 4/5 rename GPT partitions to detect boot failure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it tries to boot the ‘backup’ partition.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
--- cmd/Kconfig | 7 ++ cmd/gpt.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 13 ++++ 3 files changed, 215 insertions(+), 4 deletions(-)
cmd/Kconfig +7 -0
@@ -593,6 +593,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +195 -4
253 lines not on this page · raw message
doc/README.gpt +13 -0
@@ -210,6 +210,19 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read' and 'gpt flip' commands facilitate programmatic renaming of +partitions from bootscripts by generating and modifying the partitions +layout string. The code in gpt_flip() illustrates the case of +swapping 'primary' and 'backup' partitions via: + +U-BOOT> gpt flip mmc 0 + +Choose different partition names by modifying these strings in gpt.c. Partition type GUID: ====================
Signature · 1 line
2.1.4
PATCH v3 4/5 rename GPT partitions to detect boot failure
Hi,
Quoted 104 lines · On Fri, 2 Jun 2017 19:22:33 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it tries to boot the ‘backup’ partition.Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Signed-off-by Alison Chaiken <[email protected]>--- cmd/Kconfig | 7 ++ cmd/gpt.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 13 ++++ 3 files changed, 215 insertions(+), 4 deletions(-)cmd/Kconfig +7
-0@@ -593,6 +593,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"cmd/gpt.c +27
-2@@ -20,6 +20,7 @@#include <div64.h> #include <memalign.h> #include <linux/compat.h> +#include <linux/sizes.h> static LIST_HEAD (disk_partitions);@@ -190,16 +191,33 @@ static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum)return newpart; } +static void prettyprint_part_size (char *sizestr,unsigned long partsize, +unsigned long blksize) +{ +unsigned long long partbytes; +unsigned long partmegabytes; + + partbytes = partsize * blksize; + partmegabytes =lldiv (partbytes,SZ_1M ); +snprintf (sizestr,16 ,"%luMiB" , partmegabytes); +} +static void print_gpt_info (void ) {struct list_head *pos;struct disk_part *curr; +char partstartstr[16 ]; +char partsizestr[16 ];list_for_each (pos, &disk_partitions) { curr = list_entry(pos, struct disk_part, list); +prettyprint_part_size (partstartstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +prettyprint_part_size (partsizestr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +printf ("Partition %d:\n" , curr->partnum); -printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, - (unsigned )curr->gpt_part_info.size); +printf ("Start %s, size %s\n" , partstartstr, partsizestr);printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, curr->gpt_part_info.name); printf("Type %s, bootable %d\n", curr->gpt_part_info.type,@@ -211,6 +229,85 @@ static void print_gpt_info(void) } } +#ifdef CONFIG_CMD_GPT_FLIP +static int calc_parts_list_len (int numparts) +{ +/* +* prefatory string: +* doc/README.GPT, suggests that +* int partlistlen = UUID_STR_LEN + 1 + strlen("partitions=uuid_disk=");
cmd/gpt.c static void print_gpt_info(void) · line 248
Quoted 10 lines
cmd/gpt.c +9
-0+* is correct, but extract_val() expects "uuid_disk" first. +*/ +int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" ); +/* for the comma */ + partlistlen++; + +/* per-partition additions; numparts starts at 1, so this should be correct */ + partlistlen += numparts * (strlen ("name=," ) +PART_NAME_LEN +1 ); +/* 17 because partstr in create_gpt_partitions_list() is 16 chars */
NO! The size of partstr in create_gpt_partitions_list() is:
| char partstr[PART_NAME_LEN + 1];
which happens to be defined as:
include/part.h +0 -0
@@ -49,6 +49,7 @@ struct block_drvr {#define PART_NAME_LEN 32 ^^#define PART_TYPE_LEN 32
cmd/gpt.c static void print_gpt_info(void) · line 251
Quoted 3 lines
cmd/gpt.c +2
-0+ partlistlen += numparts * (strlen ("start=MiB," ) +17 ); + partlistlen += numparts * (strlen ("size=MiB," ) +17 );
Never use magic numbers in code, but use appropriate #define's!
Quoted 8 lines
cmd/gpt.c +4
-0@@ -523,6 +625,86 @@ static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)return ret; } +#ifdef CONFIG_CMD_GPT_FLIP +static int do_flip_gpt_parts (struct blk_desc *dev_desc) +{ +struct list_head *pos;
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 641
Quoted 10 lines
cmd/gpt.c +10
-0+struct disk_part *curr; +disk_partition_t *new_partitions =NULL ; +char disk_guid[UUID_STR_LEN +1 ]; +char *partitions_list, *str_disk_guid; +u8 part_count =0 ; +int partlistlen, ret, numparts =0 ; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return ret;
AGAIN: You are passing the return value of this function back to the caller of the CMD handler do_gpt() which expects a return value of CMD_RET_FAILURE or CMD_RET_SUCCESS, not an arbitrary negative value.
Quoted 70 lines
cmd/gpt.c +66
-0+ + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; +printf ("Current partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + + partlistlen =calc_parts_list_len (numparts); + partitions_list = (char *)malloc (partlistlen); +memset (partitions_list,'\0' , partlistlen); + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, + partitions_list); +if (ret <0 ) +return ret; +debug ("OLD partitions_list is %s with %d chars\n" , partitions_list,strlen (partitions_list)); + + ret =set_gpt_info (dev_desc, (const char *)partitions_list, &str_disk_guid, + &new_partitions, &part_count); +if (ret <0 ) +return ret; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +if (!strcmp ((char *)curr->gpt_part_info.name,"backup_kernel" )) +strcpy ((char *)curr->gpt_part_info.name,"candidate_kernel" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"primary_kernel" )) +strcpy ((char *)curr->gpt_part_info.name,"backup_kernel" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"backup_rootfs" )) +strcpy ((char *)curr->gpt_part_info.name,"candidate_rootfs" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"primary_rootfs" )) +strcpy ((char *)curr->gpt_part_info.name,"backup_rootfs" ); + } + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, partitions_list); +if (ret <0 ) +return ret; +debug ("NEW partitions_list is %s with %d chars\n" , partitions_list,strlen (partitions_list)); + + ret =set_gpt_info (dev_desc, (const char *)partitions_list, &str_disk_guid, + &new_partitions, &part_count); +if (ret <0 ) +return ret; + +debug ("Writing new partition table\n" ); + ret =gpt_restore (dev_desc, disk_guid, new_partitions, numparts); +if (ret <0 ) { +printf ("Writing new partition table failed\n" ); +return ret; + } + +debug ("Reading back new partition table\n" ); + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; +printf ("new partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + +del_gpt_info (); +free (partitions_list); +free (str_disk_guid); +free (new_partitions); + return ret; +} +#endif +/** * do_gpt(): Perform GPT operations *
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 754
Quoted 8 lines
cmd/gpt.c +4
-0@@ -565,6 +747,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return do_disk_guid (blk_dev_desc, argv[4 ]); }else if (strcmp (argv[1 ],"read" ) ==0 ) {return do_get_gpt_info (blk_dev_desc); +#ifdef CONFIG_CMD_GPT_FLIP + }else if (strcmp (argv[1 ],"flip" ) ==0 ) { +return do_flip_gpt_parts (blk_dev_desc); +#endif
See my comment to your patch 1/5.
Lothar Waßmann
PATCH v5 3/3 rename GPT partitions to detect boot failure
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it tries to boot the ‘backup’ partition.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
Changes since v4:
-- Changed the erroneous '17' values in calc_parts_list_len() to
match the definition of struct disk_partition in part.h.
-- Modified do_gpt() so that the 'gpt flip' command prints
"success!" or "error!" on exit.
--- cmd/Kconfig | 7 +++ cmd/gpt.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 13 ++++ 3 files changed, 206 insertions(+), 4 deletions(-)
cmd/Kconfig +7 -0
@@ -593,6 +593,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +186 -4
244 lines not on this page · raw message
doc/README.gpt +13 -0
@@ -210,6 +210,19 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read' and 'gpt flip' commands facilitate programmatic renaming of +partitions from bootscripts by generating and modifying the partitions +layout string. The code in gpt_flip() illustrates the case of +swapping 'primary' and 'backup' partitions via: + +U-BOOT> gpt flip mmc 0 + +Choose different partition names by modifying these strings in gpt.c. Partition type GUID: ====================
Signature · 1 line
2.1.4
PATCH v5 3/3 rename GPT partitions to detect boot failure
Dear Alison,
Quoted 5 lines · In message <[email protected]> you…
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
Quoted 8 lines
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it tries to boot the ‘backup’ partition.
I think you are talking about two parts here, and I strongly feel these should be kept separate.
The first part is support for renaming GPT partitions. The idea is clean, but should it not rather be kept general and let the user provide the new name as argument, i. e. implement a generic "gpt rename" command instead of a hard-wired "gpt flip"?
The second part is the flipping of the partition names. This is in my opinion policy, and should also not be hardwaired into this command, but left to the user. Maybe I do nmot want to fall back to the ‘backup’ partition after a single boot attempt, but instead try other things first, like booting another kernel or another device tree blob?
I feel this should be not so much hardwired, but leave more freedom for the user's creativity.
What do you think?
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de ...computer hardware progress is so fast. No other technology since civilization began has seen six orders of magnitude in performance- price gain in 30 years. - Fred Brooks, Jr.
PATCH v5 3/3 rename GPT partitions to detect boot failure
Quoted 15 lines · Wolfgang Denk
I think you are talking about two parts here, and I strongly feel these should be kept separate.
The first part is support for renaming GPT partitions. The idea is clean, but should it not rather be kept general and let the user provide the new name as argument, i. e. implement a generic "gpt rename" command instead of a hard-wired "gpt flip"?
The second part is the flipping of the partition names. This is in my opinion policy, and should also not be hardwaired into this command, but left to the user. Maybe I do nmot want to fall back to the ‘backup’ partition after a single boot attempt, but instead try other things first, like booting another kernel or another device tree blob?
Quoted 3 lines
I feel this should be not so much hardwired, but leave more freedom for the user's creativity.
Lukasz has already made similar suggestions. In the following message is
a new version which attempts to implement them.
Thanks to Lothar and Lukasz for all their help.
Best wishes,
Alison Chaiken
Peloton Technology
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
In reply to Wolfgang DenkFrom: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode prints a warning if no matching partition names are found. If only one matching name of a provided pair is found, it renames the matching partitions to the new name.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
Changes since v5:
-- The former 'gpt flip' is now 'gpt swap', which takes the two
arbitrary partition names it exchanges as command-line input.
-- A new command, 'gpt rename', now allows renaming of single,
specified partitions.
-- Updated README.gpt to reflect the changes.
--- cmd/Kconfig | 8 ++ cmd/gpt.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 20 ++++- 3 files changed, 261 insertions(+), 6 deletions(-)
cmd/Kconfig +8 -0
@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +234 -5
299 lines not on this page · raw message
doc/README.gpt +19 -1
@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Signature · 1 line
2.1.4
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Quoted 9 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode prints a warning if no matching partition names are found. If only one matching name of a provided pair is found, it renames the matching partitions to the new name.
So in the case where 'gpt swap partA partB' is used and partB doesn't exist, it's the same as 'gpt rename partA partB' ? That seems like it might surprise users and I think if we changed:
Quoted 11 lines
cmd/gpt.c +11
-0+if (!strcmp (subcomm,"swap" )) { +if ((strlen (name1) >PART_NAME_LEN ) || (strlen (name2) >PART_NAME_LEN )) { +printf ("Names longer than %d characters are truncated.\n" ,PART_NAME_LEN ); +return -EINVAL ; + } +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +if (!strcmp ((char *)curr->gpt_part_info.name, name1)) { +strcpy ((char *)curr->gpt_part_info.name, name2); + changed++; + }
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 687
Quoted 10 lines
cmd/gpt.c +10
-0+else if (!strcmp ((char *)curr->gpt_part_info.name, name2)) { +strcpy ((char *)curr->gpt_part_info.name, name1); + changed++; + } + + } +if (changed ==0 ) { +printf ("No matching partition names were found.\n" ); +return ret; + }
We could also test for if changed == 1 and return an error. I assume that a GPT with the same name used more than one time is already invalid, but we could be defensive here and test for != 2 instead. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170611/fefff049/attachment.sig>
PATCH v7 1/1 GPT: provide commands to selectively rename partitions
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
--- cmd/Kconfig | 8 ++ cmd/gpt.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 20 ++++- 3 files changed, 258 insertions(+), 6 deletions(-)
cmd/Kconfig +8 -0
@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +231 -5
296 lines not on this page · raw message
doc/README.gpt +19 -1
@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Signature · 1 line
2.1.4
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
In reply to alison at peloton-tech.comDear Alison,
Quoted 4 lines · In message <[email protected]> you wrote:
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
Thanks.
One question: can multiple GPT partitions have the same name?
Quoted 3 lines
The 'swap' mode prints a warning if no matching partition names are found. If only one matching name of a provided pair is found, it renames the matching partitions to the new name.
I see a problem here...
Quoted 11 lines
cmd/gpt.c +11
-0+if (!strcmp (subcomm,"swap" )) { +if ((strlen (name1) >PART_NAME_LEN ) || (strlen (name2) >PART_NAME_LEN )) { +printf ("Names longer than %d characters are truncated.\n" ,PART_NAME_LEN ); +return -EINVAL ; + } +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +if (!strcmp ((char *)curr->gpt_part_info.name, name1)) { +strcpy ((char *)curr->gpt_part_info.name, name2); + changed++; + }
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 687
Quoted 10 lines
cmd/gpt.c +10
-0+else if (!strcmp ((char *)curr->gpt_part_info.name, name2)) { +strcpy ((char *)curr->gpt_part_info.name, name1); + changed++; + } + + } +if (changed ==0 ) { +printf ("No matching partition names were found.\n" ); +return ret; + }
You will never know if there really was a pair of names that was swapped. Just a single rename of name1->name2 _or_ of name2->name1 will make the user think everything was fine.
[Note: I'm in the process of relocating and will be offline for the next 2..3. days. Don't expect more comments from mee soon. Sorry...]
Best regards,
Wolfgang Denk
Signature · 7 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de "I dislike companies that have a we-are-the-high-priests-of-hardware- so-you'll-like-what-we-give-you attitude. I like commodity markets in which iron-and-silicon hawkers know that they exist to provide fast toys for software types like me to play with..." - Eric S. Raymond
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Quoted 5 lines · Wolfgang Denk
Dear Alison,
In message <[email protected]> you
Quoted 1 line · wrote:
Quoted 8 lines
Quoted 3 lines
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
Thanks.
One question: can multiple GPT partitions have the same name?
The idea behind the 'swap' mode is that a storage device can have two sets of partitions, one set all named 'primary' and one set all named 'backup'.
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of being interrupted.
Quoted 32 lines
Quoted 4 lines
The 'swap' mode prints a warning if no matching partition names are found. If only one matching name of a provided pair is found, it renames the matching partitions to the new name.
I see a problem here...
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!strcmp(subcomm, "swap")) { + if ((strlen(name1) > PART_NAME_LEN) || (strlen(name2) >
PART_NAME_LEN)) {Quoted 1 line
+ printf("Names longer than %d characters are
truncated.\n",
PART_NAME_LEN);cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 5 lines
cmd/gpt.c +5
-0+return -EINVAL ; + } + list_for_each(pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); + if (!strcmp((char *)curr->gpt_part_info.name,name1)) {
Quoted 1 line
+ strcpy((char *)curr->gpt_part_info.name,
name2);
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 3 lines
cmd/gpt.c +3
-0+ changed++; + } + else if (!strcmp((char *)curr->gpt_part_info.name,name2)) {
Quoted 1 line
+ strcpy((char *)curr->gpt_part_info.name,
name1);
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 6 lines
cmd/gpt.c +6
-0+ changed++; + } + + } +if (changed ==0 ) { + printf("No matching partition names were
Quoted 8 lines
found.\n");
Review
Quoted 2 lines
(quoted diff) +2
-0+ return ret; + }You will never know if there really was a pair of names that was swapped. Just a single rename of
name1->name2_or_ ofname2->name1will make the user think everything was fine.
Point taken. The last version I posted has two counters instead of just
changed in order to address this problem.
Quoted 5 lines
[Note: I'm in the process of relocating and will be offline for the next 2..3. days. Don't expect more comments from mee soon. Sorry...]
Best regards,
Wolfgang Denk
One additional note: the last version I posted worked fine for the sandbox, but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't find atoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied in simple_atoi() fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyone have
a better idea to solve this problem?
Thanks,
Alison Chaiken
Peloton Technology
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Quoted 13 lines · Alison Chaiken
Quoted 11 lines · Wolfgang Denk
Dear Alison,
In message <[email protected]> you
Quoted 4 lines · wrote:
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
Thanks.
Quoted 8 lines
Quoted 1 line
One question: can multiple GPT partitions have the same name?
The idea behind the 'swap' mode is that a storage device can have two sets of partitions, one set all named 'primary' and one set all named 'backup'. The software updater in userspace can then simply rename
the partitions with sgdisk in order to pick the new image. The swap
mode changes the whole set of labels at once, so there's little chance of being interrupted.
I'm a little confused here now then. Can you provide an example set of usage, in the cover letter for v8 of the series (see below) that makes it a bit clearer? Thanks!
Quoted 53 lines
Quoted 31 lines
Quoted 3 lines
The 'swap' mode prints a warning if no matching partition names are found. If only one matching name of a provided pair is found, it renames the matching partitions to the new name.
I see a problem here...
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!strcmp(subcomm, "swap")) { + if ((strlen(name1) > PART_NAME_LEN) || (strlen(name2) >
PART_NAME_LEN)) {Quoted 1 line
+ printf("Names longer than %d characters are
truncated.\n",
PART_NAME_LEN);cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 5 lines
cmd/gpt.c +5
-0+return -EINVAL ; + } + list_for_each(pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); + if (!strcmp((char *)curr->gpt_part_info.name,name1)) {
Quoted 1 line
+ strcpy((char *)curr->gpt_part_info.name,
name2);
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 3 lines
cmd/gpt.c +3
-0+ changed++; + } + else if (!strcmp((char *)curr->gpt_part_info.name,name2)) {
Quoted 1 line
+ strcpy((char *)curr->gpt_part_info.name,
name1);
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 6 lines
cmd/gpt.c +6
-0+ changed++; + } + + } +if (changed ==0 ) { + printf("No matching partition names wereQuoted 8 lines
found.\n");
Review
Quoted 2 lines
(quoted diff) +2
-0+ return ret; + }You will never know if there really was a pair of names that was swapped. Just a single rename of
name1->name2_or_ ofname2->name1will make the user think everything was fine.Point taken. The last version I posted has two counters instead of just
changed in order to address this problem.Quoted 5 lines
[Note: I'm in the process of relocating and will be offline for the next 2..3. days. Don't expect more comments from mee soon. Sorry...]
Best regards,
Wolfgang Denk
Quoted 6 lines
One additional note: the last version I posted worked fine for the sandbox, but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyone have
a better idea to solve this problem?
Looking at the man page for atoi:
The atoi() function converts the initial portion of the string pointed to by nptr to int. The behavior is the same as
strtol(nptr, NULL, 10);
So we should just re-work to use simple_strtol here. And since you brought it up on IRC, I suppose at this point a 'clean' posting of all 5 patches marked as 'v8' might make it easier to see what's what and in what order. Thanks again!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170612/a0d7e5bc/attachment.sig>
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Dear Tom,
Quoted 11 lines · In message <20170612145646.GY10782@bill-the-cat> you wrote:
Looking at the man page for atoi:
Theatoi()function converts the initial portion of the string pointed to by nptr to int. The behavior is the same asstrtol(nptr, NULL, 10);So we should just re-work to use
simple_strtolhere. And since you brought it up on IRC, I suppose at this point a 'clean' posting of all 5 patches marked as 'v8' might make it easier to see what's what and in what order. Thanks again!
Hm... the claim that the behaviour is the _same_ is not strictly correct.
atoi() returns "int", while strtol() returns "long int"...
Anyway, you are right that atoi() is not being used anywhere in active U-Boot code.
Best regards,
Wolfgang Denk
Signature · 4 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de C++ is the best example of second-system effect since OS/360.
v7 cover add support for GPT partition name manipulation
From: Alison Chaiken <[email protected]>
Here is a resubmission of the 9-part patch series, the first 8 of which have already been marked 'applied', 'reviewed', or 'ack'ed' by Lukasz Majewski, Simon Glass or Tom Rini. I'm reposting them all as a set at Tom Rini's suggestion. Those earlier patches are listed here:
GPT: read partition table from device into a data structure
GPT: add accessor function for disk GUID
partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
cmd gpt: test in sandbox
Applied to u-boot-dm by Simon Glass, Jun 15 in <CAPnjgZ0G6QADVFLC0mExQN3HXhLXbgE4neBEtmWAg0YZu-=aNg@mail.gmail.com>
sandbox: README: fix partition command invocation
GPT: fix error in partitions string doc
Ack'ed by Lukasz Majewski, May 31, in <0170531132155.33a558e7@jawa>
disk_partition: introduce macros for description string lengths
EFI: replace number with UUID_STR_LEN macro
Changes since last version to the last patch in the series:
-- Removed several casts in create_gpt_partitions_list() and
do_rename_gpt_parts() as suggested by Lothar Waßmann. The cast of gpt_part_info.name to char* is needed to silence a compiler warning.
-- Substituted simple_strtol() for atoi() in do_gpt_rename_parts() as
suggested by Tom Rini and Wolfgang Denk.
-- Fixed bug in do_rename_gpt_parts() where 0 was returned as a valid
number of partitions with which to continue.
-- Added a comment to do_rename_gpt_parts() noting that the debug()
string it optionally prints is useful as input to the pre-existing 'gpt write' and 'gpt verify' commands.
-- Changed some -1 return values to -ENODEV and -EINVAL as suggested
by Tom Rini.
Changes to penultimate patch:
-- Removed a cast in allocate_disk_part() as suggested by Lothar.
Remaining tasks planned for future patches:
-- Create tests for GPT functionality as suggested by Lukasz.
-- Improve support for CONFIG_RANDOM_UUID.
-- Preserve partition type info when rewriting GPT.
Alison Chaiken (9):
EFI: replace number with UUID_STR_LEN macro
disk_partition: introduce macros for description string lengths
GPT: fix error in partitions string doc
sandbox: README: fix partition command invocation
cmd gpt: test in sandbox
partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
GPT: add accessor function for disk GUID
GPT: read partition table from device into a data structure
GPT: provide commands to selectively rename partitions
board/sandbox/README.sandbox | 2 +- cmd/Kconfig | 8 + cmd/gpt.c | 376 ++++++++++++++++++++++++++++++++++++++++++- disk/part.c | 1 - disk/part_efi.c | 33 +++- doc/README.gpt | 39 ++++- include/part.h | 35 +++- 7 files changed, 481 insertions(+), 13 deletions(-)
Signature · 1 line
2.1.4
PATCH v7 1/9 EFI: replace number with UUID_STR_LEN macro
From: Alison Chaiken <[email protected]>
Changes since v6: none.
--- disk/part_efi.c | 2 +- include/part.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-)
disk/part_efi.c +1 -1
@@ -183,7 +183,7 @@ void part_print_efi(struct blk_desc *dev_desc)ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);gpt_entry *gpt_pte =NULL ;int i =0 ; -char uuid[37 ]; +char uuid[UUID_STR_LEN +1 ];unsigned char *uuid_bin;/* This function validates AND fills in the GPT header and PTE */
include/part.h +3 -2
@@ -9,6 +9,7 @@#include <blk.h> #include <ide.h> +#include <uuid.h> struct block_drvr {char *name;
@@ -54,10 +55,10 @@ typedef struct disk_partition {uchar type[32 ];/* string type description */ int bootable;/* Active/Bootable flag is set */ #if CONFIG_IS_ENABLED (PARTITION_UUIDS ) -char uuid[37 ];/* filesystem UUID as string, if exists */ +char uuid[UUID_STR_LEN +1 ];/* filesystem UUID as string, if exists */ #endif #ifdef CONFIG_PARTITION_TYPE_GUID -char type_guid[37 ];/* type GUID as string, if exists */ +char type_guid[UUID_STR_LEN +1 ];/* type GUID as string, if exists */ #endif #ifdef CONFIG_DOS_PARTITION uchar sys_ind;/* partition type */
Signature · 1 line
2.1.4
PATCH v7 1/9 EFI: replace number with UUID_STR_LEN macro
Quoted 5 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/3ecb51ad/attachment.sig>
PATCH v7 2/9 disk_partition: introduce macros for description string lengths
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Changes since v6: none.
--- include/part.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
include/part.h +5 -2
@@ -47,12 +47,15 @@ struct block_drvr {#define DEV_TYPE_CDROM 0x05/* CD-ROM */ #define DEV_TYPE_OPDISK 0x07/* optical disk */ +#define PART_NAME_LEN 32 +#define PART_TYPE_LEN 32 + typedef struct disk_partition { lbaint_t start; /* # of first block in partition */ lbaint_t size; /* number of blocks in partition */ ulong blksz; /* block size in bytes */ - uchar name[32]; /* partition name */ - uchar type[32]; /* string type description */ + uchar name[PART_NAME_LEN]; /* partition name */ + uchar type[PART_TYPE_LEN]; /* string type description */ int bootable; /* Active/Bootable flag is set */ #if CONFIG_IS_ENABLED(PARTITION_UUIDS) char uuid[UUID_STR_LEN + 1]; /* filesystem UUID as string, if exists */
Signature · 1 line
2.1.4
PATCH v7 2/9 disk_partition: introduce macros for description string lengths
Quoted 5 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/5cc1ee50/attachment.sig>
PATCH v7 3/9 GPT: fix error in partitions string doc
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
The existing partitions-list parsing in cmd/gpt.c passes a value from gpt_default() to set_gpt_info() that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call from set_gpt_info() to extract_val() to find 'uuid_disk' will fail. Change README.gpt accordingly.
Changes since v6: none.
--- doc/README.gpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
doc/README.gpt +4 -4
@@ -156,10 +156,10 @@ Creating GPT partitions in U-Boot: To restore GUID partition table one needs to: 1. Define partition layout in the environment. Format of partitions layout: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or - "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + "uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition.
@@ -219,7 +219,7 @@ PARTITION_BASIC_DATA_GUID (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7). If you define 'CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type' can specify a other partition type guid: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=..., type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"
@@ -241,7 +241,7 @@ Some strings can be also used at the place of known GUID : "lvm" = PARTITION_LINUX_LVM_GUID (E6D6D379-F507-44C2-A23C-238F2A3DF928) - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...,type=linux;" They are also used to display the type of partition in "part list" command.
Signature · 1 line
2.1.4
PATCH v7 3/9 GPT: fix error in partitions string doc
Quoted 9 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
The existing partitions-list parsing in
cmd/gpt.cpasses a value fromgpt_default()toset_gpt_info()that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call fromset_gpt_info()toextract_val()to find 'uuid_disk' will fail. Change README.gpt accordingly.
Quoted 3 lines
Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/b77ecd23/attachment.sig>
PATCH v7 4/9 sandbox: README: fix partition command invocation
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
The instructions for creating a disk image that are presently in README.sandbox fail because sfdisk doesn't know about GPT.
Changes since v6: none.
--- board/sandbox/README.sandbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
board/sandbox/README.sandbox +1 -1
@@ -333,7 +333,7 @@ the contents of the root directory on the second partion of the image A disk image can be created using the following commands: $> truncate -s 1200M ./disk.raw -$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sfdisk ./disk.raw +$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sgdisk ./disk.raw $> lodev=`sudo losetup -P -f --show ./disk.raw` $> sudo mkfs.vfat -n EFI -v ${lodev}p1 $> sudo mkfs.ext4 -L ROOT -v ${lodev}p2
Signature · 1 line
2.1.4
PATCH v7 4/9 sandbox: README: fix partition command invocation
Quoted 8 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
The instructions for creating a disk image that are presently in README.sandbox fail because sfdisk doesn't know about GPT.
Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/c10c2e25/attachment.sig>
PATCH v7 5/9 cmd gpt: test in sandbox
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Make minor changes to README.gpt and sandbox_defconfig to support testing of the gpt command's functionality in the sandbox.
Changes since v6: none.
--- doc/README.gpt | 10 ++++++++++ 1 file changed, 10 insertions(+)
doc/README.gpt +10 -0
@@ -210,6 +210,16 @@ U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +The GPT functionality may be tested with the 'sandbox' board by +creating a disk image as described under 'Block Device Emulation' in +board/sandbox/README.sandbox: + +=>host bind 0 ./disk.raw +=> gpt read host 0 +[ . . . ] +=> gpt flip host 0 +[ . . . ] + Partition type GUID: ====================
Signature · 1 line
2.1.4
PATCH v7 5/9 cmd gpt: test in sandbox
Quoted 8 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
Make minor changes to README.gpt and
sandbox_defconfigto support testing of the gpt command's functionality in the sandbox.Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/433e43e0/attachment.sig>
PATCH v7 6/9 partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Move MAX_SEARCH_PARTITIONS to part.h so that functions in cmd directory can find it. At the same time, increase the value to 64 since some operating systems use many, and the resources consumed by a larger value are minimal.
Changes since v6: none.
--- disk/part.c | 1 - include/part.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
disk/part.c +0 -1
@@ -388,7 +388,6 @@ cleanup:#define PART_UNSPECIFIED -2#define PART_AUTO -1 -#define MAX_SEARCH_PARTITIONS 16int blk_get_device_part_str (const char *ifname,const char *dev_part_str,struct blk_desc **dev_desc,disk_partition_t *info,int allow_whole_dev)
include/part.h +1 -0
@@ -49,6 +49,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 64 typedef struct disk_partition { lbaint_t start; /* # of first block in partition */
Signature · 1 line
2.1.4
PATCH v7 6/9 partitions: increase MAX_SEARCH_PARTITIONS and move to part.h
Quoted 10 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
Move
MAX_SEARCH_PARTITIONStopart.hso that functions in cmd directory can find it. At the same time, increase the value to 64 since some operating systems use many, and the resources consumed by a larger value are minimal.Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/98a57a06/attachment.sig>
PATCH v7 7/9 GPT: add accessor function for disk GUID
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Changes since v6: none.
--- cmd/gpt.c | 26 ++++++++++++++++++++++++++ disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-)
cmd/gpt.c +26 -0
@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return CMD_RET_FAILURE ; + +if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return ret; +} +/** * do_gpt(): Perform GPT operations *
@@ -436,6 +453,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }else if ((strcmp (argv[1 ],"verify" ) ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { + ret =do_disk_guid (blk_dev_desc, argv[4 ]); }else {return CMD_RET_USAGE ; }
@@ -458,4 +477,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );
disk/part_efi.c +31 -0
@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)* Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +*/ +int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{ +ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz); +gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */ +if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); +if (is_gpt_valid (dev_desc, dev_desc->lba -1 , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid Backup GPT ***\n" , + __func__); +return -EINVAL ; + }else { +printf ("%s: *** Using Backup GPT ***\n" , + __func__); + } + } + + guid_bin = gpt_head->disk_guid.b; +uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc) {ALLOC_CACHE_ALIGN_BUFFER_PAD (gpt_header, gpt_head,1 , dev_desc->blksz);
doc/README.gpt +2 -1
@@ -171,7 +171,8 @@ To restore GUID partition table one needs to: The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set to - the generated UUID. + the generated UUID. The 'gpt guid' command reads the current value of the + uuid_disk from the GPT. The field 'bootable' is optional, it is used to mark the GPT partition bootable (set attribute flags "Legacy BIOS bootable").
include/part.h +15 -0
@@ -372,6 +372,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,int gpt_verify_partitions (struct blk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT +* +* This function reads the GUID string from a block device whose descriptor +* is provided. +* +* @param dev_desc - block device descriptor +* @param guid - pre-allocated string in which to return the GUID +* +* @return - '0' on success, otherwise error +*/ +int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Signature · 1 line
2.1.4
PATCH v7 7/9 GPT: add accessor function for disk GUID
Quoted 10 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Changes since v6: none.
Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/41b5b6db/attachment.sig>
PATCH v7 8/9 GPT: read partition table from device into a data structure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
Change since v6:
-- Removed a cast in allocate_disk_part() as suggested by Lothar.
--- cmd/gpt.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 126 insertions(+)
cmd/gpt.c +119 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,118 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart =malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name, +PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type, +PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +/* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ + newpart->gpt_part_info.uuid[UUID_STR_LEN ] ='\0' ; +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part)) + goto out; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); + goto out; + } +return --valid_parts; + out: +if (valid_parts >=2 ) +del_gpt_info (); +return -ENODEV ; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); +return 0 ; + } +return ret; +} +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -455,6 +570,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("Verify GPT: " ); }else if (strcmp (argv[1 ],"guid" ) ==0 ) { ret =do_disk_guid (blk_dev_desc, argv[4 ]); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { + ret =do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -477,6 +594,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +7 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH v7 8/9 GPT: read partition table from device into a data structure
Hi,
Quoted 112 lines · On Sun, 25 Jun 2017 16:43:24 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Change since v6:
-- Removed a cast inallocate_disk_part()as suggested by Lothar.Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 126 insertions(+)cmd/gpt.c +82
-0@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}' @@ -151,6 +154,118 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart =malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name, +PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type, +PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +/* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ + newpart->gpt_part_info.uuid[UUID_STR_LEN ] ='\0' ; +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ;
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 245
Quoted 10 lines
cmd/gpt.c +9
-0+ + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part)) + goto out; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) {
You initialize valid_parts to '1' and only ever increment it, so it can never be '0' here.
Lothar Waßmann
PATCH v8 8/10 GPT: read partition table from device into a data structure
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
---
Changes since v7:
The failure-handling logic of get_gpt_info() now is triggered properly when valid_part=1.
cmd/gpt.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 126 insertions(+)
cmd/gpt.c +119 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,118 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart =malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name, +PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type, +PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +/* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ + newpart->gpt_part_info.uuid[UUID_STR_LEN ] ='\0' ; +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part)) + goto out; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (valid_parts ==1 ) { +printf ("** No valid partitions found **\n" ); + goto out; + } +return --valid_parts; + out: +if (valid_parts >=2 ) +del_gpt_info (); +return -ENODEV ; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); +return 0 ; + } +return ret; +} +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -455,6 +570,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("Verify GPT: " ); }else if (strcmp (argv[1 ],"guid" ) ==0 ) { ret =do_disk_guid (blk_dev_desc, argv[4 ]); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { + ret =do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -477,6 +594,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +7 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH v8 8/10 GPT: read partition table from device into a data structure
Hi,
Quoted 21 lines · On Sat, 1 Jul 2017 15:42:57 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Signed-off-by Alison Chaiken <[email protected]>---
Changes since v7:
The failure-handling logic ofget_gpt_info()now is triggered properly when valid_part=1.cmd/gpt.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 126 insertions(+)cmd/gpt.c +0
-0
[...]
Quoted 18 lines
cmd/gpt.c +17
-0+static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part))
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 248
Quoted 10 lines
cmd/gpt.c +10
-0+ goto out; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (valid_parts ==1 ) { +printf ("** No valid partitions found **\n" ); + goto out; + } +return --valid_parts;
I personally find it somewhat strange to initialize a counter to 1 and then return its value reduced by one, rather than initializing it to 0 and returning the exact counter value.
Lothar Waßmann
PATCH v8 8/10 GPT: read partition table from device into a data structure
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
--- cmd/gpt.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 128 insertions(+)
cmd/gpt.c +0 -0
Changes since v7:
-- Made counter in get_gpt_info() start at 0 rather than 1. -- Checkpatch cleanup.
@@ -19,6 +19,9 @@
#include <linux/ctype.h>
#include <div64.h>
#include <memalign.h>
+#include <linux/compat.h>
+
+static LIST_HEAD(disk_partitions);
/**
* extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,120 @@ static bool found_key(const char *str, const char *key)
return result;
}
+static void del_gpt_info(void)
+{
+ struct list_head *pos = &disk_partitions;
+ struct disk_part *curr;
+ while (!list_empty(pos)) {
+ curr = list_entry(pos->next, struct disk_part, list);
+ list_del(pos->next);
+ free(curr);
+ }
+}
+
+static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum) +{
+ struct disk_part *newpart;
+ newpart = malloc(sizeof(*newpart));
+ if (!newpart)
+ return ERR_PTR(-ENOMEM);
+ memset(newpart, '\0', sizeof(newpart));
+
+ newpart->gpt_part_info.start = info->start;
+ newpart->gpt_part_info.size = info->size;
+ newpart->gpt_part_info.blksz = info->blksz;
+ strncpy((char *)newpart->gpt_part_info.name, (const char *)info->name,
+ PART_NAME_LEN);
+ newpart->gpt_part_info.name[PART_NAME_LEN - 1] = '\0';
+ strncpy((char *)newpart->gpt_part_info.type, (const char *)info->type,
+ PART_TYPE_LEN);
+ newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
+ newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_UUIDS
+ strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
+ UUID_STR_LEN);
+ /* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */
+ newpart->gpt_part_info.uuid[UUID_STR_LEN] = '\0';
+#endif
+ newpart->partnum = partnum;
+
+ return newpart;
+}
+
+static void print_gpt_info(void)
+{
+ struct list_head *pos;
+ struct disk_part *curr;
+
+ list_for_each(pos, &disk_partitions) {
+ curr = list_entry(pos, struct disk_part, list);
+ printf("Partition %d:\n", curr->partnum);
+ printf("1st block %x, size %x\n", (unsigned)curr->gpt_part_info.start,
+ (unsigned)curr->gpt_part_info.size);
+ printf("Block size %lu, name %s\n", curr->gpt_part_info.blksz,
+ curr->gpt_part_info.name);
+ printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
+ curr->gpt_part_info.bootable);
+#ifdef CONFIG_PARTITION_UUIDS
+ printf("UUID %s\n", curr->gpt_part_info.uuid);
+#endif
+ printf("\n");
+ }
+}
+
+/*
+ * read partition info into disk_partitions list where
+ * it can be printed or modified
+ */
+static int get_gpt_info(struct blk_desc *dev_desc)
+{
+ /* start partition numbering at 1, as U-Boot does */
+ int valid_parts = 0, p, ret;
+ disk_partition_t info;
+ struct disk_part *new_disk_part;
+
+ if (disk_partitions.next == NULL)
+ INIT_LIST_HEAD(&disk_partitions);
+
+ for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
+ ret = part_get_info(dev_desc, p, &info);
+ if (ret)
+ continue;
+
+ /* Add 1 here because counter is zero-based but p1 is
+ the first partition */
+ new_disk_part = allocate_disk_part(&info, valid_parts+1);
+ if (IS_ERR(new_disk_part))
+ goto out;
+
+ list_add_tail(&new_disk_part->list, &disk_partitions);
+ valid_parts++;
+ }
+ if (valid_parts == 0) {
+ printf("** No valid partitions found **\n");
+ goto out;
+ }
+ return valid_parts;
+ out:
+ if (valid_parts >= 1)
+ del_gpt_info();
+ return -ENODEV;
+}
+
+/* a wrapper to test get_gpt_info */
+static int do_get_gpt_info(struct blk_desc *dev_desc)
+{
+ int ret;
+
+ ret = get_gpt_info(dev_desc);
+ if (ret > 0) {
+ print_gpt_info();
+ del_gpt_info();
+ return 0;
+ }
+ return ret;
+}
+
/**
* set_gpt_info(): Fill partition information from string
* function allocates memory, remember to free!
@@ -455,6 +572,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Verify GPT: ");
} else if (strcmp(argv[1], "guid") == 0) {
ret = do_disk_guid(blk_dev_desc, argv[4]);
+ } else if (strcmp(argv[1], "read") == 0) {
+ ret = do_get_gpt_info(blk_dev_desc);
} else {
return CMD_RET_USAGE;
}
@@ -477,6 +596,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
" Example usage:\n"
" gpt write mmc 0 $partitions\n"
" gpt verify mmc 0 $partitions\n"
+ " read <interface> <dev>\n"
+ " - read GPT into a data structure for manipulation\n"
" guid <interface> <dev>\n"
" - print disk GUID\n"
" guid <interface> <dev> <varname>\n"
include/part.h +7 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.13.2
PATCH v8 8/10 GPT: read partition table from device into a data structure
Quoted 7 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Signed-off-by Alison Chaiken <[email protected]>
After changing this to only be adding significant code when CMD_GPT_RENAME is enabled, applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/43f8eb20/attachment.sig>
PATCH v7 9/9 GPT: provide commands to selectively rename partitions
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
Changes since v7:
-- Removed several casts in create_gpt_partitions_list() and
do_rename_gpt_parts() as suggested by Lothar Waßmann. The cast of gpt_part_info.name to char* is needed to silence a compiler warning.
-- Substituted simple_strtol() for atoi() in do_gpt_rename_parts() as
suggested by Tom Rini and Wolfgang Denk.
-- Fixed bug in do_rename_gpt_parts() where 0 was returned as a valid
number of partitions with which to continue.
-- Added a comment to do_rename_gpt_parts() noting that the debug()
string it optionally prints is useful as input to the pre-existing 'gpt write' and 'gpt verify' commands.
-- Changed some -1 return values to -ENODEV and -EINVAL as suggested
by Tom Rini.
--- cmd/Kconfig | 8 ++ cmd/gpt.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 20 ++++- 3 files changed, 261 insertions(+), 6 deletions(-)
cmd/Kconfig +8 -0
@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +234 -5
299 lines not on this page · raw message
doc/README.gpt +19 -1
@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Signature · 1 line
2.1.4
PATCH v7 9/9 GPT: provide commands to selectively rename partitions
Hi
Quoted 29 lines · On Mon, Jun 26, 2017 at 7:43 AM, <[email protected]> wrote:
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Changes since v7:
-- Removed several casts in
create_gpt_partitions_list()and
do_rename_gpt_parts()as suggested by Lothar Waßmann. The cast of gpt_part_info.name to char* is needed to silence a compiler warning.-- Substituted
simple_strtol()foratoi()indo_gpt_rename_parts()as
suggested by Tom Rini and Wolfgang Denk.-- Fixed bug in
do_rename_gpt_parts()where 0 was returned as a valid
number of partitions with which to continue.
Quoted 7 lines
-- Added a comment to
do_rename_gpt_parts()noting that thedebug()
string it optionally prints is useful as input to the pre-existing 'gpt write' and 'gpt verify' commands.-- Changed some -1 return values to
-ENODEVand-EINVALas suggested
by Tom Rini.
Can you please remove the changelog from the commit message, instead put it in the commit-notes section below ---?
Quoted 8 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/Kconfig | 8 ++ cmd/gpt.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 20 ++++- 3 files changed, 261 insertions(+), 6 deletions(-)
[snip]
Regards,
Bin
PATCH v7 9/9 GPT: provide commands to selectively rename partitions
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
--- cmd/Kconfig | 8 ++ cmd/gpt.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 20 ++++- 3 files changed, 261 insertions(+), 6 deletions(-)
Changes since v7:
-- Removed several casts in create_gpt_partitions_list() and
do_rename_gpt_parts() as suggested by Lothar Waßmann. The cast of gpt_part_info.name to char* is needed to silence a compiler warning.
-- Substituted simple_strtol() for atoi() in do_gpt_rename_parts() as
suggested by Tom Rini and Wolfgang Denk.
-- Fixed bug in do_rename_gpt_parts() where 0 was returned as a valid
number of partitions with which to continue.
-- Added a comment to do_rename_gpt_parts() noting that the debug()
string it optionally prints is useful as input to the pre-existing 'gpt write' and 'gpt verify' commands.
-- Changed some -1 return values to -ENODEV and -EINVAL as suggested
by Tom Rini.
cmd/Kconfig +8 -0
@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +234 -5
299 lines not on this page · raw message
doc/README.gpt +19 -1
@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Signature · 1 line
2.1.4
PATCH v7 9/9 GPT: provide commands to selectively rename partitions
In reply to alison at peloton-tech.comHi,
Quoted 162 lines · On Sun, 25 Jun 2017 16:43:25 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Changes since v7:
-- Removed several casts in
create_gpt_partitions_list()and
do_rename_gpt_parts()as suggested by Lothar Waßmann. The cast of gpt_part_info.name to char* is needed to silence a compiler warning.-- Substituted
simple_strtol()foratoi()indo_gpt_rename_parts()as
suggested by Tom Rini and Wolfgang Denk.-- Fixed bug in
do_rename_gpt_parts()where 0 was returned as a valid
number of partitions with which to continue.-- Added a comment to
do_rename_gpt_parts()noting that thedebug()
string it optionally prints is useful as input to the pre-existing 'gpt write' and 'gpt verify' commands.-- Changed some -1 return values to
-ENODEVand-EINVALas suggested
by Tom Rini.Signed-off-by Alison Chaiken <[email protected]>--- cmd/Kconfig | 8 ++ cmd/gpt.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 20 ++++- 3 files changed, 261 insertions(+), 6 deletions(-)cmd/Kconfig +8
-0@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"cmd/gpt.c +67
-2@@ -20,6 +20,8 @@#include <div64.h> #include <memalign.h> #include <linux/compat.h> +#include <linux/sizes.h> +#include <stdlib.h> static LIST_HEAD (disk_partitions);@@ -194,16 +196,33 @@ static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum)return newpart; } +static void prettyprint_part_size (char *sizestr,unsigned long partsize, +unsigned long blksize) +{ +unsigned long long partbytes; +unsigned long partmegabytes; + + partbytes = partsize * blksize; + partmegabytes =lldiv (partbytes,SZ_1M ); +snprintf (sizestr,16 ,"%luMiB" , partmegabytes); +} +static void print_gpt_info (void ) {struct list_head *pos;struct disk_part *curr; +char partstartstr[16 ]; +char partsizestr[16 ];list_for_each (pos, &disk_partitions) { curr = list_entry(pos, struct disk_part, list); +prettyprint_part_size (partstartstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +prettyprint_part_size (partsizestr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +printf ("Partition %d:\n" , curr->partnum); -printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, - (unsigned )curr->gpt_part_info.size); +printf ("Start %s, size %s\n" , partstartstr, partsizestr);printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, curr->gpt_part_info.name); printf("Type %s, bootable %d\n", curr->gpt_part_info.type,@@ -215,6 +234,74 @@ static void print_gpt_info(void) } } +#ifdef CONFIG_CMD_GPT_RENAME +static int calc_parts_list_len (int numparts) +{ +int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" ); +/* for the comma */ + partlistlen++; + +/* per-partition additions; numparts starts at 1, so this should be correct */ + partlistlen += numparts * (strlen ("name=," ) +PART_NAME_LEN +1 ); +/* 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 ); + partlistlen += numparts * (strlen ("uuid=;" ) +UUID_STR_LEN +1 ); +/* for the terminating null */ + partlistlen++; +debug ("Length of partitions_list is %d for %d partitions\n" , partlistlen, + numparts); +return partlistlen; +} + +/* +* create the string that upstream 'gpt write' command will accept as an +* argument +* +* From doc/README.gpt, Format of partitions layout: +* "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* name=kernel,size=60MiB,uuid=...;" +* The fields 'name' and 'size' are mandatory for every partition. +* The field 'start' is optional. The fields 'uuid' and 'uuid_disk' +* are optional if CONFIG_RANDOM_UUID is enabled. +*/ +static int create_gpt_partitions_list (int numparts,const char *guid,char *partitions_list) +{ +struct list_head *pos; +struct disk_part *curr; +char partstr[PART_NAME_LEN +1 ]; + +if (!partitions_list) +return -EINVAL ; + +strcpy (partitions_list,"uuid_disk=" ); +strncat (partitions_list, guid,UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list);
cmd/gpt.c static void print_gpt_info(void) · line 292
Quoted 10 lines
cmd/gpt.c +9
-0+strcat (partitions_list,"name=" ); +strncat (partitions_list, (const char *)curr->gpt_part_info.name,PART_NAME_LEN +1 ); +strcat (partitions_list,",start=" ); +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +/* one extra byte for NULL */ +strncat (partitions_list, partstr,PART_NAME_LEN +1 ); +strcat (partitions_list,",size=" ); +/* lbaint_t is unsigned long, per include/ide.h */
AFAICT lbaint_t is declared in include/blk.h and may be uint64_t or ulong depending on CONFIG_SYS_64BIT_LBA.
Quoted 62 lines
cmd/gpt.c +13
-0+prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +strncat (partitions_list, partstr,PART_NAME_LEN +1 ); + +strcat (partitions_list,",uuid=" ); +strncat (partitions_list, curr->gpt_part_info.uuid, +UUID_STR_LEN +1 ); + strcat(partitions_list, ";"); + } +return 0 ; +} +#endif +/* * read partition info into disk_partitions list where * it can be printed or modified
cmd/gpt.c +26
-2@@ -226,8 +313,11 @@ static int get_gpt_info(struct blk_desc *dev_desc)disk_partition_t info;struct disk_part *new_disk_part; -if (disk_partitions.next ==NULL ) -INIT_LIST_HEAD (&disk_partitions); +/* +* Always re-read partition info from device, in case +* it has changed +*/ +INIT_LIST_HEAD (&disk_partitions);for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { ret =part_get_info (dev_desc, p, &info);@@ -301,6 +391,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,return -1 ; str =strdup (str_part); +if (str ==NULL ) +return -ENOMEM ;/* extract disk guid */ s = str;@@ -530,6 +622,127 @@ static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)return ret; } +#ifdef CONFIG_CMD_GPT_RENAME +static int do_rename_gpt_parts (struct blk_desc *dev_desc,char *subcomm, +char *name1,char *name2) +{ +struct list_head *pos; +struct disk_part *curr; +disk_partition_t *new_partitions =NULL ; +char disk_guid[UUID_STR_LEN +1 ]; +char *partitions_list, *str_disk_guid; +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" )))) +return -EINVAL ; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return ret;
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 653
Quoted 10 lines
cmd/gpt.c +9
-0+ numparts =get_gpt_info (dev_desc); +if (numparts <=0 ) +return numparts ? numparts: -ENODEV ; + + partlistlen =calc_parts_list_len (numparts); + partitions_list =malloc (partlistlen); +memset (partitions_list,'\0' , partlistlen); + + ret = create_gpt_partitions_list(numparts, (const char *) disk_guid,
unnecessary type cast. A function that takes a 'const' argument may well be passed a non-'const' value.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 12 lines
cmd/gpt.c +11
-0+ partitions_list); +if (ret <0 ) +return ret; +/* +* Uncomment the following line to print a string that 'gpt write' +* or 'gpt verify' will accept as input. +*/ +debug ("OLD partitions_list is %s with %u chars\n" , partitions_list, + (unsigned )strlen (partitions_list)); + + ret = set_gpt_info(dev_desc, (const char *)partitions_list, &str_disk_guid,
dto.
[...]
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
Quoted 12 lines
cmd/gpt.c +11
-0+list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +if (i == partnum) { +strcpy ((char *)curr->gpt_part_info.name, name2); +break ; + } + i++; + } + } + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, partitions_list);
dto.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 719
Quoted 6 lines
cmd/gpt.c +6
-0+if (ret <0 ) +return ret; +debug ("NEW partitions_list is %s with %u chars\n" , partitions_list, + (unsigned )strlen (partitions_list)); + + ret = set_gpt_info(dev_desc, (const char *)partitions_list, &str_disk_guid,
dto.
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 764
Quoted 7 lines
cmd/gpt.c +1
-1@@ -547,7 +760,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])char *ep;struct blk_desc *blk_dev_desc =NULL ; -if (argc <4 || argc >5 ) +if (argc <4 || argc >6 )
Other subcommands still accept only 4 parameters, so this check should possibly be done after checking the subcommand name, or at least made conditional on CONFIG_CMD_GPT_RENAME which enables the new subcommands.
Quoted 61 lines
cmd/gpt.c +0
-0return CMD_RET_USAGE ;cmd/gpt.c +16
-0dev = (int )simple_strtoul (argv[3 ], &ep,10 );@@ -572,6 +785,11 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ret =do_disk_guid (blk_dev_desc, argv[4 ]); }else if (strcmp (argv[1 ],"read" ) ==0 ) { ret =do_get_gpt_info (blk_dev_desc); +#ifdef CONFIG_CMD_GPT_RENAME + }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 ]); +#endif }else {return CMD_RET_USAGE ; }@@ -603,4 +821,15 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt guid mmc 0\n" " gpt guid mmc 0 varname\n" +#ifdef CONFIG_CMD_GPT_RENAME +"gpt partition renaming commands:\n" +"gpt swap <interface> <dev> <name1> <name2>\n" +" - change all partitions named name1 to name2\n" +" and vice-versa\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" +#endif );doc/README.gpt +18
-0@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
doc/README.gpt board/sandbox/README.sandbox: · line 242
Quoted 8 lines
doc/README.gpt +1
-1@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Lothar Waßmann
PATCH 9/10 GPT: provide commands to selectively rename partitions
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
---
Changes since v7:
This version removes casts to unsigned long where the underlying data type is lbaint_t. I tested this version both with and without CONFIG_SYS_64BIT_LBA, and the output is fine in either case. This version also removes unneeded casts to const and restores the gpt command's error reporting to its earlier state if CONFIG_GPT_RENAME is unset.
In addition, there is an additional check that a malloc() has succeeded.
cmd/Kconfig | 8 ++ cmd/gpt.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- doc/README.gpt | 20 ++++- 3 files changed, 263 insertions(+), 5 deletions(-)
cmd/Kconfig +8 -0
@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +236 -4
301 lines not on this page · raw message
doc/README.gpt +19 -1
@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Signature · 1 line
2.1.4
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
In reply to Alison ChaikenDear Alison,
Quoted 6 lines · In message <CAOuSAjdHerD7iWSwv5HQmx07nALRHschnH5=XToNEZDqA9JsvQ@mail.gmail.com>…
The idea behind the 'swap' mode is that a storage device can have two sets of partitions, one set all named 'primary' and one set all named 'backup'.
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of being interrupted.
It's still a sequential, non-atomic operation, and "little chance" is exactly the places where Murphy likes to hit you.
Quoted 6 lines
One additional note: the last version I posted worked fine for the sandbox, but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyone have
a better idea to solve this problem?
U-Boot should always be self-contained and not link regular library code from the tool chain.
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Looks clean and obviously correct to me, but then _everything_ I write always looks obviously correct to me. - Linus Torvalds in <[email protected]>
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Quoted 24 lines · Wolfgang Denk
Dear Alison,
In message <CAOuSAjdHerD7iWSwv5HQmx07nALRHschnH5=XToNEZDqA9JsvQ@mail.
Quoted 2 lines · gmail.com> you wrote:
The idea behind the 'swap' mode is that a storage device can have two
sets
Quoted 1 line
of partitions, one set all named 'primary' and one set all named
'backup'.
Quoted 3 lines
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of beinginterrupted.
It's still a sequential, non-atomic operation, and "little chance" is exactly the places where Murphy likes to hit you.
Quoted 1 line
One additional note: the last version I posted worked fine for the
sandbox,
Quoted 4 lines
but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyonehave
Quoted 9 lines
Quoted 1 line
a better idea to solve this problem?
U-Boot should always be self-contained and not link regular library code from the tool chain.
Best regards,
Wolfgang Denk
I'm about to submit a new version of the patches that adopts Wolfgang's and Tom's suggestions about replacing atoi().
Regarding the atomicity of 'gpt swap, the point is that 'gpt swap' first modifies the names in an in-memory
data structure, and then uses the existing 'gpt write' functionality to change the actual partition table stored on the device. Thus, interruption of the new command is low-risk, as interruption of the modification of the new data structure has no persistent effect, and the risk associated with 'gpt write' is the same as always.
By the way, in the course of testing an earlier version of this patch series, I noticed that 'gpt write' and 'gpt verify' segv if presented with a non-null-terminated partitions string. It's the strlen function in lib that actually generates an error. I haven't yet quite figured out what the best solution to the problem is: should strlen() itself be modified, or is
it enough to test in gpt.c? The right solution is not to present the
commands with poorly formed strings, but it's easy to do so.
Mit freundlichen Grüße,
Alison
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Quoted 47 lines · Alison Chaiken
Quoted 24 lines · Wolfgang Denk
Dear Alison,
In message <CAOuSAjdHerD7iWSwv5HQmx07nALRHschnH5=XToNEZDqA9JsvQ@mail.
Quoted 2 lines · gmail.com> you wrote:
The idea behind the 'swap' mode is that a storage device can have two
sets
Quoted 1 line
of partitions, one set all named 'primary' and one set all named
'backup'.
Quoted 3 lines
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of beinginterrupted.
It's still a sequential, non-atomic operation, and "little chance" is exactly the places where Murphy likes to hit you.
Quoted 1 line
One additional note: the last version I posted worked fine for the
sandbox,
Quoted 4 lines
but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyonehave
Quoted 9 lines
Quoted 1 line
a better idea to solve this problem?
U-Boot should always be self-contained and not link regular library code from the tool chain.
Best regards,
Wolfgang Denk
I'm about to submit a new version of the patches that adopts Wolfgang's and Tom's suggestions about replacing
atoi().Regarding the atomicity of 'gpt swap, the point is that 'gpt swap' first modifies the names in an in-memory
data structure, and then uses the existing 'gpt write' functionality to change the actual partition table stored on the device. Thus, interruption of the new command is low-risk, as interruption of the modification of the new data structure has no persistent effect, and the risk associated with 'gpt write' is the same as always.
Quoted 7 lines
By the way, in the course of testing an earlier version of this patch series, I noticed that 'gpt write' and 'gpt verify' segv if presented with a non-null-terminated partitions string. It's the strlen function in lib that actually generates an error. I haven't yet quite figured out what the best solution to the problem is: should
strlen()itself be modified, or is
it enough to test ingpt.c? The right solution is not to present the
commands with poorly formed strings, but it's easy to do so.
It is likely this particular bug is one of many in the class of using strlen when we cannot really be certain of well formatted input / buffer, sadly. So a fix to gpt.c and if you're so inclined, a git grep around for other likely cases.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170626/e271ce2a/attachment.sig>
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
In reply to Alison ChaikenHi,
Quoted 47 lines · On Sun, 25 Jun 2017 14:54:56 -0700 Alison Chaiken wrote:
Quoted 24 lines · Wolfgang Denk
Dear Alison,
In message <CAOuSAjdHerD7iWSwv5HQmx07nALRHschnH5=XToNEZDqA9JsvQ@mail.
Quoted 2 lines · gmail.com> you wrote:
The idea behind the 'swap' mode is that a storage device can have two
sets
Quoted 1 line
of partitions, one set all named 'primary' and one set all named
'backup'.
Quoted 3 lines
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of beinginterrupted.
It's still a sequential, non-atomic operation, and "little chance" is exactly the places where Murphy likes to hit you.
Quoted 1 line
One additional note: the last version I posted worked fine for the
sandbox,
Quoted 4 lines
but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyonehave
Quoted 9 lines
Quoted 1 line
a better idea to solve this problem?
U-Boot should always be self-contained and not link regular library code from the tool chain.
Best regards,
Wolfgang Denk
I'm about to submit a new version of the patches that adopts Wolfgang's and Tom's suggestions about replacing
atoi().Regarding the atomicity of 'gpt swap, the point is that 'gpt swap' first modifies the names in an in-memory
data structure, and then uses the existing 'gpt write' functionality to change the actual partition table stored on the device. Thus, interruption of the new command is low-risk, as interruption of the modification of the new data structure has no persistent effect, and the risk associated with 'gpt write' is the same as always.
Quoted 8 lines
By the way, in the course of testing an earlier version of this patch series, I noticed that 'gpt write' and 'gpt verify' segv if presented with a non-null-terminated partitions string. It's the strlen function in lib that actually generates an error. I haven't yet quite figured out what the best solution to the problem is: should
strlen()itself be modified, or is
it enough to test ingpt.c? The right solution is not to present the
commands with poorly formed strings, but it's easy to do so.
You can use strnlen() if you know the maximum allowed length of the string.
NB: A quick glance at set_gpt_info() revealed this potential crash cause:
| str = strdup(str_part); | | /* extract disk guid */ | s = str; | val = extract_val(str, "uuid_disk");
strdup() may fail (especially if the input string is not zero terminated) and return a NULL pointer which then will happily be used by extract_val().
Lothar Waßmann
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Hi,
Quoted 63 lines · On Tue, 27 Jun 2017 09:05:14 +0200 Lothar Waßmann wrote:
Hi,
Quoted 47 lines · On Sun, 25 Jun 2017 14:54:56 -0700 Alison Chaiken wrote:
Quoted 24 lines · Wolfgang Denk
Dear Alison,
In message <CAOuSAjdHerD7iWSwv5HQmx07nALRHschnH5=XToNEZDqA9JsvQ@mail.
Quoted 2 lines · gmail.com> you wrote:
The idea behind the 'swap' mode is that a storage device can have two
sets
Quoted 1 line
of partitions, one set all named 'primary' and one set all named
'backup'.
Quoted 3 lines
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of beinginterrupted.
It's still a sequential, non-atomic operation, and "little chance" is exactly the places where Murphy likes to hit you.
Quoted 1 line
One additional note: the last version I posted worked fine for the
sandbox,
Quoted 4 lines
but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyonehave
Quoted 9 lines
Quoted 1 line
a better idea to solve this problem?
U-Boot should always be self-contained and not link regular library code from the tool chain.
Best regards,
Wolfgang Denk
I'm about to submit a new version of the patches that adopts Wolfgang's and Tom's suggestions about replacing
atoi().Regarding the atomicity of 'gpt swap, the point is that 'gpt swap' first modifies the names in an in-memory
data structure, and then uses the existing 'gpt write' functionality to change the actual partition table stored on the device. Thus, interruption of the new command is low-risk, as interruption of the modification of the new data structure has no persistent effect, and the risk associated with 'gpt write' is the same as always.Quoted 8 lines
By the way, in the course of testing an earlier version of this patch series, I noticed that 'gpt write' and 'gpt verify' segv if presented with a non-null-terminated partitions string. It's the strlen function in lib that actually generates an error. I haven't yet quite figured out what the best solution to the problem is: should
strlen()itself be modified, or is
it enough to test ingpt.c? The right solution is not to present the
commands with poorly formed strings, but it's easy to do so.You can use
strnlen()if you know the maximum allowed length of the string.NB: A quick glance at
set_gpt_info()revealed this potential crash cause:
Quoted 9 lines
| str = strdup(str_part); | | /* extract disk guid */ | s = str; | val = extract_val(str, "uuid_disk");
strdup()may fail (especially if the input string is not zero terminated) and return a NULL pointer which then will happily be used byextract_val().
There are some more highlights in this code:
| *str_disk_guid = malloc(UUID_STR_LEN + 1);
| gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD);
Quoted 1 line
malloc() can fail too.
| *str_disk_guid = strdup(p); | free(val); | /* Move s to first partition */ | strsep(&s, ";");
Quoted 1 line
if strdup() fails, *str_disk_guid will be a NULL pointer, but the function will return success eventually and the NULL pointer will be passed on to subsequent functions without further checks.
|static bool found_key(const char *str, const char *key)
|{
| char *k;
| char *s, *strcopy;
| bool result = false;
|
| strcopy = strdup(str);
| if (!strcopy)
| return NULL;Quoted 1 line
The function has a bool return type, but returns a pointer type here. This accidentally works as expected.
Lothar Waßmann
PATCH 10/10 gpt: harden set_gpt_info() against non NULL-terminated strings
From: Alison Chaiken <[email protected]>
Strings read from devices may sometimes fail to be
NULL-terminated. The functions in lib/string.c are subject to
failure in this case. Protect against observed failures inset_gpt_info() by switching to length-checking variants with a length limit of the maximum possible partition table length. At the same time, add a few checks for NULL string pointers.
Here is an example as observed in sandbox under GDB:
=> gpt verify host 0 $partitions
Program received signal SIGSEGV, Segmentation fault.
0x0000000000477747 in strlen (s=0x0) at lib/string.c:267
267 for (sc = s; *sc != '\0'; ++sc)
(gdb) bt
#0 0x0000000000477747 in strlen (s=0x0) at lib/string.c:267
#1 0x00000000004140b2 in set_gpt_info (str_part=<optimized out>,
str_disk_guid=str_disk_guid at entry=0x7fffffffdbe8, partitions=partitions at entry=0x7fffffffdbd8,
parts_count=parts_count at entry=0x7fffffffdbcf "", dev_desc=<optimized out>) at cmd/gpt.c:415
#2 0x00000000004145b9 in gpt_verify (str_part=<optimized out>, blk_dev_desc=0x7fffef09a9d0) at cmd/gpt.c:580
#3 do_gpt (cmdtp=<optimized out>, flag=<optimized out>, argc=<optimized out>, argv=0x7fffef09a8f0)
at cmd/gpt.c:783
#4 0x00000000004295b0 in cmd_call (argv=0x7fffef09a8f0, argc=0x5, flag=<optimized out>,
cmdtp=0x714e20 <_u_boot_list_2_cmd_2_gpt>) at common/command.c:500
#5 cmd_process (flag=<optimized out>, argc=0x5, argv=0x7fffef09a8f0,
repeatable=repeatable at entry=0x726c04 <flag_repeat>, ticks=ticks at entry=0x0) at common/command.c:539--- cmd/gpt.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
cmd/gpt.c +19 -9
@@ -233,7 +233,7 @@ static void print_gpt_info(void) } } -#ifdef CONFIG_CMD_GPT_RENAME +static int calc_parts_list_len (int numparts) {int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );
@@ -253,6 +253,7 @@ static int calc_parts_list_len(int numparts)return partlistlen; } +#ifdef CONFIG_CMD_GPT_RENAME /* * create the string that upstream 'gpt write' command will accept as an * argument
@@ -381,6 +382,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,int errno =0 ;uint64_t size_ll, start_ll;lbaint_t offset =0 ; +int max_str_part =calc_parts_list_len (MAX_SEARCH_PARTITIONS );debug ("%s: lba num: 0x%x %d\n" , __func__, (unsigned int )dev_desc->lba, (unsigned int )dev_desc->lba);
@@ -398,6 +400,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,if (!val) {#ifdef CONFIG_RANDOM_UUID *str_disk_guid =malloc (UUID_STR_LEN +1 ); +if (str_disk_guid ==NULL ) +return -ENOMEM ;gen_rand_uuid_str (*str_disk_guid,UUID_STR_FORMAT_STD );#else free (str);
@@ -412,10 +416,14 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* Move s to first partition */ strsep (&s,";" ); } -if (strlen (s) ==0 ) +if (s ==NULL ) { +printf ("Error: is the partitions string NULL-terminated?\n" ); +return -EINVAL ; + } +if (strnlen (s, max_str_part) ==0 )return -3 ; - i =strlen (s) -1 ; + i =strnlen (s, max_str_part) -1 ;if (s[i] ==';' ) s[i] ='\0' ;
@@ -429,6 +437,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* allocate memory for partitions */ parts =calloc (sizeof (disk_partition_t), p_count); +if (parts ==NULL ) +return -ENOMEM ;/* retrieve partitions data from string */ for (i =0 ; i < p_count; i++) {
@@ -450,12 +460,12 @@ static int set_gpt_info(struct blk_desc *dev_desc, }else {if (extract_env (val, &p)) p = val; -if (strlen (p) >=sizeof (parts[i].uuid)) { +if (strnlen (p, max_str_part) >=sizeof (parts[i].uuid)) {printf ("Wrong uuid format for partition %d\n" , i); errno =-4 ; goto err; } -strcpy ((char *)parts[i].uuid, p); +strncpy ((char *)parts[i].uuid, p, max_str_part);free (val); }#ifdef CONFIG_PARTITION_TYPE_GUID
@@ -465,13 +475,13 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* 'type' is optional */ if (extract_env (val, &p)) p = val; -if (strlen (p) >=sizeof (parts[i].type_guid)) { +if (strnlen (p, max_str_part) >=sizeof (parts[i].type_guid)) {printf ("Wrong type guid format for partition %d\n" , i); errno =-4 ; goto err; } -strcpy ((char *)parts[i].type_guid, p); +strncpy ((char *)parts[i].type_guid, p, max_str_part); free(val); }#endif
@@ -483,11 +493,11 @@ static int set_gpt_info(struct blk_desc *dev_desc, }if (extract_env (val, &p)) p = val; -if (strlen (p) >=sizeof (parts[i].name)) { +if (strnlen (p, max_str_part) >=sizeof (parts[i].name)) { errno =-4 ; goto err; } -strcpy ((char *)parts[i].name, p); +strncpy ((char *)parts[i].name, p, max_str_part);free (val);/* size */
Signature · 1 line
2.1.4
PATCH 10/10 gpt: harden set_gpt_info() against non NULL-terminated strings
Hi,
Quoted 56 lines · On Sat, 1 Jul 2017 15:44:44 -0700 alison at peloton-tech.com wrote:
From: Alison Chaiken <[email protected]>
Strings read from devices may sometimes fail to be
NULL-terminated. The functions inlib/string.care subject to
failure in this case. Protect against observed failures inset_gpt_info()by switching to length-checking variants with a length limit of the maximum possible partition table length. At the same time, add a few checks for NULL string pointers.Here is an example as observed in sandbox under GDB:
=> gpt verify host 0 $partitions Program received signal SIGSEGV, Segmentation fault. 0x0000000000477747 in strlen (s=0x0) at lib/string.c:267 267 for (sc = s; *sc != '\0'; ++sc) (gdb) bt #0 0x0000000000477747 in strlen (s=0x0) at lib/string.c:267 #1 0x00000000004140b2 in set_gpt_info (str_part=<optimized out>, str_disk_guid=str_disk_guid at entry=0x7fffffffdbe8, partitions=partitions at entry=0x7fffffffdbd8, parts_count=parts_count at entry=0x7fffffffdbcf "", dev_desc=<optimized out>) at cmd/gpt.c:415 #2 0x00000000004145b9 in gpt_verify (str_part=<optimized out>, blk_dev_desc=0x7fffef09a9d0) at cmd/gpt.c:580 #3 do_gpt (cmdtp=<optimized out>, flag=<optimized out>, argc=<optimized out>, argv=0x7fffef09a8f0) at cmd/gpt.c:783 #4 0x00000000004295b0 in cmd_call (argv=0x7fffef09a8f0, argc=0x5, flag=<optimized out>, cmdtp=0x714e20 <_u_boot_list_2_cmd_2_gpt>) at common/command.c:500 #5 cmd_process (flag=<optimized out>, argc=0x5, argv=0x7fffef09a8f0, repeatable=repeatable at entry=0x726c04 <flag_repeat>, ticks=ticks at entry=0x0) at common/command.c:539Suggested-by Lothar Waßmann <[email protected]>Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)cmd/gpt.c +2
-1@@ -233,7 +233,7 @@ static void print_gpt_info(void) } } -#ifdef CONFIG_CMD_GPT_RENAME +static int calc_parts_list_len (int numparts) {int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );@@ -253,6 +253,7 @@ static int calc_parts_list_len(int numparts)return partlistlen; } +#ifdef CONFIG_CMD_GPT_RENAME /* * create the string that upstream 'gpt write' command will accept as an * argument
cmd/gpt.c static int set_gpt_info(struct blk_desc *dev_desc, · line 386
Quoted 5 lines
cmd/gpt.c +1
-0@@ -381,6 +382,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,int errno =0 ;uint64_t size_ll, start_ll;lbaint_t offset =0 ; +int max_str_part =calc_parts_list_len (MAX_SEARCH_PARTITIONS );
indentation should use tabs not spaces (scripts/checkpatch.pl would tell you).
Quoted 12 lines
cmd/gpt.c +2
-0debug ("%s: lba num: 0x%x %d\n" , __func__, (unsigned int )dev_desc->lba, (unsigned int )dev_desc->lba);@@ -398,6 +400,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,if (!val) {#ifdef CONFIG_RANDOM_UUID *str_disk_guid =malloc (UUID_STR_LEN +1 ); +if (str_disk_guid ==NULL ) +return -ENOMEM ;gen_rand_uuid_str (*str_disk_guid,UUID_STR_FORMAT_STD );#else free (str);
cmd/gpt.c static int set_gpt_info(struct blk_desc *dev_desc, · line 422
Quoted 8 lines
cmd/gpt.c +3
-1@@ -412,10 +416,14 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* Move s to first partition */ strsep (&s,";" ); } -if (strlen (s) ==0 ) +if (s ==NULL ) { +printf ("Error: is the partitions string NULL-terminated?\n" ); +return -EINVAL ;
dto.
Lothar Waßmann
PATCH v2 10/10 gpt: harden set_gpt_info() against non NULL-terminated strings
From: Alison Chaiken <[email protected]>
Strings read from devices may sometimes fail to be
NULL-terminated. The functions in lib/string.c are subject to
failure in this case. Protect against observed failures inset_gpt_info() by switching to length-checking variants with a length limit of the maximum possible partition table length. At the same time, add a few checks for NULL string pointers.
Here is an example as observed in sandbox under GDB:
=> gpt verify host 0 $partitions
Program received signal SIGSEGV, Segmentation fault.
0x0000000000477747 in strlen (s=0x0) at lib/string.c:267
267 for (sc = s; *sc != '\0'; ++sc)
(gdb) bt
#0 0x0000000000477747 in strlen (s=0x0) at lib/string.c:267
#1 0x00000000004140b2 in set_gpt_info (str_part=<optimized out>,
str_disk_guid=str_disk_guid at entry=0x7fffffffdbe8, partitions=partitions at entry=0x7fffffffdbd8,
parts_count=parts_count at entry=0x7fffffffdbcf "", dev_desc=<optimized out>) at cmd/gpt.c:415
#2 0x00000000004145b9 in gpt_verify (str_part=<optimized out>, blk_dev_desc=0x7fffef09a9d0) at cmd/gpt.c:580
#3 do_gpt (cmdtp=<optimized out>, flag=<optimized out>, argc=<optimized out>, argv=0x7fffef09a8f0)
at cmd/gpt.c:783
#4 0x00000000004295b0 in cmd_call (argv=0x7fffef09a8f0, argc=0x5, flag=<optimized out>,
cmdtp=0x714e20 <_u_boot_list_2_cmd_2_gpt>) at common/command.c:500
#5 cmd_process (flag=<optimized out>, argc=0x5, argv=0x7fffef09a8f0,
repeatable=repeatable at entry=0x726c04 <flag_repeat>, ticks=ticks at entry=0x0) at common/command.c:539---
Changes since v1:
-- Checkpatch cleanups.
cmd/gpt.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
cmd/gpt.c +19 -9
@@ -233,7 +233,7 @@ static void print_gpt_info(void) } } -#ifdef CONFIG_CMD_GPT_RENAME +static int calc_parts_list_len (int numparts) {int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );
@@ -253,6 +253,7 @@ static int calc_parts_list_len(int numparts)return partlistlen; } +#ifdef CONFIG_CMD_GPT_RENAME /* * create the string that upstream 'gpt write' command will accept as an * argument
@@ -385,6 +386,7 @@ static int set_gpt_info(struct blk_desc *dev_desc,int errno =0 ;uint64_t size_ll, start_ll;lbaint_t offset =0 ; +int max_str_part =calc_parts_list_len (MAX_SEARCH_PARTITIONS );debug ("%s: lba num: 0x%x %d\n" , __func__, (unsigned int )dev_desc->lba, (unsigned int )dev_desc->lba);
@@ -402,6 +404,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,if (!val) {#ifdef CONFIG_RANDOM_UUID *str_disk_guid =malloc (UUID_STR_LEN +1 ); +if (str_disk_guid ==NULL ) +return -ENOMEM ;gen_rand_uuid_str (*str_disk_guid,UUID_STR_FORMAT_STD );#else free (str);
@@ -416,10 +420,14 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* Move s to first partition */ strsep (&s,";" ); } -if (strlen (s) ==0 ) +if (s ==NULL ) { +printf ("Error: is the partitions string NULL-terminated?\n" ); +return -EINVAL ; + } +if (strnlen (s, max_str_part) ==0 )return -3 ; - i =strlen (s) -1 ; + i =strnlen (s, max_str_part) -1 ;if (s[i] ==';' ) s[i] ='\0' ;
@@ -433,6 +441,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* allocate memory for partitions */ parts =calloc (sizeof (disk_partition_t), p_count); +if (parts ==NULL ) +return -ENOMEM ;/* retrieve partitions data from string */ for (i =0 ; i < p_count; i++) {
@@ -454,12 +464,12 @@ static int set_gpt_info(struct blk_desc *dev_desc, }else {if (extract_env (val, &p)) p = val; -if (strlen (p) >=sizeof (parts[i].uuid)) { +if (strnlen (p, max_str_part) >=sizeof (parts[i].uuid)) {printf ("Wrong uuid format for partition %d\n" , i); errno =-4 ; goto err; } -strcpy ((char *)parts[i].uuid, p); +strncpy ((char *)parts[i].uuid, p, max_str_part);free (val); }#ifdef CONFIG_PARTITION_TYPE_GUID
@@ -469,13 +479,13 @@ static int set_gpt_info(struct blk_desc *dev_desc,/* 'type' is optional */ if (extract_env (val, &p)) p = val; -if (strlen (p) >=sizeof (parts[i].type_guid)) { +if (strnlen (p, max_str_part) >=sizeof (parts[i].type_guid)) {printf ("Wrong type guid format for partition %d\n" , i); errno =-4 ; goto err; } -strcpy ((char *)parts[i].type_guid, p); +strncpy ((char *)parts[i].type_guid, p, max_str_part); free(val); }#endif
@@ -487,11 +497,11 @@ static int set_gpt_info(struct blk_desc *dev_desc, }if (extract_env (val, &p)) p = val; -if (strlen (p) >=sizeof (parts[i].name)) { +if (strnlen (p, max_str_part) >=sizeof (parts[i].name)) { errno =-4 ; goto err; } -strcpy ((char *)parts[i].name, p); +strncpy ((char *)parts[i].name, p, max_str_part);free (val);/* size */
Signature · 1 line
2.13.2
PATCH v2 10/10 gpt: harden set_gpt_info() against non NULL-terminated strings
Quoted 28 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
Strings read from devices may sometimes fail to be
NULL-terminated. The functions inlib/string.care subject to
failure in this case. Protect against observed failures inset_gpt_info()by switching to length-checking variants with a length limit of the maximum possible partition table length. At the same time, add a few checks for NULL string pointers.Here is an example as observed in sandbox under GDB:
=> gpt verify host 0 $partitions Program received signal SIGSEGV, Segmentation fault. 0x0000000000477747 in strlen (s=0x0) at lib/string.c:267 267 for (sc = s; *sc != '\0'; ++sc) (gdb) bt #0 0x0000000000477747 in strlen (s=0x0) at lib/string.c:267 #1 0x00000000004140b2 in set_gpt_info (str_part=<optimized out>, str_disk_guid=str_disk_guid at entry=0x7fffffffdbe8, partitions=partitions at entry=0x7fffffffdbd8, parts_count=parts_count at entry=0x7fffffffdbcf "", dev_desc=<optimized out>) at cmd/gpt.c:415 #2 0x00000000004145b9 in gpt_verify (str_part=<optimized out>, blk_dev_desc=0x7fffef09a9d0) at cmd/gpt.c:580 #3 do_gpt (cmdtp=<optimized out>, flag=<optimized out>, argc=<optimized out>, argv=0x7fffef09a8f0) at cmd/gpt.c:783 #4 0x00000000004295b0 in cmd_call (argv=0x7fffef09a8f0, argc=0x5, flag=<optimized out>, cmdtp=0x714e20 <_u_boot_list_2_cmd_2_gpt>) at common/command.c:500 #5 cmd_process (flag=<optimized out>, argc=0x5, argv=0x7fffef09a8f0, repeatable=repeatable at entry=0x726c04 <flag_repeat>, ticks=ticks at entry=0x0) at common/command.c:539
Quoted 2 lines
Suggested-by Lothar Waßmann <[email protected]>Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/b9d0644c/attachment.sig>
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
In reply to Lothar WaßmannQuoted 59 lines · Lothar Waßmann
Hi,
Quoted 47 lines · On Sun, 25 Jun 2017 14:54:56 -0700 Alison Chaiken wrote:
Quoted 24 lines · Wolfgang Denk
Dear Alison,
In message <CAOuSAjdHerD7iWSwv5HQmx07nALRHschnH5=XToNEZDqA9JsvQ@mail.
Quoted 2 lines · gmail.com> you wrote:
The idea behind the 'swap' mode is that a storage device can have two
sets
Quoted 1 line
of partitions, one set all named 'primary' and one set all named
'backup'.
Quoted 3 lines
The software updater in userspace can then simply rename the partitions
with sgdisk in order to pick the new image. The swap mode changes the
whole set of labels at once, so there's little chance of beinginterrupted.
It's still a sequential, non-atomic operation, and "little chance" is exactly the places where Murphy likes to hit you.
Quoted 1 line
One additional note: the last version I posted worked fine for the
sandbox,
Quoted 4 lines
but wouldn't link for an ARM target with the Linaro toolchain, as the
linker couldn't findatoi(). I guess the libc for the x86 compiler
includes it. To test on ARM, I copied insimple_atoi()fromlib/vsprintf.c, but assuredly that is an ugly solution. Does anyonehave
Quoted 9 lines
Quoted 1 line
a better idea to solve this problem?
U-Boot should always be self-contained and not link regular library code from the tool chain.
Best regards,
Wolfgang Denk
I'm about to submit a new version of the patches that adopts Wolfgang's and Tom's suggestions about replacing
atoi().Regarding the atomicity of 'gpt swap, the point is that 'gpt swap' first modifies the names in an in-memory
data structure, and then uses the existing 'gpt write' functionality to change the actual partition table stored on the device. Thus, interruption of the new command is low-risk, as interruption of the modification of the new data structure has no persistent effect, and the risk associated with 'gpt write' is the same as always.Quoted 8 lines
By the way, in the course of testing an earlier version of this patch series, I noticed that 'gpt write' and 'gpt verify' segv if presented with a non-null-terminated partitions string. It's the strlen function in lib that actually generates an error. I haven't yet quite figured out what the best solution to the problem is: should
strlen()itself be modified, or is
it enough to test ingpt.c? The right solution is not to present the
commands with poorly formed strings, but it's easy to do so.
Quoted 2 lines
You can use
strnlen()if you know the maximum allowed length of the string.
Thanks for that tip: I didn't know that strnlen() existed. That
indeed seems like a good protection against at least the problems identified here.
Quoted 8 lines
NB: A quick glance at
set_gpt_info()revealed this potential crash cause:| str = strdup(str_part); | | /* extract disk guid */ | s = str; | val = extract_val(str, "uuid_disk");
Quoted 7 lines
strdup()may fail (especially if the input string is not zero terminated) and return a NULL pointer which then will happily be used byextract_val().Lothar Waßmann
The underlying cause of the problem is that u-boot's implementations
of strlen() and the CLI handle strings differently. The former
terminates strings only on NULLs, while the latter terminates strings
*either* on NULLs or on semicolons. Reading the partition table
back from a device's GPT results in a string with a NULL only at the
very end, but with one semicolon per partition. Running 'gpt verify
mmc 0 $partitions" or 'gpt write mmc 0 $partitions' therefore causes a crash if the user has previously typed 'setenv partitions 1;2;3;4;5;'
rather than 'setenv partitions "1;2;3;4;5;"'. In the former case,
the partitions string ends up being '1' without NULL-termination, resulting in the crash.
U-boot environment parameters often have lots of semi-colon-separated
lists. I'm not sure what other code paths lead to strlen() orstrdup(), as Lothar alludes to above, but it seems likely to me that
there are other ways to reproduce this bug. Looking at lib/string.c,
there are other functions like strcpy() that also check "!= '\0'".
--- Alison
PATCH v6 3/3 GPT: provide commands to selectively rename partitions
Hi,
Quoted 3 lines
The underlying cause of the problem is that u-boot's implementations
ofstrlen()and the CLI handle strings differently. The former
"u-boot's implementation" is conformant with the standard and well documented libc implementation that exists since the dawn of C programming.
Quoted 9 lines
terminates strings only on NULLs, while the latter terminates strings
*either* on NULLs or on semicolons. Reading the partition table
back from a device's GPT results in a string with a NULL only at the
very end, but with one semicolon per partition. Running 'gpt verify
mmc 0 $partitions" or 'gpt write mmc 0 $partitions' therefore causes a crash if the user has previously typed 'setenv partitions 1;2;3;4;5;'
rather than 'setenv partitions "1;2;3;4;5;"'. In the former case,
the partitions string ends up being '1' without NULL-termination,
That's nonsense. _Every_ string in the environment is NULL terminated. In the former case of your example the characters after the first semicolon are interpreted as commands and lead to an error message Unknown command '2' - try 'help'
...
because the ';' is treated as a command terminator by the parser unless quoted.
Lothar Waßmann
PATCH v8 9/10 GPT: provide commands to selectively rename partitions
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
---
Changes since v7:
-- Checkpatch cleanups.
cmd/Kconfig | 8 ++ cmd/gpt.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- doc/README.gpt | 20 ++++- 3 files changed, 264 insertions(+), 5 deletions(-)
cmd/Kconfig +8 -0
@@ -595,6 +595,14 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_RENAME + bool "GPT partition renaming commands" + depends on CMD_GPT + help + Enables the 'gpt' command to interchange names on two GPT + partitions via the 'gpt swap' command or to rename single + partitions via the 'rename' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +237 -4
302 lines not on this page · raw message
doc/README.gpt +19 -1
@@ -210,6 +210,24 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read', 'gpt rename' and 'gpt swap' commands facilitate +programmatic renaming of partitions from bootscripts by generating and +modifying the partitions layout string. Here is an illustration of +employing 'swap' to exchange 'primary' and 'backup' partition names: + +U-BOOT> gpt swap mmc 0 primary backup + +Afterwards, all partitions previously named 'primary' will be named +'backup', and vice-versa. Alternatively, single partitions may be +renamed. In this example, mmc0's first partition will be renamed +'primary': + +U-BOOT> gpt rename mmc 0 1 primary The GPT functionality may be tested with the 'sandbox' board by creating a disk image as described under 'Block Device Emulation' in
@@ -218,7 +236,7 @@ board/sandbox/README.sandbox: =>host bind 0 ./disk.raw => gpt read host 0 [ . . . ] -=> gpt flip host 0 +=> gpt swap host 0 name othername [ . . . ] Partition type GUID:
Signature · 1 line
2.13.2
PATCH v8 9/10 GPT: provide commands to selectively rename partitions
Quoted 11 lines · Alison Chaiken
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via new 'gpt swap' and 'gpt rename' commands.
The 'swap' mode returns an error if no matching partition names are found, or if the number of partitions with one name does not equal
the number with the second name. The 'rename' variant always
succeeds as long as a partition with the provided number exists.
Quoted 6 lines
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Signed-off-by Alison Chaiken <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/e678c149/attachment.sig>
PATCH v3 5/5 GPT: fix error in partitions string doc
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
The existing partitions-list parsing in cmd/gpt.c passes a value from gpt_default() to set_gpt_info() that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call from set_gpt_info() to extract_val() to find 'uuid_disk' will fail. Change README.gpt and file comments accordingly.
--- cmd/gpt.c | 13 +------------ doc/README.gpt | 8 ++++---- 2 files changed, 5 insertions(+), 16 deletions(-)
cmd/gpt.c +1 -12
@@ -232,12 +232,6 @@ static void print_gpt_info(void)#ifdef CONFIG_CMD_GPT_FLIP static int calc_parts_list_len (int numparts) { -/* -* prefatory string: -* doc/README.GPT, suggests that -* int partlistlen = UUID_STR_LEN + 1 + strlen("partitions=uuid_disk="); -* is correct, but extract_val() expects "uuid_disk" first. -*/ int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );/* for the comma */ partlistlen++;
@@ -260,7 +254,7 @@ static int calc_parts_list_len(int numparts)* argument * * From doc/README.gpt, Format of partitions layout: -* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; * name=kernel,size=60MiB,uuid=...;" * The fields 'name' and 'size' are mandatory for every partition. * The field 'start' is optional. The fields 'uuid' and 'uuid_disk'
@@ -275,11 +269,6 @@ static int create_gpt_partitions_list(int numparts, const char *guid, char *partif (!partitions_list)return -1 ; -/* -* README.gpt specifies starting with "partitions=" like so: -* strcpy(partitions_list, "partitions=uuid_disk="); -* but that breaks extract_val, which doesn't skip over 'partitions='. -*/ strcpy (partitions_list,"uuid_disk=" );strncat (partitions_list, guid,UUID_STR_LEN +1 );strcat (partitions_list,";" );
doc/README.gpt +4 -4
@@ -156,10 +156,10 @@ Creating GPT partitions in U-Boot: To restore GUID partition table one needs to: 1. Define partition layout in the environment. Format of partitions layout: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or - "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + "uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition.
@@ -233,7 +233,7 @@ PARTITION_BASIC_DATA_GUID (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7). If you define 'CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type' can specify a other partition type guid: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=..., type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"
@@ -255,7 +255,7 @@ Some strings can be also used at the place of known GUID : "lvm" = PARTITION_LINUX_LVM_GUID (E6D6D379-F507-44C2-A23C-238F2A3DF928) - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...,type=linux;" They are also used to display the type of partition in "part list" command.
Signature · 1 line
2.1.4
v3 cover add support for GPT partition name manipulation
In reply to alison at peloton-tech.comQuoted 11 lines · On Fri, 2 Jun 2017 19:22:29 -0700 alison at peloton-tech.com wrote:
Significant changes since v2:
-- Got rid of the need to allocate memory for the GUID string in
do_gpt();
-- Fixed the problems with string NULL termination in
allocate_disk_part();
-- Removed duplicate definition ofMAX_SEARCH_PARTITIONSfrom
disk/part.cand increased the value ininclude/part.hto 64;
-- Improved the commit message for "rename GPT partitions to detect
boot failure" to better describe the version of the patch I submitted;
-- Fixed numerous small problems with function return values.
Just informative - (no need to resend patches) - for next submissions - please add changelog to each relevant patch.
In this way one can quickly refer to the code.
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 3/6 GPT: add accessor function for disk GUID
In reply to alison at peloton-tech.comHi Alison,
Quoted 6 lines
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Quoted 156 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 30 +++++++++++++++++++++++++++++- disk/part_efi.c | 31 +++++++++++++++++++++++++++++++ doc/README.gpt | 3 ++- include/part.h | 15 +++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-)cmd/gpt.c +28
-1@@ -398,6 +398,23 @@ static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part) return ret; } +static int do_disk_guid (struct blk_desc *dev_desc,char *const namestr) +{ +int ret; +char disk_guid[UUID_STR_LEN +1 ]; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return 1 ; + +if (namestr) +setenv (namestr, disk_guid); +else +printf ("%s\n" , disk_guid); + +return 0 ; +} +/** * do_gpt(): Perform GPT operations * @@ -412,7 +429,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {int ret =CMD_RET_SUCCESS ;int dev =0 ; -char *ep; +char *ep, *varname =NULL ;struct blk_desc *blk_dev_desc =NULL ;if (argc <4 || argc >5 )@@ -436,6 +453,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else if ((strcmp(argv[1], "verify") ==0 )) { ret =gpt_verify (blk_dev_desc, argv[4 ]);printf ("Verify GPT: " ); + }else if (strcmp (argv[1 ],"guid" ) ==0 ) { +if (argc ==5 ) +strcpy (varname, argv[4 ]); +return do_disk_guid (blk_dev_desc, varname); }else {return CMD_RET_USAGE ; }@@ -458,4 +479,11 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" guid <interface> <dev>\n" +" - print disk GUID\n" +" guid <interface> <dev> <varname>\n" +" - set environment variable to disk GUID\n" +" Example usage:\n" +" gpt guid mmc 0\n" +" gpt guid mmc 0 varname\n" );disk/part_efi.c +3
-0@@ -178,6 +178,37 @@ static void prepare_backup_gpt_header(gpt_header*gpt_h) * Public Functions (include/part.h) */ +/* +* UUID is displayed as 32 hexadecimal digits, in 5 groups, +* separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters
+ */disk/part_efi.c +3
-0+int get_disk_guid (struct blk_desc * dev_desc,char *guid) +{ + ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1,
dev_desc->blksz);disk/part_efi.c +4
-0+gpt_entry *gpt_pte =NULL ; +unsigned char *guid_bin; + +/* This function validates AND fills in the GPT header and PTE */
disk/part_efi.c +6
-0+if (is_gpt_valid (dev_desc,GPT_PRIMARY_PARTITION_TABLE_LBA , + gpt_head, &gpt_pte) !=1 ) { +printf ("%s: *** ERROR: Invalid GPT ***\n" , __func__); +if (is_gpt_valid (dev_desc, (dev_desc->lba -1 ), + gpt_head, &gpt_pte) !=1 ) { + printf("%s: *** ERROR: Invalid Backup GPT***\n",
disk/part_efi.c +4
-0+ __func__); +return -1 ; + }else { + printf("%s: *** Using Backup GPT***\n",
disk/part_efi.c +10
-0+ __func__); + } + } + + guid_bin = (unsigned char *)(gpt_head->disk_guid.b); +uuid_bin_to_str (guid_bin, guid,UUID_STR_FORMAT_GUID ); + +return 0 ; +} +void part_print_efi (struct blk_desc *dev_desc) { ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1,
dev_desc->blksz); diff --git a/doc/README.gpt b/doc/README.gpt index 3fcd835..c0779a4 100644doc/README.gpt +0
-0@@ -171,7 +171,8 @@ To restore GUID partition table one needs to: The fields 'uuid' and 'uuid_disk' are optional if
CONFIG_RANDOM_UUIDis enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set todoc/README.gpt +1
-1- the generated UUID. + the generated UUID. The 'gpt guid' command reads the currentvalue of the
+uuid_diskfrom the GPT.The field 'bootable' is optional, it is used to mark the GPT
partition bootable (set attribute flags "Legacy BIOS bootable").include/part.h +4
-0@@ -371,6 +371,21 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head, int gpt_verify_partitions(structblk_desc *dev_desc,disk_partition_t *partitions,int parts,gpt_header *gpt_head,gpt_entry **gpt_pte); + + +/** +* get_disk_guid() - Function to read the GUID string from a device's GPT
+ *
+ * This function reads the GUID string from a block device whose descriptor
+ * is provided.
+ *
+ * @paramdev_desc- block device descriptor
+ * @param guid - pre-allocated string in which to return the GUID
+ *
+ * @return - '0' on success, otherwise error
+ */
include/part.h int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head, · line 391
Quoted 5 lines
include/part.h +2
-0+int get_disk_guid (struct blk_desc *dev_desc,char *guid); +#endif #if CONFIG_IS_ENABLED (DOS_PARTITION )
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 3/6 GPT: add accessor function for disk GUID
Hi,
Quoted 11 lines · On Wed, 31 May 2017 09:44:43 +0200 Lukasz Majewski wrote:
Hi Alison,
Quoted 6 lines
From: Alison Chaiken <[email protected]>
In order to read the GPT, modify the partition name strings, and then write out a new GPT, the disk GUID is needed. While there is an existing accessor for the partition UUIDs, there is none yet for the disk GUID.
Acked-by Lukasz Majewski <[email protected]>
Did you read my comments on this patch in:
<[email protected]>
e.g.:
|> + if (argc == 5) |> + strcpy(varname, argv[4]); |> |You didn't allocate any memory for varname and copy the argument string |to a NULL pointer! |Maybe use strdup() and free varname after use?
Lothar Waßmann
PATCH v2 4/6 GPT: read partition table from device into a data structure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
--- cmd/gpt.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 8 +++++ 2 files changed, 120 insertions(+)
cmd/gpt.c +112 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +memset (newpart,'\0' ,sizeof (newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); +memset (newpart->gpt_part_info.name +31 ,'\0' ,1 ); +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,PART_TYPE_LEN ); +memset (newpart->gpt_part_info.type +31 ,'\0' ,1 ); + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as u-boot does */ +int valid_parts =1 , p, ret =0 ; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && (valid_parts >=2 )) +return -1 ; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -457,6 +565,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc ==5 )strcpy (varname, argv[4 ]);return do_disk_guid (blk_dev_desc, varname); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -479,6 +589,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +8 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -49,6 +50,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 16 typedef struct disk_partition { lbaint_t start; /* # of first block in partition */
@@ -68,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH v2 4/6 GPT: read partition table from device into a data structure
Quoted 27 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 8 +++++ 2 files changed, 120 insertions(+)cmd/gpt.c +3
-0@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 162
Quoted 9 lines
cmd/gpt.c +5
-0@@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) {
empty line between declarations and code?
cmd/gpt.c static bool found_key(const char *str, const char *key)
Quoted 11 lines
cmd/gpt.c +10
-0+ curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart));
useless type cast. malloc returns a void pointer which can be assigned to any typed pointer without a cast.
cmd/gpt.c static bool found_key(const char *str, const char *key)
Quoted 3 lines
cmd/gpt.c +2
-0+memset (newpart,'\0' ,sizeof (newpart)); +if (!newpart)
This NULL check should be done before the memset()!
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 180
Quoted 7 lines
cmd/gpt.c +7
-0+return ERR_PTR (-ENOMEM ); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); +memset (newpart->gpt_part_info.name +31 ,'\0' ,1 );
newpart->gpt_part_info.name[PART_NAME_LEN - 1] = '\0';
1. No need for memset here.
2. You are copying PART_NAME_LEN bytes, but set the byte at pos 31 to '\0'. => This code will blow up if PART_NAME_LEN is changed to a
different value!
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 182
Quoted 2 lines
cmd/gpt.c +2
-0+strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,PART_TYPE_LEN ); +memset (newpart->gpt_part_info.type +31 ,'\0' ,1 );
dto.
Quoted 29 lines
cmd/gpt.c +28
-0+ newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" );
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 220
Quoted 10 lines
cmd/gpt.c +10
-0+ } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as u-boot does */
s/u-boot/U-Boot/
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 221
Quoted 2 lines
cmd/gpt.c +1
-0+int valid_parts =1 , p, ret =0 ;
No need to initialize ret here (no need to declare it here either).
Quoted 4 lines
cmd/gpt.c +3
-0+disk_partition_t info; +struct disk_part *new_disk_part; +
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 234
Quoted 10 lines
cmd/gpt.c +10
-0+if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && (valid_parts >=2 ))
No need for () around the '>=' expression.
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 235
Quoted 1 line
cmd/gpt.c +1
-0+return -1 ;
You return -ENODEV lateron, so you should return a valid errno value here. -1 (-EPERM) is most probably not the error code you want to use here.
Quoted 13 lines
cmd/gpt.c +12
-0+list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */
cmd/gpt.c static bool found_key(const char *str, const char *key) · line 258
Quoted 10 lines
cmd/gpt.c +10
-0+static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret;
Since the return value of this function is passed on as the exit code of the calling CMD handler it should be one of CMD_RET_SUCCESS or CMD_RET_FAILURE:
return ret ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
But see my comment below!
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 570
Quoted 10 lines
cmd/gpt.c +2
-0/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free! @@ -457,6 +565,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc ==5 )strcpy (varname, argv[4 ]);return do_disk_guid (blk_dev_desc, varname); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc);
If you have a careful look at the succeeding code in this function you would see, that it does not blindly pass on the return value of the functions called for each subcommand but does:
| if (ret) {
| printf("error!\n");
| return CMD_RET_FAILURE;
| }
|
| printf("success!\n");
| return CMD_RET_SUCCESS;So you should just assign the return value of do_disk_guid() and do_get_gpt_info() to the variable 'ret' and let the original code handle it.
Quoted 25 lines
cmd/gpt.c +0
-0}else {return CMD_RET_USAGE ;cmd/gpt.c +2
-0}@@ -479,6 +589,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n" include/part.h +1
-0@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
include/part.h struct block_drvr { · line 54
Quoted 5 lines
include/part.h +1
-0@@ -49,6 +50,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 16
Why the hard limit to 16 partitions?
A standard Android system will jump right in your face with this limit.
Lothar Waßmann
Signature · 9 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
Chaiken
PATCH v2 4/6 GPT: read partition table from device into a data structure
On 2017-05-30 00:37, Lothar Waßmann wrote:
[ SNIP]
Quoted 3 lines
Quoted 1 line
+#define
MAX_SEARCH_PARTITIONS16Why the hard limit to 16 partitions?
A standard Android system will jump right in your face with this limit.
Lothar, I'm working on making the other changes you suggested. Meanwhile, the answer to this question is that I copied the macro from a header file in 2015.07, which is the version for which I developed the
patches. I saw no equivalent value in this latest release of Das
U-Boot. Do you have a better suggestion? Is there a similar macro
elsewhere that I failed to discover?
Thanks,
Alison
---
Alison Chaiken alison at she-devel.com, 650-279-5600
http://{ she-devel.com, exerciseforthereader.org }
"We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
PATCH v2 4/6 GPT: read partition table from device into a data structure
Quoted 6 lines · Alison
On 2017-05-30 00:37, Lothar Waßmann wrote:
[ SNIP]Quoted 3 lines
Quoted 1 line
+#define
MAX_SEARCH_PARTITIONS16Why the hard limit to 16 partitions?
A standard Android system will jump right in your face with this limit.
Quoted 7 lines
Lothar, I'm working on making the other changes you suggested. Meanwhile, the answer to this question is that I copied the macro from a header file in 2015.07, which is the version for which I developed the
patches. I saw no equivalent value in this latest release of Das
U-Boot. Do you have a better suggestion? Is there a similar macro
elsewhere that I failed to discover?
I'm just concerned, that the limit may be too low for a certain class of systems and see no reason why it shouldn't be set higher. There is no memory allocation involved that would consume more memory with a higher limit.
I'v seen, the macro is defined in disk/part.c. Maybe for consistency this should be defined in some header file and used in the original place and your patch.
Lothar Waßmann
Signature · 9 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
PATCH v2 4/6 GPT: read partition table from device into a data structure
In reply to alison at peloton-tech.comHi Alison,
Quoted 5 lines
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
Quoted 183 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/part.h| 8 +++++ 2 files changed, 120 insertions(+)cmd/gpt.c +31
-0@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}' @@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key) return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info, int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +memset (newpart,'\0' ,sizeof (newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); +memset (newpart->gpt_part_info.name +31 ,'\0' ,1 ); +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type,PART_TYPE_LEN ); +memset (newpart->gpt_part_info.type +31 ,'\0' ,1 ); + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS + strncpy(newpart->gpt_part_info.uuid, (const char*)info->uuid,
cmd/gpt.c +16
-0+ UUID_STR_LEN); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); + printf("1st block %x, size %x\n",(unsigned)curr->gpt_part_info.start,
cmd/gpt.c +2
-0+ (unsigned)curr->gpt_part_info.size); + printf("Block size %lu, name %s\n",
curr->gpt_part_info.blksz,cmd/gpt.c +2
-0+ curr->gpt_part_info.name); + printf("Type %s, bootable %d\n",
curr->gpt_part_info.type,cmd/gpt.c +28
-0+ curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as u-boot does */ +int valid_parts =1 , p, ret =0 ; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part = allocate_disk_part(&info,
valid_parts);cmd/gpt.c +4
-0+if (IS_ERR (new_disk_part) && (valid_parts >=2 )) +return -1 ; + + list_add_tail(&new_disk_part->list,
&disk_partitions);cmd/gpt.c +28
-0+ valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free! @@ -457,6 +565,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc == 5) strcpy(varname, argv[4]);return do_disk_guid (blk_dev_desc, varname); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }@@ -479,6 +589,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n" include/part.h +2
-0@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;@@ -49,6 +50,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 16 typedef struct disk_partition { lbaint_t start; /* # of first block inpartition */ @@ -68,6 +70,12 @@ typedef struct
disk_partition{
#endif
}disk_partition_t;
include/part.h typedef struct disk_partition { · line 81
Quoted 9 lines
include/part.h +6
-0+struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 4/6 GPT: read partition table from device into a data structure
Hi,
Quoted 10 lines · On Wed, 31 May 2017 09:48:45 +0200 Lukasz Majewski wrote:
Hi Alison,
Quoted 5 lines
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.Acked-by Lukasz Majewski <[email protected]>
You definitely should read other peoples comments on patches before blindly Acking them!
Lothar Waßmann
PATCH v2 4/6 GPT: read partition table from device into a data structure
Quoted 7 lines · On Wed, 31 May 2017 10:48:59 +0200 Lothar Waßmann <[email protected]>…
Hi,
Quoted 4 lines · On Wed, 31 May 2017 09:48:45 +0200 Lukasz Majewski wrote:
Hi Alison,
Quoted 2 lines
From: Alison Chaiken <[email protected]>
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Make the partition table available for modification by reading it
from the user-specified device into a linked list. Provide an
accessor function for command-line testing.Acked-by Lukasz Majewski <[email protected]>You definitely should read other peoples comments on patches before blindly Acking them!
Your reply to the original thread (v1):
From: Lothar Waßmann <[email protected]>
To: alison at peloton-tech.com
Cc: u-boot at lists.denx.de, alison at she-devel.com, trini at konsulko.com
I was not added to TO/CC.
And unfortunately (from the lack of time) - I don't have time to promptly reply/see all the responses to the ML.
Alison sent v2 on Mon (to which I was added to CC).
I've assumed that this was fixed for v2. Wasn't it?
Quoted 3 lines
Lothar Waßmann
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 4/6 GPT: read partition table from device into a data structure
Quoted 27 lines · Lukasz Majewski
Quoted 7 lines · On Wed, 31 May 2017 10:48:59 +0200 Lothar Waßmann <[email protected]>…
Hi,
Quoted 4 lines · On Wed, 31 May 2017 09:48:45 +0200 Lukasz Majewski wrote:
Hi Alison,
Quoted 2 lines
From: Alison Chaiken <[email protected]>
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Make the partition table available for modification by reading it
from the user-specified device into a linked list. Provide an
accessor function for command-line testing.Acked-by Lukasz Majewski <[email protected]>You definitely should read other peoples comments on patches before blindly Acking them!
Your reply to the original thread (v1):
From: Lothar Waßmann <[email protected]>
To: alison at peloton-tech.com
Cc: u-boot at lists.denx.de, alison at she-devel.com, trini at konsulko.comI was not added to TO/CC.
Quoted 8 lines
And unfortunately (from the lack of time) - I don't have time to promptly reply/see all the responses to the ML.
Alison sent v2 on Mon (to which I was added to CC).
I've assumed that this was fixed for v2. Wasn't it?
I replied to his v2 patch.
Lothar Waßmann
Signature · 9 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
PATCH v2 4/6 GPT: read partition table from device into a data structure
In reply to Lukasz MajewskiHi Alison,
Quoted 9 lines
Hi Alison,
Quoted 5 lines
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it
from the user-specified device into a linked list. Provide an
accessor function for command-line testing.Acked-by Lukasz Majewski <[email protected]>
Sorry, but I was to fast.
Please fix problems pointed out by Lothar.
Quoted 204 lines
Quoted 185 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/part.h| 8 +++++ 2 files changed, 120 insertions(+)cmd/gpt.c +27
-0@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> +Lothar Waßmann <[email protected]> +static LIST_HEAD(disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}' @@ -151,6 +154,111 @@ static bool found_key(const char *str, const char *key) return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info, int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +memset (newpart,'\0' ,sizeof (newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name,PART_NAME_LEN ); +memset (newpart->gpt_part_info.name +31 ,'\0' ,1 ); + strncpy((char *)newpart->gpt_part_info.type, (const char*)info->type,
PART_TYPE_LEN);cmd/gpt.c +4
-0+memset (newpart->gpt_part_info.type +31 ,'\0' ,1 ); + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS + strncpy(newpart->gpt_part_info.uuid, (const char*)info->uuid,
cmd/gpt.c +16
-0+ UUID_STR_LEN); +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); + printf("1st block %x, size %x\n",(unsigned)curr->gpt_part_info.start,
cmd/gpt.c +2
-0+ (unsigned)curr->gpt_part_info.size); + printf("Block size %lu, name %s\n",
curr->gpt_part_info.blksz,cmd/gpt.c +2
-0+ curr->gpt_part_info.name); + printf("Type %s, bootable %d\n",
curr->gpt_part_info.type,cmd/gpt.c +28
-0+ curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as u-boot does */ +int valid_parts =1 , p, ret =0 ; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part = allocate_disk_part(&info,
valid_parts);cmd/gpt.c +4
-0+if (IS_ERR (new_disk_part) && (valid_parts >=2 )) +return -1 ; + + list_add_tail(&new_disk_part->list,
&disk_partitions);cmd/gpt.c +28
-0+ valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free! @@ -457,6 +565,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc == 5) strcpy(varname, argv[4]);return do_disk_guid (blk_dev_desc, varname); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }@@ -479,6 +589,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n" include/part.h +2
-0@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;@@ -49,6 +50,7 @@ struct block_drvr {#define PART_NAME_LEN 32#define PART_TYPE_LEN 32 +#define MAX_SEARCH_PARTITIONS 16 typedef struct disk_partition { lbaint_t start; /* # of first block inpartition */ @@ -68,6 +70,12 @@ typedef struct
disk_partition{ #endif
}disk_partition_t;include/part.h typedef struct disk_partition { · line 81
Quoted 9 lines
include/part.h +6
-0+struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /** Best regards,
Lukasz Majewski
--
Quoted 7 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 5/6 rename GPT partitions to detect boot failure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command which is enabled via a CONFIG_CMD_GPT_FLIP option.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it renames it failed’ and renames the ‘backup’ partition as ‘candidate’.
Logic:
-- Partitions can go to ‘failed’ only from ‘candidate’ and only
via u-boot. Partitions can go to ‘backup’ only from ‘primary’ and vice-versa, only via Linux. Partitions go to ‘candidate’ from ‘primary’ or ‘backup’ only via u-boot. Only system update software will rename 'failed' partitions.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
--- cmd/Kconfig | 7 ++ cmd/gpt.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 13 ++++ 3 files changed, 215 insertions(+), 4 deletions(-)
cmd/Kconfig +7 -0
@@ -575,6 +575,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +195 -4
253 lines not on this page · raw message
doc/README.gpt +13 -0
@@ -210,6 +210,19 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read' and 'gpt flip' commands facilitate programmatic renaming of +partitions from bootscripts by generating and modifying the partitions +layout string. The code in gpt_flip() illustrates the case of +swapping 'primary' and 'backup' partitions via: + +U-BOOT> gpt flip mmc 0 + +Choose different partition names by modifying these strings in gpt.c. Partition type GUID: ====================
Signature · 1 line
2.1.4
PATCH v2 5/6 rename GPT partitions to detect boot failure
Quoted 219 lines · alison at peloton-tech.com
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command which is enabled via a
CONFIG_CMD_GPT_FLIPoption.The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it renames it failed’ and renames the ‘backup’ partition as ‘candidate’.Logic:
-- Partitions can go to ‘failed’ only from ‘candidate’ and only
via u-boot. Partitions can go to ‘backup’ only from ‘primary’ and vice-versa, only via Linux. Partitions go to ‘candidate’ from ‘primary’ or ‘backup’ only via u-boot. Only system update software will rename 'failed' partitions.Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Signed-off-by Alison Chaiken <[email protected]>--- cmd/Kconfig | 7 ++ cmd/gpt.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 13 ++++ 3 files changed, 215 insertions(+), 4 deletions(-)cmd/Kconfig +7
-0@@ -575,6 +575,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"cmd/gpt.c +111
-4@@ -20,6 +20,7 @@#include <div64.h> #include <memalign.h> #include <linux/compat.h> +#include <linux/sizes.h> static LIST_HEAD (disk_partitions);@@ -190,16 +191,33 @@ static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum)return newpart; } +static void prettyprint_part_size (char *sizestr,unsigned long partsize, +unsigned long blksize) +{ +unsigned long long partbytes; +unsigned long partmegabytes; + + partbytes = partsize * blksize; + partmegabytes =lldiv (partbytes,SZ_1M ); +snprintf (sizestr,16 ,"%luMiB" , partmegabytes); +} +static void print_gpt_info (void ) {struct list_head *pos;struct disk_part *curr; +char partstartstr[16 ]; +char partsizestr[16 ];list_for_each (pos, &disk_partitions) { curr = list_entry(pos, struct disk_part, list); +prettyprint_part_size (partstartstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +prettyprint_part_size (partsizestr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +printf ("Partition %d:\n" , curr->partnum); -printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, - (unsigned )curr->gpt_part_info.size); +printf ("Start %s, size %s\n" , partstartstr, partsizestr);printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, curr->gpt_part_info.name); printf("Type %s, bootable %d\n", curr->gpt_part_info.type,@@ -211,6 +229,85 @@ static void print_gpt_info(void) } } +#ifdef CONFIG_CMD_GPT_FLIP +static int calc_parts_list_len (int numparts) +{ +/* +* prefatory string: +* doc/README.GPT, suggests that +* int partlistlen = UUID_STR_LEN + 1 + strlen("partitions=uuid_disk="); +* is correct, but extract_val() expects "uuid_disk" first. +*/ +int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" ); +/* for the comma */ + partlistlen++; + +/* per-partition additions; numparts starts at 1, so this should be correct */ + partlistlen += numparts * (strlen ("name=," ) +PART_NAME_LEN +1 ); +/* 17 because partstr in create_gpt_partitions_list() is 16 chars */ + partlistlen += numparts * (strlen ("start=MiB," ) +17 ); + partlistlen += numparts * (strlen ("size=MiB," ) +17 ); + partlistlen += numparts * (strlen ("uuid=;" ) +UUID_STR_LEN +1 ); +/* for the terminating null */ + partlistlen++; +debug ("Length of partitions_list is %d for %d partitions\n" , partlistlen, + numparts); +return partlistlen; +} + +/* +* create the string that upstream 'gpt write' command will accept as an +* argument +* +* From doc/README.gpt, Format of partitions layout: +* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* name=kernel,size=60MiB,uuid=...;" +* The fields 'name' and 'size' are mandatory for every partition. +* The field 'start' is optional. The fields 'uuid' and 'uuid_disk' +* are optional if CONFIG_RANDOM_UUID is enabled. +*/ +static int create_gpt_partitions_list (int numparts,const char *guid,char *partitions_list) +{ +struct list_head *pos; +struct disk_part *curr; +char partstr[PART_NAME_LEN +1 ]; + +if (!partitions_list) +return -1 ; + +/* +* README.gpt specifies starting with "partitions=" like so: +* strcpy(partitions_list, "partitions=uuid_disk="); +* but that breaks extract_val, which doesn't skip over 'partitions='. +*/ +strcpy (partitions_list,"uuid_disk=" ); +strncat (partitions_list, guid,UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +strcat (partitions_list,"name=" ); +strncat (partitions_list, (const char *)curr->gpt_part_info.name,PART_NAME_LEN +1 ); +strcat (partitions_list,",start=" ); +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); +/* one extra byte for NULL */ +strncat (partitions_list, partstr,PART_NAME_LEN +1 ); +strcat (partitions_list,",size=" ); +/* lbaint_t is unsigned long, per include/ide.h */ +prettyprint_part_size (partstr, (unsigned long )curr->gpt_part_info.size, + (unsigned long ) curr->gpt_part_info.blksz); +strncat (partitions_list, partstr,PART_NAME_LEN +1 ); + +strcat (partitions_list,",uuid=" ); +strncat (partitions_list, (const char *)curr->gpt_part_info.uuid, +UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + } +return 0 ; +} +#endif +/* * read partition info into disk_partitions list where * it can be printed or modified @@ -222,8 +319,11 @@ static int get_gpt_info(struct blk_desc *dev_desc)disk_partition_t info;struct disk_part *new_disk_part; -if (disk_partitions.next ==NULL ) -INIT_LIST_HEAD (&disk_partitions); +/* +* Always re-read partition info from device, in case +* it has changed +*/ +INIT_LIST_HEAD (&disk_partitions);for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { ret =part_get_info (dev_desc, p, &info);@@ -294,6 +394,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,return -1 ; str =strdup (str_part); +if (str ==NULL ) +return -ENOMEM ;/* extract disk guid */ s = str;@@ -523,6 +625,86 @@ static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)return 0 ; } +#ifdef CONFIG_CMD_GPT_FLIP +static int do_flip_gpt_parts (struct blk_desc *dev_desc) +{ +struct list_head *pos; +struct disk_part *curr;
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 642
Quoted 10 lines
cmd/gpt.c +9
-0+disk_partition_t *new_partitions =NULL ; +char disk_guid[UUID_STR_LEN +1 ]; +char *partitions_list, *str_disk_guid; +u8 part_count =0 ; +int partlistlen, ret, numparts =0 ; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return ret;
This function should return either CMD_RET_FAILURE or CMD_RET_SUCCESS, since the return value is passed on as the exit code of the calling CMD handler function!
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 645
Quoted 4 lines
cmd/gpt.c +4
-0+ + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts;
see above.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 656
Quoted 11 lines
cmd/gpt.c +11
-0+printf ("Current partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + + partlistlen =calc_parts_list_len (numparts); + partitions_list = (char *)malloc (partlistlen); +memset (partitions_list,'\0' , partlistlen); + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, + partitions_list); +if (ret <0 ) +return ret;
see above.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 662
Quoted 6 lines
cmd/gpt.c +6
-0+debug ("OLD partitions_list is %s with %d chars\n" , partitions_list,strlen (partitions_list)); + + ret =set_gpt_info (dev_desc, (const char *)partitions_list, &str_disk_guid, + &new_partitions, &part_count); +if (ret <0 ) +return ret;
see above.
Quoted 6 lines
cmd/gpt.c +6
-0+ +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +if (!strcmp ((char *)curr->gpt_part_info.name,"backup_kernel" )) +strcpy ((char *)curr->gpt_part_info.name,"candidate_kernel" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"primary_kernel" ))
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 678
Quoted 10 lines
cmd/gpt.c +10
-0+strcpy ((char *)curr->gpt_part_info.name,"backup_kernel" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"backup_rootfs" )) +strcpy ((char *)curr->gpt_part_info.name,"candidate_rootfs" ); +if (!strcmp ((char *)curr->gpt_part_info.name,"primary_rootfs" )) +strcpy ((char *)curr->gpt_part_info.name,"backup_rootfs" ); + } + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, partitions_list); +if (ret <0 ) +return ret;
see above.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 684
Quoted 6 lines
cmd/gpt.c +6
-0+debug ("NEW partitions_list is %s with %d chars\n" , partitions_list,strlen (partitions_list)); + + ret =set_gpt_info (dev_desc, (const char *)partitions_list, &str_disk_guid, + &new_partitions, &part_count); +if (ret <0 ) +return ret;
see above.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 690
Quoted 5 lines
cmd/gpt.c +5
-0+debug ("Writing new partition table\n" ); + ret =gpt_restore (dev_desc, disk_guid, new_partitions, numparts); +if (ret <0 ) { +printf ("Writing new partition table failed\n" ); +return ret;
see above.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 696
Quoted 6 lines
cmd/gpt.c +6
-0+ } + +debug ("Reading back new partition table\n" ); + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts;
see above.
cmd/gpt.c static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) · line 704
Quoted 8 lines
cmd/gpt.c +8
-0+printf ("new partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + +del_gpt_info (); +free (partitions_list); +free (str_disk_guid); +free (new_partitions); +return ret;
see above.
Quoted 7 lines
cmd/gpt.c +3
-0+} +#endif +/** * do_gpt(): Perform GPT operations *
cmd/gpt.c static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 755
Quoted 7 lines
cmd/gpt.c +3
-0@@ -567,6 +749,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return do_disk_guid (blk_dev_desc, varname); }else if (strcmp (argv[1 ],"read" ) ==0 ) {return do_get_gpt_info (blk_dev_desc); +#ifdef CONFIG_CMD_GPT_FLIP + }else if (strcmp (argv[1 ],"flip" ) ==0 ) { +return do_flip_gpt_parts (blk_dev_desc);
Either make do_flip_gpt_part() return CMD_RET_... as indicated above, or check its return value here and convert it to CMD_RET_SUCCESS or CMD_RET_FAILURE.
Also see my comment to your patch 4/6 concerning this code location.
Lothar Waßmann
Signature · 9 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Geschäftsführer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
PATCH v2 5/6 rename GPT partitions to detect boot failure
In reply to alison at peloton-tech.comHi Alison,
Quoted 370 lines
From: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command which is enabled via a
CONFIG_CMD_GPT_FLIPoption.The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it renames it failed’ and renames the ‘backup’ partition as ‘candidate’.Logic:
-- Partitions can go to ‘failed’ only from ‘candidate’ and only
via u-boot. Partitions can go to ‘backup’ only from ‘primary’ and vice-versa, only via Linux. Partitions go to ‘candidate’ from ‘primary’ or ‘backup’ only via u-boot. Only system update software will rename 'failed' partitions.Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type
PARTITION_BASIC_DATA_GUIDis hard-coded in thegpt_fill_pte()function. This does not appear to cause any harm.Signed-off-by Alison Chaiken <[email protected]>--- cmd/Kconfig | 7 ++ cmd/gpt.c | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++--
doc/README.gpt | 13 ++++ 3 files changed, 215 insertions(+), 4 deletions(-)cmd/Kconfig +0
-0@@ -575,6 +575,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT stylepartition tables.
cmd/Kconfig +7
-0+config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"cmd/gpt.c +18
-0@@ -20,6 +20,7 @@#include <div64.h> #include <memalign.h> #include <linux/compat.h> +#include <linux/sizes.h> static LIST_HEAD (disk_partitions);@@ -190,16 +191,33 @@ static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum) return newpart; } +static void prettyprint_part_size (char *sizestr,unsigned long partsize, +unsigned long blksize) +{ +unsigned long long partbytes; +unsigned long partmegabytes; + + partbytes = partsize * blksize; + partmegabytes =lldiv (partbytes,SZ_1M ); +snprintf (sizestr,16 ,"%luMiB" , partmegabytes); +} +static void print_gpt_info (void ) {struct list_head *pos;struct disk_part *curr; +char partstartstr[16 ]; +char partsizestr[16 ];list_for_each (pos, &disk_partitions) { curr = list_entry(pos, struct disk_part, list); +prettyprint_part_size (partstartstr, (unsigned long )curr->gpt_part_info.start, + (unsigned long ) curr->gpt_part_info.blksz); + prettyprint_part_size(partsizestr, (unsigned long)curr->gpt_part_info.size, + (unsigned long)
curr->gpt_part_info.blksz); +cmd/gpt.c +0
-1printf ("Partition %d:\n" , curr->partnum); - printf("1st block %x, size %x\n",(unsigned)curr->gpt_part_info.start,
cmd/gpt.c +1
-1- (unsigned)curr->gpt_part_info.size); + printf("Start %s, size %s\n", partstartstr,partsizestr);
printf("Block size %lu, name %s\n", curr->gpt_part_info.blksz, curr->gpt_part_info.name);
printf("Type %s, bootable %d\n",curr->gpt_part_info.type, @@ -211,6 +229,85 @@ static voidprint_gpt_info(void)}
}cmd/gpt.c +7
-0+#ifdef CONFIG_CMD_GPT_FLIP +static int calc_parts_list_len (int numparts) +{ +/* +* prefatory string: +* doc/README.GPT, suggests that +* int partlistlen = UUID_STR_LEN + 1 +
strlen("partitions=uuid_disk=");cmd/gpt.c +7
-0+* is correct, but extract_val() expects "uuid_disk" first. +*/ +int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" ); +/* for the comma */ + partlistlen++; + +/* per-partition additions; numparts starts at 1, so this should be correct */
cmd/gpt.c +3
-0+ partlistlen += numparts * (strlen ("name=," ) +PART_NAME_LEN + 1); +/* 17 because partstr in create_gpt_partitions_list() is 16 chars */
cmd/gpt.c +3
-0+ partlistlen += numparts * (strlen ("start=MiB," ) +17 ); + partlistlen += numparts * (strlen ("size=MiB," ) +17 ); + partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN +1);
cmd/gpt.c +3
-0+/* for the terminating null */ + partlistlen++; + debug("Length of partitions_list is %d for %d partitions\n",partlistlen,
cmd/gpt.c +6
-0+ numparts); +return partlistlen; +} + +/* +* create the string that upstream 'gpt write' command will accept as an
+ * argument
+ *
+ * From doc/README.gpt, Format of partitions layout:
+ * "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
+ * name=kernel,size=60MiB,uuid=...;"
+ * The fields 'name' and 'size' are mandatory for every partition.
+ * The field 'start' is optional. The fields 'uuid' and 'uuid_disk'
+ * are optional ifCONFIG_RANDOM_UUIDis enabled.
+ */
+static intcreate_gpt_partitions_list(int numparts, const char *guid, char *partitions_list)+{cmd/gpt.c +11
-0+struct list_head *pos; +struct disk_part *curr; +char partstr[PART_NAME_LEN +1 ]; + +if (!partitions_list) +return -1 ; + +/* +* README.gpt specifies starting with "partitions=" like so: +* strcpy(partitions_list, "partitions=uuid_disk="); +* but that breaks extract_val, which doesn't skip over 'partitions='.
cmd/gpt.c +9
-0+*/ +strcpy (partitions_list,"uuid_disk=" ); +strncat (partitions_list, guid,UUID_STR_LEN +1 ); +strcat (partitions_list,";" ); + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +strcat (partitions_list,"name=" ); + strncat(partitions_list, (const char*)curr->gpt_part_info.name,
PART_NAME_LEN+ 1);cmd/gpt.c +2
-0+strcat (partitions_list,",start=" ); + prettyprint_part_size(partstr, (unsignedlong)curr->gpt_part_info.start,
cmd/gpt.c +1
-0+ (unsigned long)
curr->gpt_part_info.blksz);cmd/gpt.c +5
-0+/* one extra byte for NULL */ +strncat (partitions_list, partstr,PART_NAME_LEN +1 ); +strcat (partitions_list,",size=" ); +/* lbaint_t is unsigned long, per include/ide.h */ + prettyprint_part_size(partstr, (unsignedlong)curr->gpt_part_info.size,
cmd/gpt.c +1
-0+ (unsigned long)
curr->gpt_part_info.blksz);cmd/gpt.c +4
-0+strncat (partitions_list, partstr,PART_NAME_LEN +1 ); + +strcat (partitions_list,",uuid=" ); + strncat(partitions_list, (const char*)curr->gpt_part_info.uuid,
cmd/gpt.c +44
-2+ UUID_STR_LEN + 1); + strcat(partitions_list, ";"); + } +return 0 ; +} +#endif +/* * read partition info into disk_partitions list where * it can be printed or modified @@ -222,8 +319,11 @@ static int get_gpt_info(struct blk_desc *dev_desc) disk_partition_t info;struct disk_part *new_disk_part; -if (disk_partitions.next ==NULL ) -INIT_LIST_HEAD (&disk_partitions); +/* +* Always re-read partition info from device, in case +* it has changed +*/ +INIT_LIST_HEAD (&disk_partitions);for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { ret =part_get_info (dev_desc, p, &info);@@ -294,6 +394,8 @@ static int set_gpt_info(struct blk_desc *dev_desc,return -1 ; str =strdup (str_part); +if (str ==NULL ) +return -ENOMEM ;/* extract disk guid */ s = str;@@ -523,6 +625,86 @@ static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) return 0; } +#ifdef CONFIG_CMD_GPT_FLIP +static int do_flip_gpt_parts (struct blk_desc *dev_desc) +{ +struct list_head *pos; +struct disk_part *curr; +disk_partition_t *new_partitions =NULL ; +char disk_guid[UUID_STR_LEN +1 ]; +char *partitions_list, *str_disk_guid; +u8 part_count =0 ; +int partlistlen, ret, numparts =0 ; + + ret =get_disk_guid (dev_desc, disk_guid); +if (ret <0 ) +return ret; + + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; +printf ("Current partition table with %d partitions is:\n" , numparts); +print_gpt_info (); + + partlistlen =calc_parts_list_len (numparts); + partitions_list = (char *)malloc (partlistlen); +memset (partitions_list,'\0' , partlistlen); + + ret =create_gpt_partitions_list (numparts, (const char *) disk_guid, + partitions_list); +if (ret <0 ) +return ret; + debug("OLD partitions_list is %s with %d chars\n",
partitions_list,strlen(partitions_list)); +cmd/gpt.c +1
-0+ ret = set_gpt_info(dev_desc, (const char *)partitions_list,
&str_disk_guid,cmd/gpt.c +7
-0+ &new_partitions, &part_count); +if (ret <0 ) +return ret; + + list_for_each(pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); + if (!strcmp((char *)curr->gpt_part_info.name,"
backup_kernel"))cmd/gpt.c +1
-0+ strcpy((char *)curr->gpt_part_info.name,"
candidate_kernel");cmd/gpt.c +1
-0+ if (!strcmp((char *)curr->gpt_part_info.name,"
primary_kernel"))cmd/gpt.c +1
-0+ strcpy((char *)curr->gpt_part_info.name,"
backup_kernel");cmd/gpt.c +1
-0+ if (!strcmp((char *)curr->gpt_part_info.name,"
backup_rootfs"))cmd/gpt.c +1
-0+ strcpy((char *)curr->gpt_part_info.name,"
candidate_rootfs");cmd/gpt.c +1
-0+ if (!strcmp((char *)curr->gpt_part_info.name,"
primary_rootfs"))cmd/gpt.c +1
-0+ strcpy((char *)curr->gpt_part_info.name,"
backup_rootfs");cmd/gpt.c +3
-0+ } + + ret = create_gpt_partitions_list(numparts, (const char *)
disk_guid,partitions_list);cmd/gpt.c +3
-0+if (ret <0 ) +return ret; + debug("NEW partitions_list is %s with %d chars\n",
partitions_list,strlen(partitions_list)); +cmd/gpt.c +1
-0+ ret = set_gpt_info(dev_desc, (const char *)partitions_list,
&str_disk_guid,cmd/gpt.c +6
-0+ &new_partitions, &part_count); +if (ret <0 ) +return ret; + +debug ("Writing new partition table\n" ); + ret = gpt_restore(dev_desc, disk_guid, new_partitions,numparts);
cmd/gpt.c +10
-0+if (ret <0 ) { +printf ("Writing new partition table failed\n" ); +return ret; + } + +debug ("Reading back new partition table\n" ); + numparts =get_gpt_info (dev_desc); +if (numparts <0 ) +return numparts; + printf("new partition table with %d partitions is:\n",numparts);
cmd/gpt.c +18
-0+print_gpt_info (); + +del_gpt_info (); +free (partitions_list); +free (str_disk_guid); +free (new_partitions); + return ret; +} +#endif +/** * do_gpt(): Perform GPT operations * @@ -567,6 +749,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return do_disk_guid(blk_dev_desc,varname ); }else if (strcmp (argv[1 ],"read" ) ==0 ) {return do_get_gpt_info (blk_dev_desc); +#ifdef CONFIG_CMD_GPT_FLIP + }else if (strcmp (argv[1 ],"flip" ) ==0 ) { +return do_flip_gpt_parts (blk_dev_desc); +#endif }else {return CMD_RET_USAGE ; }@@ -598,4 +784,9 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt guid mmc 0\n" " gpt guid mmc 0 varname\n" +#ifdef CONFIG_CMD_GPT_FLIP +"gpt partition-flip command\n" +"gpt flip <interface> <dev>\n" + " - exchange device's 'primary' and 'backup' partitionnames\n" +#endif
);doc/README.gpt +0
-0@@ -210,6 +210,19 @@ Following line can be used to assess if GPTverification has succeed: U-BOOT> gpt verify mmc 0 $partitions
U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fidoc/README.gpt +4
-0+Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Bootcan +communicate about software updates and boot failure. The 'gpt guid', +'gpt read' and 'gpt flip' commands facilitate programmatic renaming of +partitions from bootscripts by generating and modifying the partitions +layout string. The code in
gpt_flip()illustrates the case of +swapping 'primary' and 'backup' partitions via:
doc/README.gpt
Quoted 2 lines
doc/README.gpt +2
-0+ +U-BOOT> gpt flip mmc 0
Maybe it would be better to have
gpt flip mmc 0 <optional parameter 'name'>
(By default we have "primary" and "backup")
In that way we could set other names to GPT partitions without the need to modify the code.
And another request -> Could you consider adding tests for those new gpt commands to the 'sandbox' (sandbox_defconfig) ?
Then you can 'mount' some gpt test image ('host' command) and use it with:
gpt <command> host X .....
Despite above comments - you did a great job :-)
doc/README.gpt Following line can be used to assess if GPT verification has succeed: · line 228
Quoted 5 lines
doc/README.gpt +2
-0+ +Choose different partition names by modifying these strings in gpt.c. Partition type GUID: ====================
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Chaiken
PATCH v2 5/6 rename GPT partitions to detect boot failure
On 2017-05-31 01:12, Lukasz Majewski wrote:
[ SNIP ]
Quoted 8 lines
Maybe it would be better to have
gpt flip mmc 0 <optional parameter 'name'>
(By default we have "primary" and "backup")
In that way we could set other names to GPT partitions without the need to modify the code.
Another possibility is to support
gpt flip mmc 0 <name 1> <name 2>
where two names are required, with defaults 'primary' and 'backup'. Perhaps I should rework patch 5 that way? I considered this form for the original submission, but wasn't sure what other projects might find useful.
Quoted 2 lines
And another request -> Could you consider adding tests for those new gpt commands to the 'sandbox' (
sandbox_defconfig) ?
I will look into adding another patch to do that. I'm sure such tests
are a good idea for our project.
Quoted 1 line
Despite above comments - you did a great job :-)
Thanks. I'm sorry to have omitted you, Lukasz, from the original
submission, but I consulted an old version of MAINTAINERS from my original 2015.07.
-- Alison
---
Alison Chaiken alison at she-devel.com, 650-279-5600
http://{ she-devel.com, exerciseforthereader.org }
"We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
PATCH v2 5/6 rename GPT partitions to detect boot failure
Hi Alison,
Quoted 13 lines · Lukasz Majewski
[ SNIP ]
Quoted 8 lines
Maybe it would be better to have
gpt flip mmc 0 <optional parameter 'name'>
(By default we have "primary" and "backup")
In that way we could set other names to GPT partitions without the need to modify the code.
Quoted 6 lines
Another possibility is to support
gpt flip mmc 0 <name 1> <name 2>
where two names are required, with defaults 'primary' and 'backup'. Perhaps I should rework patch 5 that way?
Please correct my understanding if I'm wrong.
You parse GPT partitions to a list and there are only two names possible:
"primary" and "backup".
When we call gpt filp we rename those names ("primary" -> "backup" and the other way).
Ahhh..... so your patch would allow to rename "primary" to <name1> and "backup" to <name2> for all names.
My idea was rather to have a gpt call to set name of a GPT partition....
Quoted 3 lines
I considered this form for
the original submission, but wasn't sure what other projects might find useful.
I can image that somebody would like to change on the fly single GPT partition name (when having/care about 2 partitions for his/her project specific data).
But, I don't know how much effort it would take to implement it (and if others would see it beneficial).
Quoted 6 lines
Quoted 3 lines
And another request -> Could you consider adding tests for those new gpt commands to the 'sandbox' (
sandbox_defconfig) ?I will look into adding another patch to do that. I'm sure such
tests are a good idea for our project.
It is relatively easy to use sandbox to test some high level stuff (like file systems, gpt, etc). One don't need HW for it.
Quoted 6 lines
Quoted 2 lines
Despite above comments - you did a great job :-)
Thanks. I'm sorry to have omitted you, Lukasz, from the original
submission, but I consulted an old version ofMAINTAINERSfrom my original 2015.07.
It's Ok, don't worry. Things like that do happen....
Quoted 8 lines
-- Alison
---
Alison Chaiken alison at she-devel.com, 650-279-5600
http://{ she-devel.com, exerciseforthereader.org } "We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Chaiken
PATCH v2 5/6 rename GPT partitions to detect boot failure
Quoted 8 lines · Lukasz Majewski
Maybe it would be better to have
gpt flip mmc 0 <optional parameter 'name'>
(By default we have "primary" and "backup")
In that way we could set other names to GPT partitions without the need to modify the code.
I answered:
Quoted 6 lines
Quoted 6 lines
Another possibility is to support
gpt flip mmc 0 <name 1> <name 2>
where two names are required, with defaults 'primary' and 'backup'. Perhaps I should rework patch 5 that way?
Lukasz responded:
Quoted 13 lines
Please correct my understanding if I'm wrong.
You parse GPT partitions to a list and there are only two names possible:
"primary" and "backup".
When we call gpt filp we rename those names ("primary" -> "backup" and the other way).
Ahhh..... so your patch would allow to rename "primary" to <name1> and "backup" to <name2> for all names.
Quoted 8 lines
My idea was rather to have a gpt call to set name of a GPT partition....
I can image that somebody would like to change on the fly single GPT partition name (when having/care about 2 partitions for his/her project specific data).
But, I don't know how much effort it would take to implement it (and if others would see it beneficial).
I would propose then two options:
gpt rename mmc 0 <name 1> <name 2>
which renames all the 1's to 2's, and
gpt flip mmc 0 <name 1> <name 2>
which swaps the two name strings for all partitions where they're found.
These two operations together with 'gpt write' then cover all the
common use cases I can imagine.
I'm open to any other suggestions, of course. I just posted what I
already had to get started.
-- Alison
---
Alison Chaiken alison at she-devel.com, 650-279-5600
http://{ she-devel.com, exerciseforthereader.org }
"We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
PATCH v2 5/6 rename GPT partitions to detect boot failure
Hi Alison,
Quoted 49 lines
Quoted 8 lines · Lukasz Majewski
Maybe it would be better to have
gpt flip mmc 0 <optional parameter 'name'>
(By default we have "primary" and "backup")
In that way we could set other names to GPT partitions without the need to modify the code.
I answered:
Quoted 6 lines
Quoted 6 lines
Another possibility is to support
gpt flip mmc 0 <name 1> <name 2>
where two names are required, with defaults 'primary' and 'backup'. Perhaps I should rework patch 5 that way?
Lukasz responded:
Quoted 16 lines
Please correct my understanding if I'm wrong.
You parse GPT partitions to a list and there are only two names possible:
"primary" and "backup".
When we call gpt filp we rename those names ("primary" -> "backup" and the other way).
Ahhh..... so your patch would allow to rename "primary" to <name1> and "backup" to <name2> for all names.
My idea was rather to have a gpt call to set name of a GPT partition....
Quoted 6 lines
I can image that somebody would like to change on the fly single GPT partition name (when having/care about 2 partitions for his/her project specific data).
But, I don't know how much effort it would take to implement it (and if others would see it beneficial).
I would propose then two options:
gpt rename mmc 0 <name 1> <name 2>
Quoted 7 lines
which renames all the 1's to 2's, and
gpt flip mmc 0 <name 1> <name 2>
which swaps the two name strings for all partitions where they're found. These two operations together with 'gpt write' then cover all the common use cases I can imagine.
I think that this is enough. Let's wait for other's opinions (if any).
Quoted 11 lines
I'm open to any other suggestions, of course. I just posted what I
already had to get started.-- Alison
---
Alison Chaiken alison at she-devel.com,
650-279-5600 http://{ she-devel.com, exerciseforthereader.org } "We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
v4 cover add support for GPT partition name manipulation
In reply to Lukasz MajewskiFrom: Alison Chaiken <[email protected]>
One way for userspace and the bootloader to exchange information about dynamic image selection is via the storage device partition table, as described at
https://source.android.com/devices/tech/ota/ab_updates
The scheme described there relies on setting partitions' "boot" flag. When no partition on a device is bootable since the kernel and U-Boot are stored elsewhere, the name field in the GPT partition table offers another logical place to store information. These patches allow users to easily modify GPT partition names via bootscripts that can select different images based on a boot-failure counter, or when userspace installs a software update.
These patches have been tested in the u-boot sandbox and (re)tested on a TI DRA7xx-based SOM with U-Boot 2015.07.
Significant changes since v3:
-- Testing in sandbox showed error in NULL termination of UUID string
in cmd/gpt.c. That problem is fixed in 0001-GPT-read-partition-table-from-device-into-a-data-str.patch.
-- Patch 3 "GPT: fix error in partitions string doc" now only treats
the topic in the commit title, as the part dealing with the proposed 'flip' feature is moved to that patch.
-- Two new commits come from testing in the sandbox (of which I was
previously unaware). One fixes an error in README.sandbox, and
one adds a few comments about sandbox testing to README.gpt.
Significant changes since v2:
-- Got rid of the need to allocate memory for the GUID string in
do_gpt();
-- Fixed the problems with string NULL termination in
allocate_disk_part();
-- Removed duplicate definition of MAX_SEARCH_PARTITIONS from
disk/part.c and increased the value in include/part.h to 64;
-- Improved the commit message for "rename GPT partitions to detect
boot failure" to better describe the version of the patch I submitted;
-- Fixed numerous small problems with function return values.
Significant changes since v1:
-- Put the gpt_flip() function and auxiliary ones inside a new
CONFIG_CMD_GPT_FLIP option that depends on CMD_GPT.
-- Replace intentional overwriting of name and type string arrays with
memset() instead.
-- Move part.h changes earlier in the patchset.
-- Add a few lines to README.gpt about the new gpt subcommands.
Added a few simple patches to do the following:
-- Replace remaining occurrences of '37' with UUID_STR_LEN+1; -- Introduce new macros to get rid of the similar '32'; -- fix a smaller error in doc/README.gpt.
There are also some fixups of whitespace and formatting errors (plus usual inevitable addition of new ones).
To do in future:
-- Add support for preserving the type flag for partitions. The u-boot
version on which this patchset is based did not have this feature, and it's easy to add, but I need to figure how to test it first.
-- Add tests for the new gpt commands to the sandbox.
Alison Chaiken (5):
GPT: read partition table from device into a data structure rename GPT partitions to detect boot failure
GPT: fix error in partitions string doc
sandbox: README: fix partition command invocation cmd gpt: test in sandbox
board/sandbox/README.sandbox | 2 +- cmd/Kconfig | 7 + cmd/gpt.c | 298 +++++++++++++++++++++++++++++++++++++++++++ doc/README.gpt | 31 ++++- include/part.h | 7 + 5 files changed, 340 insertions(+), 5 deletions(-)
Signature · 1 line
2.1.4
PATCH v4 1/5 GPT: read partition table from device into a data structure
From: Alison Chaiken <[email protected]>
Make the partition table available for modification by reading it from
the user-specified device into a linked list. Provide an accessor
function for command-line testing.
Changes since v3:
Fixed problem with NULL termination of the newly created uuid[]
member of the partitions list in allocate_disk_part. This
version has been tested in the u-boot sandbox.
--- cmd/gpt.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 7 ++++ 2 files changed, 123 insertions(+)
cmd/gpt.c +116 -0
@@ -19,6 +19,9 @@#include <linux/ctype.h> #include <div64.h> #include <memalign.h> +#include <linux/compat.h> + +static LIST_HEAD (disk_partitions);/** * extract_env(): Expand env name from string format '&{env_name}'
@@ -151,6 +154,115 @@ static bool found_key(const char *str, const char *key)return result; } +static void del_gpt_info (void ) +{ +struct list_head *pos = &disk_partitions; +struct disk_part *curr; +while (!list_empty (pos)) { + curr = list_entry(pos->next, struct disk_part, list); +list_del (pos->next); +free (curr); + } +} + +static struct disk_part *allocate_disk_part (disk_partition_t *info,int partnum) +{ +struct disk_part *newpart; + newpart = (struct disk_part *)malloc (sizeof (*newpart)); +if (!newpart) +return ERR_PTR (-ENOMEM ); +memset (newpart,'\0' ,sizeof (newpart)); + + newpart->gpt_part_info.start = info->start; + newpart->gpt_part_info.size = info->size; + newpart->gpt_part_info.blksz = info->blksz; +strncpy ((char *)newpart->gpt_part_info.name, (const char *)info->name, +PART_NAME_LEN ); + newpart->gpt_part_info.name[PART_NAME_LEN -1 ] ='\0' ; +strncpy ((char *)newpart->gpt_part_info.type, (const char *)info->type, +PART_TYPE_LEN ); + newpart->gpt_part_info.type[PART_TYPE_LEN -1 ] ='\0' ; + newpart->gpt_part_info.bootable = info->bootable; +#ifdef CONFIG_PARTITION_UUIDS +strncpy (newpart->gpt_part_info.uuid, (const char *)info->uuid, +UUID_STR_LEN ); +/* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ + newpart->gpt_part_info.uuid[UUID_STR_LEN ] ='\0' ; +#endif + newpart->partnum = partnum; + +return newpart; +} + +static void print_gpt_info (void ) +{ +struct list_head *pos; +struct disk_part *curr; + +list_for_each (pos, &disk_partitions) { + curr = list_entry(pos, struct disk_part, list); +printf ("Partition %d:\n" , curr->partnum); +printf ("1st block %x, size %x\n" , (unsigned )curr->gpt_part_info.start, + (unsigned )curr->gpt_part_info.size); +printf ("Block size %lu, name %s\n" , curr->gpt_part_info.blksz, + curr->gpt_part_info.name); +printf ("Type %s, bootable %d\n" , curr->gpt_part_info.type, + curr->gpt_part_info.bootable); +#ifdef CONFIG_PARTITION_UUIDS +printf ("UUID %s\n" , curr->gpt_part_info.uuid); +#endif +printf ("\n" ); + } +} + +/* +* read partition info into disk_partitions list where +* it can be printed or modified +*/ +static int get_gpt_info (struct blk_desc *dev_desc) +{ +/* start partition numbering at 1, as U-Boot does */ +int valid_parts =1 , p, ret; +disk_partition_t info; +struct disk_part *new_disk_part; + +if (disk_partitions.next ==NULL ) +INIT_LIST_HEAD (&disk_partitions); + +for (p =1 ; p <=MAX_SEARCH_PARTITIONS ; p++) { + ret =part_get_info (dev_desc, p, &info); +if (ret) +continue ; + + new_disk_part =allocate_disk_part (&info, valid_parts); +if (IS_ERR (new_disk_part) && valid_parts >=2 ) +return -ENODEV ; + +list_add_tail (&new_disk_part->list, &disk_partitions); + valid_parts++; + } +if (!valid_parts) { +printf ("** No valid partitions found **\n" ); +del_gpt_info (); +return -ENODEV ; + } +return --valid_parts; +} + +/* a wrapper to test get_gpt_info */ +static int do_get_gpt_info (struct blk_desc *dev_desc) +{ +int ret; + + ret =get_gpt_info (dev_desc); +if (ret >0 ) { +print_gpt_info (); +del_gpt_info (); + } +return ret; +} + +/** * set_gpt_info(): Fill partition information from string * function allocates memory, remember to free!
@@ -455,6 +567,8 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("Verify GPT: " ); }else if (strcmp (argv[1 ],"guid" ) ==0 ) {return do_disk_guid (blk_dev_desc, argv[4 ]); + }else if (strcmp (argv[1 ],"read" ) ==0 ) { +return do_get_gpt_info (blk_dev_desc); }else {return CMD_RET_USAGE ; }
@@ -477,6 +591,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt," Example usage:\n" " gpt write mmc 0 $partitions\n" " gpt verify mmc 0 $partitions\n" +" read <interface> <dev>\n" +" - read GPT into a data structure for manipulation\n" " guid <interface> <dev>\n" " - print disk GUID\n" " guid <interface> <dev> <varname>\n"
include/part.h +7 -0
@@ -10,6 +10,7 @@#include <blk.h> #include <ide.h> #include <uuid.h> +#include <linux/list.h> struct block_drvr {char *name;
@@ -69,6 +70,12 @@ typedef struct disk_partition {#endif } disk_partition_t; +struct disk_part { +int partnum; +disk_partition_t gpt_part_info; +struct list_head list; +}; +/* Misc _get_dev functions */ #ifdef CONFIG_PARTITIONS /**
Signature · 1 line
2.1.4
PATCH v4 2/5 rename GPT partitions to detect boot failure
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
This patch provides support in u-boot for renaming GPT partitions. The renaming is accomplished via a new 'gpt flip' command.
The concept for the bootloader state machine is the following:
-- u-boot renames ‘primary’ partitions as ‘candidate’ and tries
to boot them.
-- Linux, at boot, will rename ‘candidate’ partitions as
‘primary’.
-- If u-boot sees a ‘candidate’ partition after a boot attempt,
it tries to boot the ‘backup’ partition.
Rewriting the partition table has the side-effect that all partitions end up with "msftdata" flag set. The reason is that partition type PARTITION_BASIC_DATA_GUID is hard-coded in the gpt_fill_pte() function. This does not appear to cause any harm.
Changes since v3:
-- Squashed changes to comments that had been made in a different
patch into this one.
-- Fixed lines over 80 chars.
-- Tested in u-boot sandbox.
--- cmd/Kconfig | 7 +++ cmd/gpt.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/README.gpt | 13 ++++ 3 files changed, 206 insertions(+), 4 deletions(-)
cmd/Kconfig +7 -0
@@ -593,6 +593,13 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. +config CMD_GPT_FLIP + bool "GPT flip-partitions command" + depends on CMD_GPT + help + Enables the 'gpt' command to write modified GPT partition + tables via the 'gpt flip' command. + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash"
cmd/gpt.c +186 -4
244 lines not on this page · raw message
doc/README.gpt +13 -0
@@ -210,6 +210,19 @@ Following line can be used to assess if GPT verification has succeed: U-BOOT> gpt verify mmc 0 $partitions U-BOOT> if test $? = 0; then echo "GPT OK"; else echo "GPT ERR"; fi +Renaming GPT partitions from U-Boot: +==================================== + +GPT partition names are a mechanism via which userspace and U-Boot can +communicate about software updates and boot failure. The 'gpt guid', +'gpt read' and 'gpt flip' commands facilitate programmatic renaming of +partitions from bootscripts by generating and modifying the partitions +layout string. The code in gpt_flip() illustrates the case of +swapping 'primary' and 'backup' partitions via: + +U-BOOT> gpt flip mmc 0 + +Choose different partition names by modifying these strings in gpt.c. Partition type GUID: ====================
Signature · 1 line
2.1.4
PATCH v4 3/5 GPT: fix error in partitions string doc
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
The existing partitions-list parsing in cmd/gpt.c passes a value from gpt_default() to set_gpt_info() that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call from set_gpt_info() to extract_val() to find 'uuid_disk' will fail. Change README.gpt accordingly.
Changes since v3:
-- The part of this patch dealing with the partition-flipping
behavior was squashed into the patch that introduces that feature.
--- doc/README.gpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
doc/README.gpt +4 -4
@@ -156,10 +156,10 @@ Creating GPT partitions in U-Boot: To restore GUID partition table one needs to: 1. Define partition layout in the environment. Format of partitions layout: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or - "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + "uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition.
@@ -233,7 +233,7 @@ PARTITION_BASIC_DATA_GUID (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7). If you define 'CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type' can specify a other partition type guid: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=..., type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"
@@ -255,7 +255,7 @@ Some strings can be also used at the place of known GUID : "lvm" = PARTITION_LINUX_LVM_GUID (E6D6D379-F507-44C2-A23C-238F2A3DF928) - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...,type=linux;" They are also used to display the type of partition in "part list" command.
Signature · 1 line
2.1.4
PATCH v4 4/5 sandbox: README: fix partition command invocation
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
The instructions for creating a disk image that are presently in README.sandbox fail because sfdisk doesn't know about GPT.
--- board/sandbox/README.sandbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
board/sandbox/README.sandbox +1 -1
@@ -333,7 +333,7 @@ the contents of the root directory on the second partion of the image A disk image can be created using the following commands: $> truncate -s 1200M ./disk.raw -$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sfdisk ./disk.raw +$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sgdisk ./disk.raw $> lodev=`sudo losetup -P -f --show ./disk.raw` $> sudo mkfs.vfat -n EFI -v ${lodev}p1 $> sudo mkfs.ext4 -L ROOT -v ${lodev}p2
Signature · 1 line
2.1.4
PATCH 4/5 sandbox: README: fix partition command invocation
Quoted 15 lines · On 4 June 2017 at 16:11, <[email protected]> wrote:
From: Alison Chaiken <[email protected]>
The instructions for creating a disk image that are presently in README.sandbox fail because sfdisk doesn't know about GPT.
Signed-off-by Alison Chaiken <[email protected]>--- board/sandbox/README.sandbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)board/sandbox/README.sandbox +0
-0
board/sandbox/README.sandbox the contents of the root directory on the second partion of the image · line 339
Quoted 8 lines
board/sandbox/README.sandbox +1
-1@@ -333,7 +333,7 @@ the contents of the root directory on the second partion of the image A disk image can be created using the following commands: $> truncate -s 1200M ./disk.raw -$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sfdisk ./disk.raw +$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sgdisk ./disk.raw $> lodev=`sudo losetup -P -f --show ./disk.raw` $> sudo mkfs.vfat -n EFI -v ${lodev}p1 $> sudo mkfs.ext4 -L ROOT -v ${lodev}p2
Tested on Ubuntu 14.04 (with tools in /sbin):
Quoted 7 lines
--
2.1.4_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
PATCH 4/5 sandbox: README: fix partition command invocation
Quoted 10 lines · On 4 June 2017 at 16:11, <[email protected]> wrote:
From: Alison Chaiken <[email protected]>
The instructions for creating a disk image that are presently in README.sandbox fail because sfdisk doesn't know about GPT.
Signed-off-by Alison Chaiken <[email protected]>--- board/sandbox/README.sandbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm, thanks!
PATCH v4 5/5 cmd gpt: test in sandbox
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
Make minor changes to README.gpt and sandbox_defconfig to support testing of the gpt command's functionality in the sandbox.
--- doc/README.gpt | 10 ++++++++++ 1 file changed, 10 insertions(+)
doc/README.gpt +10 -0
@@ -224,6 +224,16 @@ U-BOOT> gpt flip mmc 0 Choose different partition names by modifying these strings in gpt.c. +The GPT functionality may be tested with the 'sandbox' board by +creating a disk image as described under 'Block Device Emulation' in +board/sandbox/README.sandbox: + +=>host bind 0 ./disk.raw +=> gpt read host 0 +[ . . . ] +=> gpt flip host 0 +[ . . . ] + Partition type GUID: ====================
Signature · 1 line
2.1.4
PATCH 5/5 cmd gpt: test in sandbox
From: Alison Chaiken <[email protected]>
Make minor changes to README.gpt and sandbox_defconfig to support testing of the gpt command's functionality in the sandbox.
--- doc/README.gpt | 10 ++++++++++ 1 file changed, 10 insertions(+)
Applied to u-boot-dm, thanks!
Chaiken
PATCH v2 5/6 rename GPT partitions to detect boot failure
In reply to Lukasz MajewskiOn 2017-05-31 01:12, Lukasz Majewski wrote:
[ . . . ]
Quoted 6 lines
And another request -> Could you consider adding tests for those new gpt commands to the 'sandbox' (
sandbox_defconfig) ?Then you can 'mount' some gpt test image ('host' command) and use it with:
gpt <command> host X .....
The GPT functionality really cannot be tested without a block device. We could build the disk.raw described in board/sandbox/README.sandbox when (CONFIG_UNIT_TEST && CONFIG_CMD_GPT_RENAME) in imitation of the
file helloworld.efi. There would be no reason for the size to be as
large as 1200M, of course. 256KB appears to be the smallest usable
size for 4 partitions (although trying to partition a 16 KB raw object with gdisk produces entertaining results).
To create this object for testing, we could use a subdirectory like lib/efi_loader, but maybe doing so in test/ makes more sense? If the build system did create the object, then we could modify
board/sandbox/README.sandbox to so indicate. Then the test should go
in test/py/tests presumably.
Thanks for feedback,
Alison
---
Alison Chaiken alison at she-devel.com
http://{ she-devel.com, exerciseforthereader.org }
"We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
PATCH v2 5/6 rename GPT partitions to detect boot failure
Quoted 19 lines · Alison
On 2017-05-31 01:12, Lukasz Majewski wrote:
[ . . . ]
Quoted 6 lines
And another request -> Could you consider adding tests for those new gpt commands to the 'sandbox' (
sandbox_defconfig) ?Then you can 'mount' some gpt test image ('host' command) and use it with:
gpt <command> host X .....The GPT functionality really cannot be tested without a block device. We could build the disk.raw described in board/sandbox/README.sandbox when (
CONFIG_UNIT_TEST&&CONFIG_CMD_GPT_RENAME) in imitation of the
file helloworld.efi. There would be no reason for the size to be as
large as 1200M, of course. 256KB appears to be the smallest usable
size for 4 partitions (although trying to partition a 16 KB raw object with gdisk produces entertaining results).
Quoted 5 lines
To create this object for testing, we could use a subdirectory like
lib/efi_loader, but maybe doing so in test/ makes more sense? If the build system did create the object, then we could modify
board/sandbox/README.sandbox to so indicate. Then the test should go
in test/py/tests presumably.
If you have encountered some issues with adding this test to sandbox (and those are difficult to solve), then it would be also correct to add this test to test/py and run it on a real HW.
Please also keep in mind to provide some kind of verbose in-code description or proper documentation entry.
Quoted 10 lines
Thanks for feedback,
Alison---
Alison Chaiken alison at she-devel.com
http://{ she-devel.com, exerciseforthereader.org }
"We are giving up our privacy, one convenience at a time." -- Evangelos Simoudis
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 5/6 rename GPT partitions to detect boot failure
Quoted 26 lines · Å�ukasz Majewski
Quoted 19 lines · Alison
On 2017-05-31 01:12, Lukasz Majewski wrote:
[ . . . ]
Quoted 6 lines
And another request -> Could you consider adding tests for those new gpt commands to the 'sandbox' (
sandbox_defconfig) ?Then you can 'mount' some gpt test image ('host' command) and use it with:
gpt <command> host X .....The GPT functionality really cannot be tested without a block device. We could build the disk.raw described in board/sandbox/README.sandbox when (
CONFIG_UNIT_TEST&&CONFIG_CMD_GPT_RENAME) in imitation of the
file helloworld.efi. There would be no reason for the size to be as
large as 1200M, of course. 256KB appears to be the smallest usable
size for 4 partitions (although trying to partition a 16 KB raw object with gdisk produces entertaining results).Quoted 5 lines
To create this object for testing, we could use a subdirectory like
lib/efi_loader, but maybe doing so in test/ makes more sense? If the build system did create the object, then we could modify
board/sandbox/README.sandbox to so indicate. Then the test should go
in test/py/tests presumably.
Quoted 3 lines
If you have encountered some issues with adding this test to sandbox (and those are difficult to solve), then it would be also correct to add this test to test/py and run it on a real HW.
Right. Everyone can run test.py on sandbox _and_ QEMU, and there are then some people with labs setup that also run test.py on real hardware. Between QEMU and real hardware we should be able to add and run tests for this. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170828/3b6b97d8/attachment.sig>
PATCH v2 6/6 GPT: fix error in partitions string doc
In reply to alison at peloton-tech.comFrom: Alison Chaiken <[email protected]>
The existing partitions-list parsing in cmd/gpt.c passes a value from gpt_default() to set_gpt_info() that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call from set_gpt_info() to extract_val() to find 'uuid_disk' will fail. Change README.gpt and file comments accordingly.
--- cmd/gpt.c | 13 +------------ doc/README.gpt | 8 ++++---- 2 files changed, 5 insertions(+), 16 deletions(-)
cmd/gpt.c +1 -12
@@ -232,12 +232,6 @@ static void print_gpt_info(void)#ifdef CONFIG_CMD_GPT_FLIP static int calc_parts_list_len (int numparts) { -/* -* prefatory string: -* doc/README.GPT, suggests that -* int partlistlen = UUID_STR_LEN + 1 + strlen("partitions=uuid_disk="); -* is correct, but extract_val() expects "uuid_disk" first. -*/ int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );/* for the comma */ partlistlen++;
@@ -260,7 +254,7 @@ static int calc_parts_list_len(int numparts)* argument * * From doc/README.gpt, Format of partitions layout: -* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; * name=kernel,size=60MiB,uuid=...;" * The fields 'name' and 'size' are mandatory for every partition. * The field 'start' is optional. The fields 'uuid' and 'uuid_disk'
@@ -275,11 +269,6 @@ static int create_gpt_partitions_list(int numparts, const char *guid, char *partif (!partitions_list)return -1 ; -/* -* README.gpt specifies starting with "partitions=" like so: -* strcpy(partitions_list, "partitions=uuid_disk="); -* but that breaks extract_val, which doesn't skip over 'partitions='. -*/ strcpy (partitions_list,"uuid_disk=" );strncat (partitions_list, guid,UUID_STR_LEN +1 );strcat (partitions_list,";" );
doc/README.gpt +4 -4
@@ -156,10 +156,10 @@ Creating GPT partitions in U-Boot: To restore GUID partition table one needs to: 1. Define partition layout in the environment. Format of partitions layout: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or - "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + "uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition.
@@ -233,7 +233,7 @@ PARTITION_BASIC_DATA_GUID (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7). If you define 'CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type' can specify a other partition type guid: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=..., type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"
@@ -255,7 +255,7 @@ Some strings can be also used at the place of known GUID : "lvm" = PARTITION_LINUX_LVM_GUID (E6D6D379-F507-44C2-A23C-238F2A3DF928) - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...,type=linux;" They are also used to display the type of partition in "part list" command.
Signature · 1 line
2.1.4
PATCH v2 6/6 GPT: fix error in partitions string doc
Hi Alison,
Quoted 8 lines
From: Alison Chaiken <[email protected]>
The existing partitions-list parsing in
cmd/gpt.cpasses a value fromgpt_default()toset_gpt_info()that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call fromset_gpt_info()toextract_val()to find 'uuid_disk' will fail. Change README.gpt and file comments accordingly.
Thank you for updating the README.gpt entry.
Quoted 82 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 13 +------------ doc/README.gpt | 8 ++++---- 2 files changed, 5 insertions(+), 16 deletions(-)cmd/gpt.c +0
-6@@ -232,12 +232,6 @@ static void print_gpt_info(void)#ifdef CONFIG_CMD_GPT_FLIP static int calc_parts_list_len (int numparts) { -/* -* prefatory string: -* doc/README.GPT, suggests that -* int partlistlen = UUID_STR_LEN + 1 + strlen ("partitions=uuid_disk=" ); -* is correct, but extract_val() expects "uuid_disk" first. -*/ int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );/* for the comma */ cmd/gpt.c +1
-5partlistlen++;@@ -260,7 +254,7 @@ static int calc_parts_list_len(int numparts)* argument * * From doc/README.gpt, Format of partitions layout: -* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; * name=kernel,size=60MiB,uuid=...;" * The fields 'name' and 'size' are mandatory for every partition. * The field 'start' is optional. The fields 'uuid' and 'uuid_disk' @@ -275,11 +269,6 @@ static int create_gpt_partitions_list(int numparts, const char *guid, char *part if (!partitions_list)return -1 ; -/* -* README.gpt specifies starting with "partitions=" like so: -* strcpy(partitions_list, "partitions=uuid_disk="); -* but that breaks extract_val, which doesn't skip over 'partitions='.
cmd/gpt.c +0
-1-*/ strcpy (partitions_list,"uuid_disk=" );strncat (partitions_list, guid,UUID_STR_LEN +1 );strcat (partitions_list,";" );doc/README.gpt +2
-2@@ -156,10 +156,10 @@ Creating GPT partitions in U-Boot: To restore GUID partition table one needs to: 1. Define partition layout in the environment. Format of partitions layout: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or - "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + "uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition.@@ -233,7 +233,7 @@ PARTITION_BASIC_DATA_GUID(EBD0A0A2-B9E5-4433-87C0-68B6B72699C7). If you define '
CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type' can specify a other partition type guid:doc/README.gpt +1
-1- "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=..., type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"@@ -255,7 +255,7 @@ Some strings can be also used at the place ofknown GUID : "lvm" =
PARTITION_LINUX_LVM_GUIDdoc/README.gpt +1
-1(E6D6D379-F507-44C2-A23C-238F2A3DF928) - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...,type=linux;" They are also used to display the type of partition in "part list"
Quoted 1 line
command.
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 6/6 GPT: fix error in partitions string doc
Hi Alison,
Quoted 11 lines
Hi Alison,
Quoted 8 lines
From: Alison Chaiken <[email protected]>
The existing partitions-list parsing in
cmd/gpt.cpasses a value fromgpt_default()toset_gpt_info()that README.gpt suggests should begin with 'partitions='. Partition-list strings should in fact begin with 'uuid_disk', as otherwise the call fromset_gpt_info()toextract_val()to find 'uuid_disk' will fail. Change README.gpt and file comments accordingly.
Quoted 3 lines
Acked-by Lukasz Majewski <[email protected]>Thank you for updating the README.gpt entry.
Please also use either patman or get_maintainer before sending the patchset.
For exmaple:./scripts/get_maintainer.pl 0001-wip.patch
In that way all relevant people would be informed :-)
Quoted 91 lines
Quoted 84 lines
Signed-off-by Alison Chaiken <[email protected]>--- cmd/gpt.c | 13 +------------ doc/README.gpt | 8 ++++---- 2 files changed, 5 insertions(+), 16 deletions(-)cmd/gpt.c +0
-6@@ -232,12 +232,6 @@ static void print_gpt_info(void)#ifdef CONFIG_CMD_GPT_FLIP static int calc_parts_list_len (int numparts) { -/* -* prefatory string: -* doc/README.GPT, suggests that -* int partlistlen = UUID_STR_LEN + 1 + strlen ("partitions=uuid_disk=" ); -* is correct, but extract_val() expects "uuid_disk" first. -*/ int partlistlen =UUID_STR_LEN +1 +strlen ("uuid_disk=" );/* for the comma */ cmd/gpt.c +1
-3partlistlen++;@@ -260,7 +254,7 @@ static int calc_parts_list_len(int numparts)* argument * * From doc/README.gpt, Format of partitions layout: -* "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; +* "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; * name=kernel,size=60MiB,uuid=...;" * The fields 'name' and 'size' are mandatory for every partition. * The field 'start' is optional. The fields 'uuid' and 'uuid_disk' @@ -275,11 +269,6 @@ static int create_gpt_partitions_list(int numparts, const char *guid, char *part if (!partitions_list)return -1 ; -/* -* README.gpt specifies starting with "partitions=" like so:
cmd/gpt.c +0
-2-* strcpy(partitions_list, "partitions=uuid_disk="); -* but that breaks extract_val, which doesn't skip over 'partitions='.
cmd/gpt.c +0
-1-*/ strcpy (partitions_list,"uuid_disk=" );strncat (partitions_list, guid,UUID_STR_LEN +1 );strcat (partitions_list,";" );doc/README.gpt +2
-2@@ -156,10 +156,10 @@ Creating GPT partitions in U-Boot: To restore GUID partition table one needs to: 1. Define partition layout in the environment. Format of partitions layout: - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or - "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + "uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition.@@ -233,7 +233,7 @@ PARTITION_BASIC_DATA_GUID(EBD0A0A2-B9E5-4433-87C0-68B6B72699C7). If you define '
CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type' can specify a other partition type guid:doc/README.gpt +1
-1- "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=..., type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"@@ -255,7 +255,7 @@ Some strings can be also used at the place ofknown GUID : "lvm" =
PARTITION_LINUX_LVM_GUIDdoc/README.gpt +1
-1(E6D6D379-F507-44C2-A23C-238F2A3DF928) - "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...,type=linux;" They are also used to display the type of partition in "part list"Quoted 1 line
command.
Best regards,
Quoted 7 lines
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de