Message ID | 1347523805-17825-4-git-send-email-l.majewski@samsung.com |
---|---|
State | Changes Requested |
Delegated to: | Tom Rini |
Headers | show |
On 09/13/2012 02:10 AM, Lukasz Majewski wrote: > Documentation of the GPT format. > diff --git a/doc/README.gpt b/doc/README.gpt > +Example usage: > +============== > + > +To restore GUID partition table one needs to: > +1. at ./include/configs/{board}.h > + - define "partitions=" environment variable with format: > + "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" > + - define GPT_PARTS_NUM with actual number of partitions (as defined above) That seems unfortunate; the partitions variable and GPT_PARTS_NUM define could easily become out-of-sync (what if the user edited the variable in order to create an alternative disk layout, or what if a developer simply forgot to update GPT_PARTS_NUM when editing the hard-coded value?). Instead, can't GPT_PARTS_NUM be removed, and the code simply count the number of entries in the partitions variable? > + - #define CONFIG_EFI_PARTITION and #define CONFIG_CMD_GPT > + > +2. From u-boot prompt type: > + gpt mmc 0 uuid_disk=ec2cddf2-fbf5-11e1-af3a-001fd09285c0, \ > + uuid1=ed09c4b0-fbf5-11e1-9a95-001fd09285c0, \ > + uuid2=edd6d93c-fbf5-11e1-875a-001fd09285c0, \ > + uuid3=f0485114-fbf5-11e1-a3ae-001fd09285c0 ... > + > + UUIDs shall be defined up to GPT_PARTS_NUM. Smaller number is acceptable. > + When UUIDs are NOT provided, internal (rather weak) GUID generator will be > + used instead Hmmm. It's a little unfortunate to provide the partitions list through one mechanism (environment variable with a hard-coded name), and the UUIDs through a different mechanism (command-line). Surely these two mechanisms can be combined; rather than the command reading an environment variable, you could at least require the user to pass the appropriate data on the command-line, and optionally have them pass the environment variable if they want to use the pre-defined layout, e.g.: pre-defined: gpt mmc 0 ${partitions} manual/custom layout: gpt mmc 0 name=u-boot,size=60M;name=kernel,size=60M;... Then, I wonder if you couldn't define the partitions environment variable as: partitions=\ name=u-boot,size=60M,uuid=${uuid_gpt_u_boot};\ name=kernel,size=60M,uuid=${uuid_gpt_kernel};... and have the environment variables expanded as in: setenv uuid_gpt_u_boot=ed09c4b0-fbf5-11e1-9a95-001fd09285c0 setenv uuid_gpt_kernel=... gpt mmc 0 ${partitions} That way, the gpt command would read everything from the command-line, yet the partition layout and UUID names could be specified separately, so as to allow the user to define them at different times or places. The implementation of "gpt" would have to scan all the variables it extracted from the command-line, and expand any environment variable references in them for this to work, since I assume the shell doesn't do recursive variable expansions like make does. Oh, and don't you want the "gpt" command to take a sub-command like "create", so that "gpt" could do different things in the future, e.g. take an existing GPT layout, and edit, say, one partition's name: gpt create mmc 0 ${partitions} gpt set-name mmc 0 ${partition-id} ${new-name}
Hi Stephen, > On 09/13/2012 02:10 AM, Lukasz Majewski wrote: > > Documentation of the GPT format. > > > diff --git a/doc/README.gpt b/doc/README.gpt > > > +Example usage: > > +============== > > + > > +To restore GUID partition table one needs to: > > +1. at ./include/configs/{board}.h > > + - define "partitions=" environment variable with format: > > + > > "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" > > + - define GPT_PARTS_NUM with actual number of partitions (as > > defined above) > > That seems unfortunate; the partitions variable and GPT_PARTS_NUM > define could easily become out-of-sync (what if the user edited the > variable in order to create an alternative disk layout, or what if a > developer simply forgot to update GPT_PARTS_NUM when editing the > hard-coded value?). > > Instead, can't GPT_PARTS_NUM be removed, and the code simply count the > number of entries in the partitions variable? Yes, the GPT_PARTS_NUM can (and shall be replaced) with a runtime detection of the number of available partitions. This can be done in a similar way as it is done at DFU code. > > > + - #define CONFIG_EFI_PARTITION and #define CONFIG_CMD_GPT > > + > > +2. From u-boot prompt type: > > + gpt mmc 0 uuid_disk=ec2cddf2-fbf5-11e1-af3a-001fd09285c0, \ > > + uuid1=ed09c4b0-fbf5-11e1-9a95-001fd09285c0, \ > > + uuid2=edd6d93c-fbf5-11e1-875a-001fd09285c0, \ > > + uuid3=f0485114-fbf5-11e1-a3ae-001fd09285c0 ... > > + > > + UUIDs shall be defined up to GPT_PARTS_NUM. Smaller number is > > acceptable. > > + When UUIDs are NOT provided, internal (rather weak) GUID > > generator will be > > + used instead > > Hmmm. It's a little unfortunate to provide the partitions list through > one mechanism (environment variable with a hard-coded name), and the > UUIDs through a different mechanism (command-line). Surely these two > mechanisms can be combined; rather than the command reading an > environment variable, you could at least require the user to pass the > appropriate data on the command-line, and optionally have them pass > the environment variable if they want to use the pre-defined layout, > e.g.: > > pre-defined: > gpt mmc 0 ${partitions} > > manual/custom layout: > gpt mmc 0 name=u-boot,size=60M;name=kernel,size=60M;... > > Then, I wonder if you couldn't define the partitions environment > variable as: > > partitions=\ > name=u-boot,size=60M,uuid=${uuid_gpt_u_boot};\ > name=kernel,size=60M,uuid=${uuid_gpt_kernel};... > > and have the environment variables expanded as in: > > setenv uuid_gpt_u_boot=ed09c4b0-fbf5-11e1-9a95-001fd09285c0 > setenv uuid_gpt_kernel=... This is a good idea to allow uuid_gpt_u_boot= to be set via setenv. Moreover I think, that "editing" of "partitions" names, uuid and other parameters shall be done via setenv (as you proposed). > gpt mmc 0 ${partitions} Moreover I think, that parsing ${partitions} as a list of argv[n] is not the best option to proceed. I think that it would be easier to: 1. Prepare predefined "partitions=" variable at ./include/configs/trats.h (when no one is available on the platform) 2. Edit relevant env variables (uuid_gpt_u_boot=, etc) via setenv and saveenv. 3. restore it with gpt mmc 0 partitions (- the name of the stored and prepared env variable) I'd like to emphasis, that I strive to avoid parsing possibly (very) long list of GPT partition definition via gpt command's argv[n]. If user wants to edit something, then one can use setenv to do that. > > That way, the gpt command would read everything from the command-line, > yet the partition layout and UUID names could be specified separately, > so as to allow the user to define them at different times or places. > > The implementation of "gpt" would have to scan all the variables it > extracted from the command-line, and expand any environment variable > references in them for this to work, since I assume the shell doesn't > do recursive variable expansions like make does. > > Oh, and don't you want the "gpt" command to take a sub-command like > "create", so that "gpt" could do different things in the future, e.g. > take an existing GPT layout, and edit, say, one partition's name: > This is a nice idea to divide the gpt commands to subcommands. However I now focus on gpt restoration (done in a correct and agreed way :-) ). I will prepare the gpt command to be easily dividable to sub-commands. > gpt create mmc 0 ${partitions} > gpt set-name mmc 0 ${partition-id} ${new-name}
Hi Stephen, > > > On 09/13/2012 02:10 AM, Lukasz Majewski wrote: > > > Documentation of the GPT format. > > > > > diff --git a/doc/README.gpt b/doc/README.gpt > > > > > +Example usage: > > > +============== > > > + > > > +To restore GUID partition table one needs to: > > > +1. at ./include/configs/{board}.h > > > + - define "partitions=" environment variable with format: > > > + > > > "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" > > > + - define GPT_PARTS_NUM with actual number of partitions (as > > > defined above) > > > > That seems unfortunate; the partitions variable and GPT_PARTS_NUM > > define could easily become out-of-sync (what if the user edited the > > variable in order to create an alternative disk layout, or what if a > > developer simply forgot to update GPT_PARTS_NUM when editing the > > hard-coded value?). > > > > Instead, can't GPT_PARTS_NUM be removed, and the code simply count > > the number of entries in the partitions variable? > > Yes, the GPT_PARTS_NUM can (and shall be replaced) with a runtime > detection of the number of available partitions. This can be done in a > similar way as it is done at DFU code. > > > > > > + - #define CONFIG_EFI_PARTITION and #define CONFIG_CMD_GPT > > > + > > > +2. From u-boot prompt type: > > > + gpt mmc 0 uuid_disk=ec2cddf2-fbf5-11e1-af3a-001fd09285c0, \ > > > + uuid1=ed09c4b0-fbf5-11e1-9a95-001fd09285c0, \ > > > + uuid2=edd6d93c-fbf5-11e1-875a-001fd09285c0, \ > > > + uuid3=f0485114-fbf5-11e1-a3ae-001fd09285c0 ... > > > + > > > + UUIDs shall be defined up to GPT_PARTS_NUM. Smaller number is > > > acceptable. > > > + When UUIDs are NOT provided, internal (rather weak) GUID > > > generator will be > > > + used instead > > > > Hmmm. It's a little unfortunate to provide the partitions list > > through one mechanism (environment variable with a hard-coded > > name), and the UUIDs through a different mechanism (command-line). > > Surely these two mechanisms can be combined; rather than the > > command reading an environment variable, you could at least require > > the user to pass the appropriate data on the command-line, and > > optionally have them pass the environment variable if they want to > > use the pre-defined layout, e.g.: > > > > pre-defined: > > gpt mmc 0 ${partitions} > > > > manual/custom layout: > > gpt mmc 0 name=u-boot,size=60M;name=kernel,size=60M;... > > > > Then, I wonder if you couldn't define the partitions environment > > variable as: > > > > partitions=\ > > name=u-boot,size=60M,uuid=${uuid_gpt_u_boot};\ > > name=kernel,size=60M,uuid=${uuid_gpt_kernel};... > > > > and have the environment variables expanded as in: > > > > setenv uuid_gpt_u_boot=ed09c4b0-fbf5-11e1-9a95-001fd09285c0 > > setenv uuid_gpt_kernel=... > > This is a good idea to allow uuid_gpt_u_boot= to be set via setenv. > Moreover I think, that "editing" of "partitions" names, uuid and other > parameters shall be done via setenv (as you proposed). > > > gpt mmc 0 ${partitions} > > Moreover I think, that parsing ${partitions} as a list of argv[n] is > not the best option to proceed. > > I think that it would be easier to: > 1. Prepare predefined "partitions=" variable > at ./include/configs/trats.h (when no one is available on the > platform) 2. Edit relevant env variables (uuid_gpt_u_boot=, etc) via > setenv and saveenv. > 3. restore it with gpt mmc 0 partitions (- the name of the stored and > prepared env variable) > > I'd like to emphasis, that I strive to avoid parsing possibly (very) > long list of GPT partition definition via gpt command's argv[n]. > > If user wants to edit something, then one can use setenv to do that. > I must correct myself here. After some research I will give a shoot to the gpt mmc 0 ${partitions} approach. As you pointed out, the depth of u-boot's shell variable expanding is one. Due to this the string passed to gpt command needs to be parsed and expanded in the gpt command: name=csa-mmc,size=8MiB,uuid=${uuid_gpt_csa-mmc} the ${uuid_gpt_csa-mmc} needs to be expanded during runtime. > > > > That way, the gpt command would read everything from the > > command-line, yet the partition layout and UUID names could be > > specified separately, so as to allow the user to define them at > > different times or places. You are right, this approach (even when taking into account the extra complexity of gpt command's run-time variables expanding) is most universal. I will prepare patches with this approach. > > > > The implementation of "gpt" would have to scan all the variables it > > extracted from the command-line, and expand any environment variable > > references in them for this to work, since I assume the shell > > doesn't do recursive variable expansions like make does. > > > > Oh, and don't you want the "gpt" command to take a sub-command like > > "create", so that "gpt" could do different things in the future, > > e.g. take an existing GPT layout, and edit, say, one partition's > > name: > > > > This is a nice idea to divide the gpt commands to subcommands. However > I now focus on gpt restoration (done in a correct and agreed > way :-) ). I will prepare the gpt command to be easily dividable to > sub-commands. > > > gpt create mmc 0 ${partitions} > > gpt set-name mmc 0 ${partition-id} ${new-name} > > >
On 10/05/2012 04:35 AM, Lukasz Majewski wrote: > Hi Stephen, > >> On 09/13/2012 02:10 AM, Lukasz Majewski wrote: ... [patch to implement GPT creation] >> Then, I wonder if you couldn't define the partitions environment >> variable as: >> >> partitions=\ >> name=u-boot,size=60M,uuid=${uuid_gpt_u_boot};\ >> name=kernel,size=60M,uuid=${uuid_gpt_kernel};... >> >> and have the environment variables expanded as in: >> >> setenv uuid_gpt_u_boot=ed09c4b0-fbf5-11e1-9a95-001fd09285c0 >> setenv uuid_gpt_kernel=... > > This is a good idea to allow uuid_gpt_u_boot= to be set via setenv. > Moreover I think, that "editing" of "partitions" names, uuid and other > parameters shall be done via setenv (as you proposed). > >> gpt mmc 0 ${partitions} > > Moreover I think, that parsing ${partitions} as a list of argv[n] is > not the best option to proceed. > > I think that it would be easier to: > 1. Prepare predefined "partitions=" variable > at ./include/configs/trats.h (when no one is available on the platform) > 2. Edit relevant env variables (uuid_gpt_u_boot=, etc) via setenv and > saveenv. > 3. restore it with gpt mmc 0 partitions (- the name of the stored and > prepared env variable) > > I'd like to emphasis, that I strive to avoid parsing possibly (very) > long list of GPT partition definition via gpt command's argv[n]. > > If user wants to edit something, then one can use setenv to do that. This forces the user to put the partition layout into an environment variable. I don't like that idea. What if the user is running some script on a recovery boot media to create the partition layout, rather then restoring some partition layout defined in the default environment in the board's U-Boot configuration file? Why should we force them to write: setenv foo <<partition_layout>> gpt create mmc 0 ${foo} rather than simply: gpt create mmc 0 <<partition_layout>> The amount of work the command itself has to do for parsing is identical or in fact slightly less; it just has to go to argv[4] and interpret it as a partition list, rather than go to argv[4], read an environment variable of that name and then interpret it as a partition list. Admittedly, the command-shell has to do (very marginally) more work since it has to scan more characters for the spaces that delimit arguments, but I imagine that overhead is irrelevant compared to the actual disk IO required to write the new partition tables, or even the CPU calculations to calculate a UUID. ... >> Oh, and don't you want the "gpt" command to take a sub-command like >> "create", so that "gpt" could do different things in the future, e.g. >> take an existing GPT layout, and edit, say, one partition's name: >> > > This is a nice idea to divide the gpt commands to subcommands. However > I now focus on gpt restoration (done in a correct and agreed way :-) ). > I will prepare the gpt command to be easily dividable to sub-commands. I certainly agree that the other sub-commands can be implemented later; I just wanted to make sure that the command syntax was extensible in a backwards compatible manner.
diff --git a/doc/README.gpt b/doc/README.gpt new file mode 100644 index 0000000..ec56005 --- /dev/null +++ b/doc/README.gpt @@ -0,0 +1,207 @@ +# +# Copyright (C) 2012 Samsung Electronics +# +# Lukasz Majewski <l.majewski@samsung.com> +# +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA + + +Glossary: +======== +- UUID -(Universally Unique Identifier) +- GUID - (Globally Unique ID) +- EFI - (Extensible Firmware Interface) +- UEFI - (Unified EFI) - EFI evolution +- GPT (GUID Partition Table) - it is the EFI standard part +- partitions - lists of available partitions (defined at u-boot): + ./include/configs/{target}.h + +Introduction: +============= +This document describes the GPT partition table format when used with u-boot. + + +UUID introduction: +==================== + +GPT for marking disks/partitions is using the UUID. It is supposed to be a +globally unique value. A UUID is a 16-byte (128-bit) number. The number of +theoretically possible UUIDs is therefore about 3 × 10^38. +More often UUID is stored as 32 hexadecimal digits, displayed in 5 groups +separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +(32 digits and 4 hyphens) + +For instance, GUID of Linux data partition: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 + +Historically there are 5 methods to generate this number. The oldest one is +combining machine's MAC address and timer (epoch) value. + +Successive versions are using MD5 hash, random numbers and SHA-1 hash. All major +OSes and programming languages are providing libraries to compute UUID (e.g. +uuid command line tool). + +GPT brief explanation: +====================== + + Layout: + ------- + + -------------------------------------------------- + LBA 0 |Protective MBR | + ---------------------------------------------------------- + LBA 1 |Primary GPT Header | Primary + -------------------------------------------------- GPT + LBA 2 |Entry 1|Entry 2| Entry 3| Entry 4| + -------------------------------------------------- + LBA 3 |Entries 5 - 128 | + | | + | | + ---------------------------------------------------------- + LBA 34 |Partition 1 | + | | + ----------------------------------- + |Partition 2 | + | | + ----------------------------------- + |Partition n | + | | + ---------------------------------------------------------- + LBA -34 |Entry 1|Entry 2| Entry 3| Entry 4| Secondary + -------------------------------------------------- (bkp) + LBA -33 |Entries 5 - 128 | GPT + | | + | | + LBA -2 | | + -------------------------------------------------- + LBA -1 |Secondary GPT Header | + ---------------------------------------------------------- + + +For a legacy reasons, GPT's LBA 0 sector has a MBR structure. It is called +"protective MBR". +Its first partition entry ID has 0xEE value, and disk software, which is not +handling the GPT sees it as a storage device without free space. + +It is possible to define 128 linearly placed partition entries. + +"LBA -1" means the last addressable block (in the mmc subsystem: +"dev_desc->lba - 1") + +Primary/Secondary GPT header: +---------------------------- +Offset Size Description + +0 8 B Signature ("EFI PART", 45 46 49 20 50 41 52 54) +8 4 B Revision (For version 1.0, the value is 00 00 01 00) +12 4 B Header size (in bytes, usually 5C 00 00 00 meaning 92 bytes) +16 4 B CRC32 of header (0 to header size), with this field zeroed + during calculation +20 4 B Reserved (ZERO); +24 8 B Current LBA (location of this header copy) +32 8 B Backup LBA (location of the other header copy) +40 8 B First usable LBA for partitions (primary partition table last + LBA + 1) +48 8 B Last usable LBA (secondary partition table first LBA - 1) +56 16 B Disk GUID (also referred as UUID on UNIXes) +72 8 B Partition entries starting LBA (always 2 in primary copy) +80 4 B Number of partition entries +84 4 B Size of a partition entry (usually 128) +88 4 B CRC32 of partition array +92 * Reserved; must be ZERO (420 bytes for a 512-byte LBA) + +TOTAL: 512 B + + + +IMPORTANT: + +GPT headers and partition entries are protected by CRC32 (the POSIX CRC32). + +Primary GPT header and Secondary GPT header have swapped values of "Current LBA" +and "Backup LBA" and therefore different CRC32 check-sum. + +CRC32 for GPT headers (field "CRC of header") are calculated up till +"Header size" (92), NOT 512 bytes. + +CRC32 for partition entries (field "CRC32 of partition array") is calculated for +the whole array entry ( Number_of_partition_entries * +sizeof(partition_entry_size (usually 128))) + +Observe, how Secondary GPT is placed in the memory. It is NOT a mirror reflect +of the Primary. + + + Partition Entry Format: + ---------------------- + Offset Size Description + + 0 16 B Partition type GUID + 16 16 B Unique partition GUID + 32 8 B First LBA (Little Endian) + 40 8 B Last LBA (inclusive) + 48 8 B Attribute flags [+] + 56 72 B Partition name (text) + + Attribute flags: + Bit 0 - System partition + Bit 60 - Read-only + Bit 62 - Hidden + Bit 63 - Not mount + + +Example usage: +============== + +To restore GUID partition table one needs to: +1. at ./include/configs/{board}.h + - define "partitions=" environment variable with format: + "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" + - define GPT_PARTS_NUM with actual number of partitions (as defined above) + - #define CONFIG_EFI_PARTITION and #define CONFIG_CMD_GPT + +2. From u-boot prompt type: + gpt mmc 0 uuid_disk=ec2cddf2-fbf5-11e1-af3a-001fd09285c0, \ + uuid1=ed09c4b0-fbf5-11e1-9a95-001fd09285c0, \ + uuid2=edd6d93c-fbf5-11e1-875a-001fd09285c0, \ + uuid3=f0485114-fbf5-11e1-a3ae-001fd09285c0 ... + + UUIDs shall be defined up to GPT_PARTS_NUM. Smaller number is acceptable. + When UUIDs are NOT provided, internal (rather weak) GUID generator will be + used instead + +Internal GUID generator: +======================= + +For "emergency" usage (or when list of UUIDs cannot be provided) the internal +GUID generator shall be used. It uses gd->start_addr_sp as a primary source of +UUID generator (16B). + + +Useful info: +============ + +Two programs, namely: 'fdisk' and 'parted' are recommended to work with GPT +recovery. Parted is able to handle GUID partitions. Unfortunately the 'fdisk' +hasn't got such ability. +Please, pay attention at -l switch for parted. + +"uuid" program is recommended to generate UUID string. Moreover it can decode +(-d switch) passed in UUID string. It can be used to generate partitions UUID +passed to u-boot environment variables.