gpt: GUID Partition Table (GPT) restoration
Subsystems (2)
cover gpt: GUID Partition Table (GPT) restoration
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration and display.
As a pre-work, some cleanup at the part_efi.c file was performed to remove custom macros and make GPT related structures more readable.
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
Lukasz Majewski (6):
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Replace the leXX_to_int() calls with ones defined at
<compiler.h>
gpt: Replacement of GPT structures members with ones indicating
endianness and size
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Trats
common/Makefile | 1 + common/cmd_gpt.c | 182 ++++++++++++++++++++++++++ disk/part_efi.c | 334 +++++++++++++++++++++++++++++++++++++---------- disk/part_efi.h | 85 ++++++------ doc/README.gpt | 199 ++++++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/part.h | 2 + 7 files changed, 715 insertions(+), 111 deletions(-) create mode 100644 common/cmd_gpt.c create mode 100644 doc/README.gpt
Signature · 1 line
1.7.2.3
PATCH 1/6 gpt:doc: GPT (GUID Partition Table) documentation
Documentation of the GPT table format.
--- doc/README.gpt | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 199 insertions(+), 0 deletions(-) create mode 100644 doc/README.gpt
doc/README.gpt new file +199 -0
@@ -0,0 +1,199 @@ +# +# Copyright (C) 2012 Samsung Electronics +# +# Lukasz Majewski <[email protected]> +# +# +# 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 Page Table) - it is the EFI standard part +- partitions - lists of availavle 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[5]: +==================== + +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 +For u-boot GPT hyphens are omitted. + +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. + +However it costs in terms of the computational power and memory footprint. +Therefore u-boot uses the crc32 with reading random block (512B) from MMC +storage device to generate UUID/GUID. + + +GUID 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 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 lineary 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 (Don't used at u-boot): + Bit 0 - System partition + Bit 60 - Read-only + Bit 62 - Hidden + Bit 63 - Not mount + + + +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. + + +Problems with current implementation: +==================================== + +1. Entropy of the u-boot's current GUID generation is only sufficient for an +emergency situations.
Signature · 1 line
1.7.2.3
PATCH 1/6 gpt:doc: GPT (GUID Partition Table) documentation
Quoted 11 lines · Lukasz Majewski
Documentation of the GPT table format.
+++ b/doc/README.gpt
+Glossary:
+======== +- UUID -(Universally Unique Identifier) +- GUID - (Globally Unique ID) +- EFI - (Extensible Firmware Interface) +- UEFI - (Unified EFI) - EFI evolution +- GPT (GUID Page Table) - it is the EFI standard part
GUID Partition Table, not Page.
doc/README.gpt line 42
Quoted 10 lines
+- partitions - lists of availavle partitions (defined at u-boot):
doc/README.gpt new file +9
-0+ ./include/configs/{target}.h + +Introduction: +============= +This document describes the GPT partition table format when used with u-boot. + + +UUID introduction[5]: +====================
What is "[5]"?
doc/README.gpt line 52
Quoted 2 lines
doc/README.gpt new file +2
-0+For instance, GUID of Linux data partition: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 +For u-boot GPT hyphens are omitted.
I don't think U-Boot should omit any of the hyphens; it makes the UUIDs far more readable, and the strings can then be cut/paste to/from other applications that use/print UUIDs, without any manual conversion.
doc/README.gpt line 62
Quoted 9 lines
doc/README.gpt new file +9
-0+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. + +However it costs in terms of the computational power and memory footprint. +Therefore u-boot uses the crc32 with reading random block (512B) from MMC +storage device to generate UUID/GUID.
That doesn't seem particularly relevant to general documentation about GPT; it's an implementation detail of the GPT creation command in a later patch, and could easily be changed.
In fact, I wonder why not require the user to concoct UUIDs and pass them to your GPT creation command, rather than forming them using some non-standard process.
Quoted 1 line
+GUID brief explanation:
Not "GUID", but "GPT".
Quoted 7 lines
+======================
doc/README.gpt new file +6
-0+ + Layout: + ------- + + -------------------------------------------------- + LBA 0 |Protective MBR |
doc/README.gpt line 82
Quoted 10 lines
doc/README.gpt new file +10
-0+ ---------------------------------------------------------- + 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 |
The indentation looks inconsistent in this diagram
Quoted 9 lines
doc/README.gpt new file +8
-0+ | | + ----------------------------------- + |Partition 2 | + | | + ----------------------------------- + |Partition n | + | | + -----------------------------------------------------------
doc/README.gpt line 100
Quoted 10 lines
doc/README.gpt new file +10
-0+ LBA -34 |Entry 1|Entry 2| Entry 3| Entry 4| Secondary + --------------------------------------------------- (bkp) + LBA 34 |Partition 1 | + | | + ----------------------------------- + |Partition 2 | + | | + ----------------------------------- + |Partition n | + | |
That part of the diagram appears duplicated.
doc/README.gpt
Quoted 13 lines
doc/README.gpt new file +12
-0+ ----------------------------------------------------------- + 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 | + ----------------------------------------------------------- + + Attribute flags (Don't used at u-boot):
I wouldn't write "Don't used at u-boot" since that's potentially subject to change. For example, I'm expecting to send a patch to use the "Legacy BIOS bootable" attribute soon.
PATCH 1/6 gpt:doc: GPT (GUID Partition Table) documentation
Hi Stephen,
Quoted 51 lines · Lukasz Majewski
Quoted 11 lines
Documentation of the GPT table format.
+++ b/doc/README.gpt
+Glossary:
+======== +- UUID -(Universally Unique Identifier) +- GUID - (Globally Unique ID) +- EFI - (Extensible Firmware Interface) +- UEFI - (Unified EFI) - EFI evolution +- GPT (GUID Page Table) - it is the EFI standard partGUID Partition Table, not Page.
doc/README.gpt line 42
Quoted 10 lines
+- partitions - lists of availavle partitions (defined at u-boot):
doc/README.gpt new file +5
-0+ ./include/configs/{target}.h + +Introduction: +============= +This document describes the GPT partition table format when usedwith u-boot. +
doc/README.gpt new file +3
-0+ +UUID introduction[5]: +====================What is "[5]"?
Quoted 3 lines
+For instance, GUID of Linux data partition:
EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 +For u-boot GPT hyphens are omitted.I don't think U-Boot should omit any of the hyphens; it makes the UUIDs far more readable, and the strings can then be cut/paste to/from other applications that use/print UUIDs, without any manual conversion.
Quoted 9 lines
+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. +
+However it costs in terms of the computational power and memory footprint. +Therefore u-boot uses the crc32 with reading random block (512B) from MMC +storage device to generate UUID/GUID.That doesn't seem particularly relevant to general documentation about GPT; it's an implementation detail of the GPT creation command in a later patch, and could easily be changed.
Quoted 3 lines
In fact, I wonder why not require the user to concoct UUIDs and pass them to your GPT creation command, rather than forming them using some non-standard process.
I think that it is a good idea. User can use standard uuid command and store its output as an environment variable.
Quoted 16 lines
Quoted 2 lines
+GUID brief explanation:
Not "GUID", but "GPT".
Quoted 11 lines
+======================
doc/README.gpt new file +10
-0+ + Layout: + ------- + + -------------------------------------------------- + LBA 0 |Protective MBR | + ---------------------------------------------------------- + LBA 1 |Primary GPT Header | Primary + -------------------------------------------------- GPT + LBA 2 |Entry 1|Entry 2| Entry 3| Entry 4|
Quoted 8 lines
doc/README.gpt line 82
Quoted 6 lines
doc/README.gpt new file +6
-0+ -------------------------------------------------- + LBA 3 |Entries 5 - 128 | + | | + | | + ----------------------------------------------------------- + LBA 34 |Partition 1 |The indentation looks inconsistent in this diagram
Strange, my emacs shows it correctly. I'll investigate the issue.
Quoted 37 lines
Quoted 12 lines
doc/README.gpt new file +9
-0+ | | + ----------------------------------- + |Partition 2 | + | | + ----------------------------------- + |Partition n | + | | + ----------------------------------------------------------- + LBA -34 |Entry 1|Entry 2| Entry 3| Entry 4|Secondary
doc/README.gpt line 100
Quoted 9 lines
doc/README.gpt new file +9
-0+ --------------------------------------------------- (bkp) + LBA 34 |Partition 1 | + | | + ----------------------------------- + |Partition 2 | + | | + ----------------------------------- + |Partition n | + | |That part of the diagram appears duplicated.
Quoted 12 lines
(quoted diff) +2
-0+ ----------------------------------------------------------- + LBA -34 |Entry 1|Entry 2| Entry 3| Entry 4|Secondary
doc/README.gpt new file +9
-0+ --------------------------------------------------- (bkp) + LBA -33 |Entries 5 - 128 | GPT + | | + | | + LBA -2 | | + --------------------------------------------------- + LBA -1 |Secondary GPT Header | + ----------------------------------------------------------- +
Quoted 5 lines
doc/README.gpt line 178
Quoted 1 line
doc/README.gpt new file +1
-0+ Attribute flags (Don't used at u-boot):I wouldn't write "Don't used at u-boot" since that's potentially subject to change. For example, I'm expecting to send a patch to use the "Legacy BIOS bootable" attribute soon.
Ok, I will correct this.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
In reply to Lukasz MajewskiCustom definitions of le_XX_to_int functions have been replaced with standard ones, defined at <compiler.h>
--- disk/part_efi.c | 109 ++++++++++++++++++++----------------------------------- 1 files changed, 40 insertions(+), 69 deletions(-)
disk/part_efi.c +40 -69
@@ -44,34 +44,6 @@defined (CONFIG_MMC ) || \defined (CONFIG_SYSTEMACE ) -/* Convert char[2] in little endian format to the host format integer - */ -static inline unsigned short le16_to_int (unsigned char *le16) -{ -return ((le16[1 ] <<8 ) + le16[0 ]); -} - -/* Convert char[4] in little endian format to the host format integer -*/ -static inline unsigned long le32_to_int (unsigned char *le32) -{ -return ((le32[3 ] <<24 ) + (le32[2 ] <<16 ) + (le32[1 ] <<8 ) + le32[0 ]); -} - -/* Convert char[8] in little endian format to the host format integer -*/ -static inline unsigned long long le64_to_int (unsigned char *le64) -{ -return (((unsigned long long )le64[7 ] <<56 ) + - ((unsigned long long )le64[6 ] <<48 ) + - ((unsigned long long )le64[5 ] <<40 ) + - ((unsigned long long )le64[4 ] <<32 ) + - ((unsigned long long )le64[3 ] <<24 ) + - ((unsigned long long )le64[2 ] <<16 ) + - ((unsigned long long )le64[1 ] <<8 ) + - (unsigned long long )le64[0 ]); -} -/** * efi_crc32() - EFI version of crc32 function * @buf: buffer to calculate crc32 of
@@ -79,7 +51,7 @@ static inline unsigned long long le64_to_int(unsigned char *le64)* * Description: Returns EFI-style CRC32 value for @buf */ -static inline unsigned long efi_crc32 (const void *buf,unsigned long len) +static inline u32 efi_crc32 (const void *buf,u32 len) {return crc32 (0 , buf, len); }
@@ -137,13 +109,13 @@ void print_part_efi(block_dev_desc_t * dev_desc)debug ("%s: gpt-entry@%p\n" , __func__, gpt_pte);printf ("Part\tName\t\t\tStart LBA\tEnd LBA\n" ); -for (i =0 ; i <le32_to_int (gpt_head->num_partition_entries); i++) { +for (i =0 ; i <le32_to_cpu (gpt_head->num_partition_entries); i++) {if (is_pte_valid (&gpt_pte[i])) {printf ("%3d\t%-18s\t0x%08llX\t0x%08llX\n" , (i +1 ),print_efiname (&gpt_pte[i]), -le64_to_int (gpt_pte[i].starting_lba), -le64_to_int (gpt_pte[i].ending_lba)); + (u64 )le64_to_cpu (gpt_pte[i].starting_lba), + (u64 )le64_to_cpu (gpt_pte[i].ending_lba)); }else {break ;/* Stop at the first non valid PTE */ }
@@ -174,9 +146,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, }/* The ulong casting limits the maximum disk size to 2 TB */ - info->start = (ulong )le64_to_int (gpt_pte[part -1 ].starting_lba); + info->start = (u64 )le64_to_cpu (gpt_pte[part -1 ].starting_lba);/* The ending LBA is inclusive, to calculate size, add 1 to it */ - info->size = ((ulong )le64_to_int (gpt_pte[part -1 ].ending_lba) +1 ) + info->size = ((u64 )le64_to_cpu (gpt_pte[part -1 ].ending_lba) +1 ) - info->start; info->blksz =GPT_BLOCK_SIZE ;
@@ -215,7 +187,7 @@ int test_part_efi(block_dev_desc_t * dev_desc)static int pmbr_part_valid (struct partition *part) {if (part->sys_ind ==EFI_PMBR_OSTYPE_EFI_GPT && -le32_to_int (part->start_sect) ==1UL ) { +le32_to_cpu (part->start_sect) ==1UL ) {return 1 ; }
@@ -234,9 +206,8 @@ static int is_pmbr_valid(legacy_mbr * mbr) {int i =0 ; -if (!mbr ||le16_to_int (mbr->signature) !=MSDOS_MBR_SIGNATURE ) { +if (!mbr ||le16_to_cpu (mbr->signature) !=MSDOS_MBR_SIGNATURE )return 0 ; - }for (i =0 ; i <4 ; i++) {if (pmbr_part_valid (&mbr->partition_record[i])) {
@@ -259,8 +230,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)static int is_gpt_valid (block_dev_desc_t * dev_desc,unsigned long long lba,gpt_header * pgpt_head,gpt_entry ** pgpt_pte) { -unsigned char crc32_backup[4 ] = {0 }; -unsigned long calc_crc32; +u32 crc32_backup =0 ; +u32 calc_crc32;unsigned long long lastlba;if (!dev_desc || !pgpt_head) {
@@ -275,54 +246,54 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, }/* Check the GPT header signature */ -if (le64_to_int (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) { +if (le64_to_cpu (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) {printf ("GUID Partition Table Header signature is wrong:" "0x%llX != 0x%llX\n" , - (unsigned long long )le64_to_int (pgpt_head->signature), - (unsigned long long )GPT_HEADER_SIGNATURE ); + (u64 )le64_to_cpu (pgpt_head->signature), + (u64 )GPT_HEADER_SIGNATURE );return 0 ; }/* Check the GUID Partition Table CRC */ -memcpy (crc32_backup, pgpt_head->header_crc32,sizeof (crc32_backup)); -memset (pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); +memcpy (&crc32_backup, &pgpt_head->header_crc32,sizeof (crc32_backup)); +memset (&pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); calc_crc32 =efi_crc32 ((const unsigned char *)pgpt_head, -le32_to_int (pgpt_head->header_size)); +le32_to_cpu (pgpt_head->header_size)); -memcpy (pgpt_head->header_crc32, crc32_backup,sizeof (crc32_backup)); +memcpy (&pgpt_head->header_crc32, &crc32_backup,sizeof (crc32_backup)); -if (calc_crc32 !=le32_to_int (crc32_backup)) { +if (calc_crc32 !=le32_to_cpu (crc32_backup)) {printf ("GUID Partition Table Header CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (crc32_backup), calc_crc32); +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (crc32_backup), calc_crc32);return 0 ; }/* Check that the my_lba entry points to the LBA that contains the GPT */ -if (le64_to_int (pgpt_head->my_lba) != lba) { +if (le64_to_cpu (pgpt_head->my_lba) != lba) {printf ("GPT: my_lba incorrect: %llX != %llX\n" , - (unsigned long long )le64_to_int (pgpt_head->my_lba), - (unsigned long long )lba); + (u64 )le64_to_cpu (pgpt_head->my_lba), + (u64 )lba);return 0 ; }/* Check the first_usable_lba and last_usable_lba are within the disk. */ lastlba = (unsigned long long )dev_desc->lba; -if (le64_to_int (pgpt_head->first_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->first_usable_lba) > lastlba) {printf ("GPT: first_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), lastlba);return 0 ; } -if (le64_to_int (pgpt_head->last_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->last_usable_lba) > lastlba) {printf ("GPT: last_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);return 0 ; }debug ("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);/* Read and allocate Partition Table Entries */ *pgpt_pte =alloc_read_gpt_entries (dev_desc, pgpt_head);
@@ -333,13 +304,13 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,/* Check the GUID Partition Table Entry Array CRC */ calc_crc32 =efi_crc32 ((const unsigned char *)*pgpt_pte, -le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry)); +le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry)); -if (calc_crc32 !=le32_to_int (pgpt_head->partition_entry_array_crc32)) { +if (calc_crc32 !=le32_to_cpu (pgpt_head->partition_entry_array_crc32)) {printf ("GUID Partition Table Entry Array CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (pgpt_head->partition_entry_array_crc32), +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (pgpt_head->partition_entry_array_crc32), calc_crc32);free (*pgpt_pte);
@@ -370,12 +341,12 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,return NULL ; } - count =le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry); + count =le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry); -debug ("%s: count = %lu * %lu = %u\n" , __func__, -le32_to_int (pgpt_head->num_partition_entries), -le32_to_int (pgpt_head->sizeof_partition_entry), count); +debug ("%s: count = %u * %u = %u\n" , __func__, + (u32 )le32_to_cpu (pgpt_head->num_partition_entries), + (u32 )le32_to_cpu (pgpt_head->sizeof_partition_entry), count);/* Allocate memory for PTE, remember to FREE */ if (count !=0 ) {
@@ -390,7 +361,7 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,/* Read GPT Entries from device */ if (dev_desc->block_read (dev_desc->dev, - (unsigned long )le64_to_int (pgpt_head->partition_entry_lba), + (u64 )le64_to_cpu (pgpt_head->partition_entry_lba), (lbaint_t) (count /GPT_BLOCK_SIZE ), pte) != (count /GPT_BLOCK_SIZE )) {
Signature · 1 line
1.7.2.3
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
Quoted 6 lines · Lukasz Majewski
Custom definitions of
le_XX_to_intfunctions have been replaced with standard ones, defined at <compiler.h>Signed-off-by Chang Hyun Park <[email protected]>Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>
Did Chang Hyun Park write this? If so, shouldn't git have generated a "From" header for him, to reflect his authorship upstream. I'm not sure how Kyungmin Park's S-o-b plays into this, since he's not sending the patch.
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
Hi Stephen,
Quoted 12 lines · Lukasz Majewski
Quoted 6 lines
Custom definitions of
le_XX_to_intfunctions have been replaced with standard ones, defined at <compiler.h>Signed-off-by Chang Hyun Park <[email protected]>Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>Did Chang Hyun Park write this? If so, shouldn't git have generated a "From" header for him, to reflect his authorship upstream. I'm not sure how Kyungmin Park's S-o-b plays into this, since he's not sending the patch.
My work (for those patches) was based on Mr. Chang Hyum Park patches. However I had to modify his work for patches submission.
Therefore I've added Mr. Chang in a first place to credit his effort to this patch series creation.
Shall I do it in a different way?
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
Quoted 15 lines · Lukasz Majewski
Hi Stephen,
Quoted 12 lines · Lukasz Majewski
Quoted 6 lines
Custom definitions of
le_XX_to_intfunctions have been replaced with standard ones, defined at <compiler.h>Signed-off-by Chang Hyun Park <[email protected]>Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>Did Chang Hyun Park write this? If so, shouldn't git have generated a "From" header for him, to reflect his authorship upstream. I'm not sure how Kyungmin Park's S-o-b plays into this, since he's not sending the patch.
Quoted 7 lines
My work (for those patches) was based on Mr. Chang Hyum Park patches. However I had to modify his work for patches submission.
Therefore I've added Mr. Chang in a first place to credit his effort to this patch series creation.
Shall I do it in a different way?
To be honest, I'm not really sure. When I've done this, I've kept the original author in the git "author" field to show this, and then listed what I changed in the commit description. Whether that's the right way to go perhaps depends on the size of your changes. If your changes are so large that it doesn't make sense to do that, perhaps his S-o-b should be removed and replaced with a simple note "based on work by Chang Hyun Park <[email protected]>"?
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
Hi Chang Hyun,
Quoted 9 lines
Hello Lukasz, Stephen,
I see there has been quite a few mails going back and forth on the mailing list on the "gpt: Replace theleXX_to_int()calls with ones defined at <compiler.h>"I haven't been receiving the e-mails because my samsung e-mail account has expired.(Internship expired)(I just happened to run into the mails from a google search) Is there anything I should catch up on? Anything I should be doing?And on which fork is this commit being pushed onto? Thank you.
I've changed you as an author of the commit. I will also add your "private" e-mail to CC when I send gpt v2, so stay tunned :-)
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
In reply to Lukasz Majewskidisk/part_efi.c line 64
Quoted 9 lines · Lukasz Majewski
Custom definitions of
le_XX_to_intfunctions have been replaced with standard ones, defined at <compiler.h>disk/part_efi.c +0
-4-/* Convert char[8] in little endian format to the host format integer -*/ -static inline unsigned long long le64_to_int (unsigned char *le64) -{
So this original function takes a pointer to the value ...
disk/part_efi.c static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, · line 283
Quoted 4 lines
disk/part_efi.c +1
-1/* Check the first_usable_lba and last_usable_lba are within the disk. */ lastlba = (unsigned long long )dev_desc->lba; -if (le64_to_int (pgpt_head->first_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->first_usable_lba) > lastlba) {
At this point in the series, first_usable_lba is a char[8], so this is passing the address of the first byte to both the original function le64_to_int(), and the replacement function le64_to_cpu(). However, le64_to_cpu() expects to receive the 64-bit value to swap, not a pointer to it - from compiler.h:
#define _uswap_64(x, sfx) \
((((x) & 0xff00000000000000##sfx) >> 56) | \
...
# define uswap_64(x) _uswap_64(x, ull)le:
# define le64_to_cpu(x) (x) be: # define le64_to_cpu(x) uswap_64(x)
So I think this patch breaks the code, and then the next patch fixes it, since it changes the type of first_usable_lba from char[8] to __le64?
PATCH 2/6 gpt: Replace the leXX_to_int() calls with ones defined at <compiler.h>
Hi Stephen,
Quoted 30 lines · Lukasz Majewski
disk/part_efi.c line 64
Quoted 10 lines
Custom definitions of
le_XX_to_intfunctions have been replaced with standard ones, defined at <compiler.h>disk/part_efi.c +0
-1-/* Convert char[8] in little endian format to the host format integer
- */disk/part_efi.c +0
-2-static inline unsigned long long le64_to_int (unsigned char *le64) -{So this original function takes a pointer to the value ...
disk/part_efi.c static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, · line 283
Quoted 4 lines
/* Check the
first_usable_lbaandlast_usable_lbaare
within the disk. */ lastlba = (unsigned long long)dev_desc->lba;disk/part_efi.c +1
-1-if (le64_to_int (pgpt_head->first_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->first_usable_lba) > lastlba) {At this point in the series,
first_usable_lbais a char[8], so this is passing the address of the first byte to both the original functionle64_to_int(), and the replacement functionle64_to_cpu(). However,le64_to_cpu()expects to receive the 64-bit value to swap, not a pointer to it - fromcompiler.h:#define _uswap_64(x, sfx) \ ((((x) & 0xff00000000000000##sfx) >> 56) | \ ... # define uswap_64(x) _uswap_64(x, ull)
Quoted 8 lines
le:
# define le64_to_cpu(x) (x) be: # define le64_to_cpu(x) uswap_64(x)So I think this patch breaks the code, and then the next patch fixes it, since it changes the type of
first_usable_lbafrom char[8] to__le64?
First of all, thanks for very thorough review.
You are right, my fault. Patch 2/6 and 3/6 shall be squashed together. When squashed, no errors and warnings appear.
I've unnecessary separated them to show this two step change. For the sake of bisecting - those shall be squashed.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 3/6 gpt: Replacement of GPT structures members with ones indicating endianness and size
In reply to Lukasz MajewskiReplacement of several GPT related structures members with ones indicating its endianness and proper size.
--- disk/part_efi.h | 85 ++++++++++++++++++++++++++++-------------------------- 1 files changed, 44 insertions(+), 41 deletions(-)
disk/part_efi.h +44 -41
@@ -29,6 +29,8 @@* http://developer.intel.com/technology/efi/efi.htm */ +#include <linux/compiler.h> +#ifndef _DISK_PART_EFI_H#define _DISK_PART_EFI_H
@@ -41,6 +43,8 @@#define GPT_HEADER_REVISION_V1 0x00010000#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL#define GPT_ENTRY_NAME "gpt" +#define GPT_ENTRY_NUMBERS 128 +#define GPT_ENTRY_SIZE 128#define EFI_GUID (a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ ((efi_guid_t) \
@@ -72,68 +76,67 @@ 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)/* linux/include/efi.h */ -typedef unsigned short efi_char16_t ; +typedef u16 efi_char16_t ;typedef struct { -unsigned char b[16 ]; +u8 b[16 ]; }efi_guid_t ;/* based on linux/include/genhd.h */ struct partition { -unsigned char boot_ind;/* 0x80 - active */ -unsigned char head;/* starting head */ -unsigned char sector;/* starting sector */ -unsigned char cyl;/* starting cylinder */ -unsigned char sys_ind;/* What partition type */ -unsigned char end_head;/* end head */ -unsigned char end_sector;/* end sector */ -unsigned char end_cyl;/* end cylinder */ -unsigned char start_sect[4 ];/* starting sector counting from 0 */ -unsigned char nr_sects[4 ];/* nr of sectors in partition */ -} __attribute__ ((packed)); +u8 boot_ind;/* 0x80 - active */ +u8 head;/* starting head */ +u8 sector;/* starting sector */ +u8 cyl;/* starting cylinder */ +u8 sys_ind;/* What partition type */ +u8 end_head;/* end head */ +u8 end_sector;/* end sector */ +u8 end_cyl;/* end cylinder */ +__le32 start_sect;/* starting sector counting from 0 */ +__le32 nr_sects;/* nr of sectors in partition */ +} __packed;/* based on linux/fs/partitions/efi.h */ typedef struct _gpt_header { -unsigned char signature[8 ]; -unsigned char revision[4 ]; -unsigned char header_size[4 ]; -unsigned char header_crc32[4 ]; -unsigned char reserved1[4 ]; -unsigned char my_lba[8 ]; -unsigned char alternate_lba[8 ]; -unsigned char first_usable_lba[8 ]; -unsigned char last_usable_lba[8 ]; +__le64 signature; +__le32 revision; +__le32 header_size; +__le32 header_crc32; +__le32 reserved1; +__le64 my_lba; +__le64 alternate_lba; +__le64 first_usable_lba; +__le64 last_usable_lba;efi_guid_t disk_guid; -unsigned char partition_entry_lba[8 ]; -unsigned char num_partition_entries[4 ]; -unsigned char sizeof_partition_entry[4 ]; -unsigned char partition_entry_array_crc32[4 ]; -unsigned char reserved2[GPT_BLOCK_SIZE -92 ]; -} __attribute__ ((packed))gpt_header ; +__le64 partition_entry_lba; +__le32 num_partition_entries; +__le32 sizeof_partition_entry; +__le32 partition_entry_array_crc32; +u8 reserved2[GPT_BLOCK_SIZE -92 ]; +} __packed gpt_header;typedef struct _gpt_entry_attributes { -unsigned long long required_to_function:1 ; -unsigned long long reserved:47 ; -unsigned long long type_guid_specific:16 ; -} __attribute__ ((packed))gpt_entry_attributes ; +u64 required_to_function:1 ; +u64 reserved:47 ; +u64 type_guid_specific:16 ; +} __packed gpt_entry_attributes;#define PARTNAME_SZ (72 / sizeof(efi_char16_t))typedef struct _gpt_entry {efi_guid_t partition_type_guid;efi_guid_t unique_partition_guid; -unsigned char starting_lba[8 ]; -unsigned char ending_lba[8 ]; +__le64 starting_lba; +__le64 ending_lba;gpt_entry_attributes attributes;efi_char16_t partition_name[PARTNAME_SZ ]; -} -__attribute__ ((packed))gpt_entry ; +} __packed gpt_entry;typedef struct _legacy_mbr { -unsigned char boot_code[440 ]; -unsigned char unique_mbr_signature[4 ]; -unsigned char unknown[2 ]; +u8 boot_code[440 ]; +__le32 unique_mbr_signature; +__le16 unknown;struct partition partition_record[4 ]; -unsigned char signature[2 ]; -} __attribute__ ((packed))legacy_mbr ; +__le16 signature; +} __packed legacy_mbr;#endif /* _DISK_PART_EFI_H */
Signature · 1 line
1.7.2.3
PATCH 3/6 gpt: Replacement of GPT structures members with ones indicating endianness and size
Quoted 2 lines · Lukasz Majewski
Replacement of several GPT related structures members with ones indicating its endianness and proper size.
This patch seems reasonable to me, but I'm surprised it doesn't require /any/ changes to the code that uses these structures in order to avoid warnings/errors. Is git bisect maintained by this series?
PATCH 3/6 gpt: Replacement of GPT structures members with ones indicating endianness and size
Hi Stephen,
Quoted 7 lines · Lukasz Majewski
Quoted 2 lines
Replacement of several GPT related structures members with ones indicating its endianness and proper size.
This patch seems reasonable to me, but I'm surprised it doesn't require /any/ changes to the code that uses these structures in order to avoid warnings/errors. Is git bisect maintained by this series?
As I've written for Patch 2/6, this patch will be merged with patch 2/6
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 4/6 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Lukasz MajewskiThe restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
--- disk/part_efi.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 2 + 2 files changed, 227 insertions(+), 0 deletions(-)
disk/part_efi.c +225 -0
@@ -403,4 +403,229 @@ static int is_pte_valid(gpt_entry * pte) return 1; } } + +/** +* guid_gen(): Generate UUID +* +* @param dev_desc - block device descriptor +* +* @return - generated UUID table +* +* NOTE: The entrophy of this function is small +*/ +static u8 *guid_gen (block_dev_desc_t * dev_desc) +{ +int k =0 ; +static int i =1 ; +static u8 __aligned(CONFIG_SYS_CACHELINE_SIZE) guid[16 ]; +static u8 __aligned(CONFIG_SYS_CACHELINE_SIZE) ent_pool[512 ]; +u32 *ptr = (u32 *) guid; + +/* Entrophy initialization - read random content of one SD sector */ +if (i ==1 ) { +debug ("Init entropy:%x\n" , (u32)(dev_desc->lba >>14 )); + +if (dev_desc->block_read (dev_desc->dev, (dev_desc->lba >>14 ), +1 , (u32 *) ent_pool) !=1 ) { +printf ("** Can't read from device %d **\n" , + dev_desc->dev); + } + } + +for (k =0 ; k <4 ; k++) { + *(ptr + k) =efi_crc32 ((const void *) ent_pool, +sizeof (ent_pool)); + ent_pool[511 - k] = *(ptr + k); + } + + ent_pool[0 ] = ((u8 ) i) &0xff ; + +debug ("GUID: " ); +for (k =0 ; k <sizeof (guid); k++) +debug (" %x " , guid[k]); + +debug (" i:%d,\n" , i); + + i++; +return guid; +} + +/** +* set_protective_mbr(): Set the EFI protective MBR +* @param dev_desc - block device descriptor +* +* @return - zero on success, otherwise error +*/ +static int set_protective_mbr (block_dev_desc_t *dev_desc) +{ +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr)); +/* Append signature */ + p_mbr.signature =MSDOS_MBR_SIGNATURE ; + p_mbr.partition_record[0 ].sys_ind =EFI_PMBR_OSTYPE_EFI_GPT ; + p_mbr.partition_record[0 ].start_sect =1 ; + p_mbr.partition_record[0 ].nr_sects = (u32 ) dev_desc->lba; + +/* Write MBR sector to the MMC device */ +if (dev_desc->block_write (dev_desc->dev,0 ,1 , &p_mbr) !=1 ) { +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; + } + +return 0 ; +} + +/** +* fill_pte(): Fill the GPT partition table entry +* +* @param dev_desc - block device descriptor +* @param gpt_h - GPT header representation +* @param gpt_e - GPT partition table entries +* @param parts - number of partitions +* @param size - size of each partition +* @param name - name of each partition +*/ +static void fill_pte (block_dev_desc_t *dev_desc,gpt_header *gpt_h, +gpt_entry *gpt_e,int parts,unsigned int *size, +char *name[]) +{ +u32 offset = (u32 ) gpt_h->first_usable_lba; +char p[PARTNAME_SZ ]; +int i, k, j; +char *s; + +for (i =0 ; i < parts; i++) { +memcpy (gpt_e[i].partition_type_guid.b, + &PARTITION_BASIC_DATA_GUID ,16 ); +memcpy (gpt_e[i].unique_partition_guid.b, +guid_gen (dev_desc), +sizeof (gpt_e[i].unique_partition_guid.b)); + + s = name[i]; + +memset (p,0x00 ,sizeof (p)); +for (k =0 , j =0 ; k <strlen (s); k++, j +=2 ) { + p[j] = *(s + k); + p[j +1 ] ='.' ; + } + +memcpy (gpt_e[i].partition_name, + p,strlen (p)); + + gpt_e[i].starting_lba =cpu_to_le32 (offset); + +/* allocate remaining memory in last partition */ +if (i != parts -1 ) { + gpt_e[i].ending_lba = +cpu_to_le64 (offset + size[i] -1 ); + }else { + gpt_e[i].ending_lba = gpt_h->last_usable_lba; + } + +memset (&gpt_e[i].attributes,0 , +sizeof (gpt_entry_attributes)); + + offset += size[i]; +debug ("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%x\n" , + __func__, name[i], i, offset, i, size[i]); + } +} + +/** +* set_gpt_table() - Restore the GUID Partition Table +* +* @param dev_desc - block device descriptor +* @param parts - number of partitions +* @param size - pointer to array with each partition size +* @param name - pointer to array with each partition name +* +* @return - zero on success, otherwise error +*/ +int set_gpt_table (block_dev_desc_t *dev_desc, +int parts,unsigned int *size,char *name[]) +{ +const int pte_blk_num = (GPT_ENTRY_NUMBERS *sizeof (gpt_entry)) / + dev_desc->blksz; +gpt_entry gpt_e[GPT_ENTRY_NUMBERS ]; +gpt_header gpt_h; +u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); + +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +memset ((u32 *) &gpt_h,0x00 ,sizeof (gpt_h)); + +/* Generate Primary GPT header (LBA1) */ + gpt_h.signature =cpu_to_le64 (GPT_HEADER_SIGNATURE ); + gpt_h.revision =cpu_to_le32 (GPT_HEADER_REVISION_V1 ); + gpt_h.header_size =cpu_to_le32 (sizeof (gpt_header)); + gpt_h.my_lba =cpu_to_le64 (1 ); + gpt_h.alternate_lba =cpu_to_le64 (dev_desc->lba -1 ); + gpt_h.first_usable_lba =cpu_to_le64 (34 ); + gpt_h.last_usable_lba =cpu_to_le64 (dev_desc->lba -34 ); + gpt_h.partition_entry_lba =cpu_to_le64 (2 ); + gpt_h.num_partition_entries =cpu_to_le32 (GPT_ENTRY_NUMBERS ); + gpt_h.sizeof_partition_entry =cpu_to_le32 (sizeof (gpt_entry)); + gpt_h.header_crc32 =0 ; + gpt_h.partition_entry_array_crc32 =0 ; +memcpy (gpt_h.disk_guid.b,guid_gen (dev_desc), +sizeof (gpt_h.disk_guid.b)); + +memset ((u32 *) gpt_e,0x00 ,sizeof (gpt_e)); + +fill_pte (dev_desc, &gpt_h, gpt_e, parts, size, name); + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_e, +le32_to_cpu (gpt_h.num_partition_entries) * +le32_to_cpu (gpt_h.sizeof_partition_entry)); + gpt_h.partition_entry_array_crc32 =cpu_to_le32 (calc_crc32); + + calc_crc32 =efi_crc32 ((const unsigned char *)&gpt_h, +le32_to_cpu (gpt_h.header_size)); + gpt_h.header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the First GPT to the block right after the Legacy MBR */ +if (dev_desc->block_write (dev_desc->dev,1 ,1 , &gpt_h) !=1 ) + goto err; + +if (dev_desc->block_write (dev_desc->dev,2 , pte_blk_num, gpt_e) + != pte_blk_num) + goto err; + +/* recalculate the values for the Second GPT Header*/ + val =le64_to_cpu (gpt_h.my_lba); + gpt_h.my_lba = gpt_h.alternate_lba; + gpt_h.alternate_lba =cpu_to_le64 (val); + gpt_h.header_crc32 =0 ; + + calc_crc32 =efi_crc32 ((const unsigned char *)&gpt_h, +le32_to_cpu (gpt_h.header_size)); + gpt_h.header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the Second GPT that is located at the end of the disk */ +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h.last_usable_lba +1 ), + pte_blk_num, gpt_e) != pte_blk_num) + goto err; + +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h.my_lba),1 , &gpt_h) !=1 ) + goto err; + +printf ("GPT successfully written to block device!\n" ); +return 0 ; + + err: +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; +}#endif
include/part.h +2 -0
@@ -161,6 +161,8 @@ int test_part_amiga (block_dev_desc_t *dev_desc);int get_partition_info_efi (block_dev_desc_t * dev_desc,int part,disk_partition_t *info);void print_part_efi (block_dev_desc_t *dev_desc);int test_part_efi (block_dev_desc_t *dev_desc); +int set_gpt_table (block_dev_desc_t *dev_desc, +int parts,unsigned int *blocks,char *name[]);#endif #endif /* _PART_H */
Signature · 1 line
1.7.2.3
PATCH 4/6 gpt: Support for GPT (GUID Partition Table) restoration
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 165
Quoted 7 lines · Lukasz Majewski
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
include/part.h +2
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +int parts,unsigned int *blocks,char *name[]);
That interface seems very limiting; what if you want to select specific type UUIDs, set the partition attributes, leave gaps between the partitions, have the physical order of partitions (their block numbers) be different to the partition table ordering, etc.
I wonder if it wouldn't be better to take an array of structures here, and have each entry define all the properties of the partition. That would allow fields to be added to the structure to describe more information as we add more functionality.
I didn't review the implementation.
PATCH 4/6 gpt: Support for GPT (GUID Partition Table) restoration
Hi Stephen,
Quoted 14 lines · Lukasz Majewski
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 165
Quoted 7 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
include/part.h +2
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +int parts,unsigned int *blocks,char *name[]);That interface seems very limiting; what if you want to select specific type UUIDs, set the partition attributes, leave gaps between the partitions, have the physical order of partitions (their block numbers) be different to the partition table ordering, etc.
Quoted 4 lines
I wonder if it wouldn't be better to take an array of structures here, and have each entry define all the properties of the partition. That would allow fields to be added to the structure to describe more information as we add more functionality.
I agree.
I'd propose following approach:
- set_gpt_table will receive a table with pointers to partition entries (up to 128 entries in this table). In this way one can easily define partition properties (which can be different for different commands/boards).
- I think, that Legacy MBR, and Primary/Secondary GPT shall be generated in the set_gpt_table function. However I expect a problem with one Primary/Secondary GPT field
- the Disk GUID. We can read it from environment, generate it or hardcode it at ./include/boards/{target}.h
What is your opinion?
Quoted 2 lines
I didn't review the implementation.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 4/6 gpt: Support for GPT (GUID Partition Table) restoration
Quoted 30 lines · Lukasz Majewski
Hi Stephen,
Quoted 14 lines · Lukasz Majewski
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 165
Quoted 7 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
include/part.h +2
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +int parts,unsigned int *blocks,char *name[]);That interface seems very limiting; what if you want to select specific type UUIDs, set the partition attributes, leave gaps between the partitions, have the physical order of partitions (their block numbers) be different to the partition table ordering, etc.
Quoted 4 lines
I wonder if it wouldn't be better to take an array of structures here, and have each entry define all the properties of the partition. That would allow fields to be added to the structure to describe more information as we add more functionality.
I agree.
I'd propose following approach:
-
set_gpt_tablewill receive a table with pointers to partition entries (up to 128 entries in this table). In this way one can easily define partition properties (which can be different for different commands/boards).
Quoted 8 lines
- I think, that Legacy MBR, and Primary/Secondary GPT shall be generated in the
set_gpt_tablefunction. However I expect a problem with one Primary/Secondary GPT field
- the Disk GUID. We can read it from environment, generate it or hardcode it at./include/boards/{target}.hWhat is your opinion?
Perhaps rather than /just/ taking a pointer to a table of partitions, take a pointer to a struct, which can hold both global properties and a pointer to the list of partitions?
PATCH 4/6 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Lukasz MajewskiQuoted 7 lines · Lukasz Majewski
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
disk/part_efi.c +4
-0+/** +* guid_gen(): Generate UUID +* +* @param dev_desc - block device descriptor
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 420
Quoted 10 lines
disk/part_efi.c +10
-0+* +* @return - generated UUID table +* +* NOTE: The entrophy of this function is small +*/ +static u8 *guid_gen (block_dev_desc_t * dev_desc) +{ +int k =0 ; +static int i =1 ; +static u8 __aligned(CONFIG_SYS_CACHELINE_SIZE) guid[16 ];
Hmmm. Wouldn't it be better to take a pointer to the GUID as a parameter rather than returning a pointer to the same static over and over again. That way, the caller won't cause problems if they call this function 4 times, and cache the pointer each time.
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 429
Quoted 9 lines
disk/part_efi.c +9
-0+static u8 __aligned(CONFIG_SYS_CACHELINE_SIZE) ent_pool[512 ]; +u32 *ptr = (u32 *) guid; + +/* Entrophy initialization - read random content of one SD sector */ +if (i ==1 ) { +debug ("Init entropy:%x\n" , (u32)(dev_desc->lba >>14 )); + +if (dev_desc->block_read (dev_desc->dev, (dev_desc->lba >>14 ), +1 , (u32 *) ent_pool) !=1 ) {
I imagine you might get more entropy out of just reading sector 0, or 1 (or both) than some random sector in the middle of the disk, which quite possibly won't ever have been written to.
Is there any particular reason why ">> 14" rather than any other shift?
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 441
Quoted 12 lines
disk/part_efi.c +12
-0+printf ("** Can't read from device %d **\n" , + dev_desc->dev); + } + } + +for (k =0 ; k <4 ; k++) { + *(ptr + k) =efi_crc32 ((const void *) ent_pool, +sizeof (ent_pool)); + ent_pool[511 - k] = *(ptr + k); + } + + ent_pool[0 ] = ((u8 ) i) &0xff ;
That doesn't quite implement a fully compliant UUID. According to:
http://en.wikipedia.org/wiki/Universally_unique_identifier
the "variant" (UUID) and "version" (4; random) should be encoded into a few specific bits of the final UUID value.
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 445
Quoted 3 lines
disk/part_efi.c +3
-0+debug ("GUID: " ); +for (k =0 ; k <sizeof (guid); k++) +debug (" %x " , guid[k]);
I think inventing (stealing from Linux) a proper UUID formatting function would be useful; that way it could be shared by print_part_efi() if that function was ever enhanced to print the partition UUID and partition type UUID.
Quoted 5 lines
disk/part_efi.c +5
-0+debug (" i:%d,\n" , i); + + i++; +return guid; +}
PATCH 4/6 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Lukasz MajewskiQuoted 5 lines · Lukasz Majewski
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>
While the changes are fine, tt01 and eb_cpux9k2 use CONFIG_PART_EFI and do not set CONFIG_SYS_CACHELINE_SIZE and so fail to build after this patch. tt01 is easily fixable (it relies on a non-exported define elsewhere to 32) but the eb_cpu9k2 please contact the listed board maintainer to get the define added.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20121003/8df6c985/attachment.pgp>
[U-Boot] [u-boot] Adding missing CONFIG_SYS_CACHELINE_SIZE to boards definitions
Hi Jens and Helmut,
Quoted 5 lines · Lukasz Majewski
Quoted 4 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
Quoted 9 lines
Quoted 2 lines
Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>While the changes are fine, tt01 and
eb_cpux9k2useCONFIG_PART_EFIand do not setCONFIG_SYS_CACHELINE_SIZEand so fail to build after this patch. tt01 is easily fixable (it relies on a non-exported define elsewhere to 32) but theeb_cpu9k2please contact the listed board maintainer to get the define added.
Would it be possible to add the CONFIG_SYS_CACHELINE_SIZE definition to ./include/configs/{tty01|eb_cpux9k2} boards definition?
It would help improving cache alignment and GPT development.
Thanks in advance
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
[U-Boot] [u-boot] Adding missing CONFIG_SYS_CACHELINE_SIZE to boards definitions
Dear Lukasz,
Quoted 17 lines
Hi Jens and Helmut,
Quoted 5 lines · Lukasz Majewski
Quoted 4 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
Quoted 9 lines
Quoted 2 lines
Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>While the changes are fine, tt01 and
eb_cpux9k2useCONFIG_PART_EFIand do not setCONFIG_SYS_CACHELINE_SIZEand so fail to build after this patch. tt01 is easily fixable (it relies on a non-exported define elsewhere to 32) but theeb_cpu9k2please contact the listed board maintainer to get the define added.
Quoted 3 lines
Would it be possible to add the
CONFIG_SYS_CACHELINE_SIZEdefinition to ./include/configs/{tty01|eb_cpux9k2} boards definition?
The eb_cpux9k2 board based on at91rm9200 soc. This soc has currently no cache implementation. So I think your run in this error.
The attached patch sets the define to the soc default.
We can also set #define CONFIG_SYS_DCACHE_OFF
regards Jens
[U-Boot] [u-boot] Adding missing CONFIG_SYS_CACHELINE_SIZE to boards definitions
Hi esw,
(resending as it was erroneously posted on gmane; sorry for any dupes)
Quoted 22 lines · esw
Dear Lukasz,
Quoted 17 lines
Hi Jens and Helmut,
Quoted 5 lines · Lukasz Majewski
Quoted 4 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
Quoted 9 lines
Quoted 2 lines
Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>While the changes are fine, tt01 and
eb_cpux9k2useCONFIG_PART_EFIand do not setCONFIG_SYS_CACHELINE_SIZEand so fail to build after this patch. tt01 is easily fixable (it relies on a non-exported define elsewhere to 32) but theeb_cpu9k2please contact the listed board maintainer to get the define added.Quoted 3 lines
Would it be possible to add the
CONFIG_SYS_CACHELINE_SIZEdefinition to ./include/configs/{tty01|eb_cpux9k2} boards definition?
Quoted 7 lines
The
eb_cpux9k2board based on at91rm9200 soc. This soc has currently no cache implementation. So I think your run in this error.The attached patch sets the define to the soc default.
We can also set #define
CONFIG_SYS_DCACHE_OFFregards Jens
If this is to be considered an actual patch submission, then please submit via git format-patch/git send-email or patman, and copy the at91 custodian. This patch has been marked as "changes requested" in PW.
Amicalement,
Signature · 1 line
Albert.
[U-Boot] [u-boot] Adding missing CONFIG_SYS_CACHELINE_SIZE to boards definitions
In reply to Lukasz MajewskiQuoted 15 lines · Lukasz Majewski
Hi Jens and Helmut,
Quoted 5 lines · Lukasz Majewski
Quoted 4 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
Quoted 8 lines
Quoted 2 lines
Signed-off-by Lukasz Majewski<[email protected]>Signed-off-by Kyungmin Park<[email protected]>While the changes are fine, tt01 and
eb_cpux9k2useCONFIG_PART_EFIand do not setCONFIG_SYS_CACHELINE_SIZEand so fail to build after this patch. tt01 is easily fixable (it relies on a non-exported define elsewhere to 32) but theeb_cpu9k2please contact the listed board maintainer to get the define added.
Quoted 6 lines
Would it be possible to add the
CONFIG_SYS_CACHELINE_SIZEdefinition to ./include/configs/{tty01|eb_cpux9k2} boards definition?It would help improving cache alignment and GPT development.
Thanks in advance
Hi Lukasz,
feel free to do the appropriate changes in the TT-01 platform code
(explicitly setting CACHELINE_SIZE), I'm currently too busy to do any rebasing and testing on the board, we'll have to give it a time slice in the near future (to have a few platform things changed) anyway.
Helmut
--
Scanned by MailScanner.
PATCH 5/6 gpt: Support for new "gpt" command
In reply to Lukasz MajewskiNew command - "gpt" is now supported. It shows and restores the GPT partition table.
It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with CONFIG_CMD_GPT.
--- common/Makefile | 1 + common/cmd_gpt.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 0 deletions(-) create mode 100644 common/cmd_gpt.c
common/Makefile +1 -0
@@ -185,6 +185,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o +COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o endif ifdef CONFIG_SPL_BUILD
common/cmd_gpt.c new file +182 -0
182 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH 5/6 gpt: Support for new "gpt" command
Quoted 10 lines · Lukasz Majewski
New command - "gpt" is now supported. It shows and restores the GPT partition table.
It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file withCONFIG_CMD_GPT.common/cmd_gpt.c +3
-0+int set_gpt_info (block_dev_desc_t *dev_desc) +{ +char *ps[GPT_PARTS_NUM ], *name[GPT_PARTS_NUM ];
common/cmd_gpt.c line 72
Quoted 10 lines
common/cmd_gpt.c +10
-0+unsigned int size[GPT_PARTS_NUM ]; +char *tok, *t, *p, *s, *ss; +int i, ret; + + s =getenv ("partitions" ); +if (s ==NULL ) { +printf ("%s: \"partitions\" env variable not defined!\n" , + __func__); +return -1 ; + }
It'd be nice to be able to pass the partition definition on the command-line instead of (or perhaps as an alternative to) reading an environment variable.
Some documentation of the expected format of the partitions variable would be useful. From the following patch, the format appears to be:
8M(csa-mmc),60M(u-boot),60M(kernel),...
That's not particularly extensible (think about allowing partition type UUID to or attributes to be specified), and the brackets are a bit painful. Can we use key/value for defining the values, and have a simple separate separator between fields and partitions, e.g. something like:
size=8M,name=csa-mmc;size=60M,name=u-boot;size=60M,name=kernel;...
That would allow us to very easily allow new fields to be specified per partition in the future, e.g.:
uuid=XXXXX,size=512M,name=boot,type=21686148-6449-6E6F-744E-656564454649,attrs=2;uuid=YYYYY,size=7000M,name=root,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,attrs=0;...
Quoted 3 lines
common/cmd_gpt.c +3
-0+U_BOOT_CMD( + gpt, CONFIG_SYS_MAXARGS, 1, do_gpt, + "GUID Partition Table",
...
Quoted 2 lines
common/cmd_gpt.c +2
-0+"gpt restore - reset GPT partition to defaults\n" +"gpt dev #num - set device number\n"
...
common/cmd_gpt.c line 131
Quoted 5 lines
common/cmd_gpt.c +5
-0+static void set_gpt_dev (int dev) +{ + gpt_dev = dev; +} +
Hmmm. I think it'd be better to specify the device each time the gpt command was invoked. That would be simpler to use, more flexible, and more consistent with how other commands such as "ext2load" operate.
In other words, I would get rid of "gpt dev" completely, and instead of implementing "gpt restore", implement "gpt restore mmc 0".
I'm not sure "restore" is the correct name, given that the command can write arbitrary new partition layouts, rather than just restoring some specific hard-coded table from e.g. a backup image.
I'm not sure that "gpt" is even the best command name; it'd be nice if this were generic and could be extended to work with e.g. FAT in the future - something like:
part write usb 1 gpt uuid=XXXXX,size=512M,name=boot,... part write mmc 0 fat size=512M,attrs=0x80;...
common/cmd_gpt.c line 179
Quoted 4 lines
common/cmd_gpt.c +4
-0+U_BOOT_CMD ( + gpt,CONFIG_SYS_MAXARGS ,1 , do_gpt, +"GUID Partition Table" , + "show - show GPT\n"
s/show/gpt show/
common/cmd_gpt.c line 137
Quoted 6 lines
common/cmd_gpt.c +6
-0+static void gpt_show (void ) +{ +struct mmc *mmc =find_mmc_device (gpt_dev); + +print_part_efi (&mmc->block_dev); +}
Do we really need another way of showing partition tables; "mmc part", "usb part", ... already exist. I think if we want another way, it'd be better to add this functionality to my proposed "part" command, i.e. "part show mmc 0".
common/cmd_gpt.c line 146
Quoted 8 lines
common/cmd_gpt.c +8
-0+static int gpt_default (void ) +{ +struct mmc *mmc =find_mmc_device (gpt_dev); + +if (mmc ==NULL ) { +printf ("%s: mmc dev %d NOT available\n" , __func__, gpt_dev); +return CMD_RET_FAILURE ; + }
Why only allow mmc devices; what about USB for example? Other commands such as ext2load allow arbitrary device types to be used. Rob Herring recently posted some patches to unify how commands such as ext2load, ext2ls, fatload, fatls, ... all obtain a device/partition handle from their command-line - this patch should probably build on top of those patches.
Quoted 4 lines
common/cmd_gpt.c +4
-0+puts ("Using default GPT UUID\n" ); + +return set_gpt_info (&mmc->block_dev); +}
PATCH 5/6 gpt: Support for new "gpt" command
Hi Stephen,
Quoted 33 lines · Lukasz Majewski
Quoted 19 lines
New command - "gpt" is now supported. It shows and restores the GPT partition table.
It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file withCONFIG_CMD_GPT.common/cmd_gpt.c +10
-0+int set_gpt_info (block_dev_desc_t *dev_desc) +{ +char *ps[GPT_PARTS_NUM ], *name[GPT_PARTS_NUM ]; +unsigned int size[GPT_PARTS_NUM ]; +char *tok, *t, *p, *s, *ss; +int i, ret; + + s =getenv ("partitions" ); +if (s ==NULL ) { + printf("%s: \"partitions\" env variable notdefined!\n",
common/cmd_gpt.c line 72
Quoted 3 lines
common/cmd_gpt.c +3
-0+ __func__); +return -1 ; + }It'd be nice to be able to pass the partition definition on the command-line instead of (or perhaps as an alternative to) reading an environment variable.
Some documentation of the expected format of the partitions variable would be useful. From the following patch, the format appears to be:
8M(csa-mmc),60M(u-boot),60M(kernel),...
Quoted 7 lines
That's not particularly extensible (think about allowing partition type UUID to or attributes to be specified), and the brackets are a bit painful. Can we use key/value for defining the values, and have a simple separate separator between fields and partitions, e.g. something like:
size=8M,name=csa-mmc;size=60M,name=u-boot;size=60M,name=kernel;...
This approach looks reasonable, but...
Quoted 5 lines
That would allow us to very easily allow new fields to be specified per partition in the future, e.g.:
uuid=XXXXX,size=512M,name=boot,type=21686148-6449-6E6F-744E-656564454649,attrs=2;uuid=YYYYY,size=7000M,name=root,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,attrs=0;...
it would be a pain to paste so long string to u-boot command line. Suppose we have 8 partitions to define. Then the definition string grows considerable.
For default restoration, it would be good to define the environment variable (like "partitions") to perform quick default restoration.
However there is a problem with passing UUID - size, name and attributes can be defined at ./include/config/{board}.h (partitions=size=8M,name=csa-mmc;size=60M,name=u-boot;size=60M,name=kernel) , but UUID shall be passed by user via command line or generated internally at u-boot (as it is proposed in this patch).
When passing from user it would look like:
gpt default uuid1 uuid2 .... uuid8
But we shall also think about using guid_gen() function (reimplemented) for handy and quick gpt restoration.
Quoted 18 lines
Quoted 4 lines
common/cmd_gpt.c +3
-0+U_BOOT_CMD( + gpt, CONFIG_SYS_MAXARGS, 1, do_gpt, + "GUID Partition Table",...
Quoted 2 lines
common/cmd_gpt.c +2
-0+"gpt restore - reset GPT partition to defaults\n" +"gpt dev #num - set device number\n" ...
common/cmd_gpt.c line 131
Quoted 5 lines
common/cmd_gpt.c +5
-0+static void set_gpt_dev (int dev) +{ + gpt_dev = dev; +} +Hmmm. I think it'd be better to specify the device each time the gpt command was invoked. That would be simpler to use, more flexible, and more consistent with how other commands such as "ext2load" operate.
Quoted 2 lines
In other words, I would get rid of "gpt dev" completely, and instead of implementing "gpt restore", implement "gpt restore mmc 0".
Agree - the same approach is in dfu.
Quoted 11 lines
I'm not sure "restore" is the correct name, given that the command can write arbitrary new partition layouts, rather than just restoring some specific hard-coded table from e.g. a backup image.
I'm not sure that "gpt" is even the best command name; it'd be nice if this were generic and could be extended to work with e.g. FAT in the future - something like:
part write usb 1 gpt uuid=XXXXX,size=512M,name=boot,... part write mmc 0 fat size=512M,attrs=0x80;...
I'm open for discussion. Since part command is not yet finished, I will use the gpt command for version 2 of this patch series. When we agree with rest of GPT implementation we can decide if gpt or part command will be used. OK?
Quoted 8 lines
common/cmd_gpt.c line 179
Quoted 5 lines
common/cmd_gpt.c +4
-0+U_BOOT_CMD ( + gpt,CONFIG_SYS_MAXARGS ,1 , do_gpt, +"GUID Partition Table" , + "show - show GPT\n"s/show/gpt show/
Quoted 11 lines
common/cmd_gpt.c line 137
Quoted 6 lines
common/cmd_gpt.c +6
-0+static void gpt_show (void ) +{ +struct mmc *mmc =find_mmc_device (gpt_dev); + +print_part_efi (&mmc->block_dev); +}Do we really need another way of showing partition tables; "mmc part", "usb part", ... already exist. I think if we want another way, it'd be better to add this functionality to my proposed "part" command, i.e. "part show mmc 0".
I agree that "gpt show" is not needed. Instead "mmc part" can be used.
Quoted 17 lines
common/cmd_gpt.c
Quoted 10 lines
common/cmd_gpt.c +6
-0+static int gpt_default (void ) +{ +struct mmc *mmc =find_mmc_device (gpt_dev); + +if (mmc ==NULL ) { + printf("%s: mmc dev %d NOT available\n", __func__,
gpt_dev);common/cmd_gpt.c +2
-0+return CMD_RET_FAILURE ; + }Why only allow mmc devices; what about USB for example? Other commands such as ext2load allow arbitrary device types to be used. Rob Herring recently posted some patches to unify how commands such as ext2load, ext2ls, fatload, fatls, ... all obtain a device/partition handle from their command-line - this patch should probably build on top of those patches.
Yes, but Rob's patches are not yet accepted to mainline. I'd prefer to not use patches which aren't accepted as a base for development.
Quoted 6 lines
common/cmd_gpt.c line 151
Quoted 5 lines
common/cmd_gpt.c +4
-0+puts ("Using default GPT UUID\n" ); + +return set_gpt_info (&mmc->block_dev); +}
I think, that most important change is to pass table with pointers to partition entries to set_gpt_table. Second thing is to fix guid_gen() function and change the format of "partitions" to be key=value pairs.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH 6/6 gpt: Enable support for GPT partition table restoration at Samsung's Trats
In reply to Lukasz MajewskiEnable support for GPT partition table restoration at Samsung's Trats development board.
--- include/configs/trats.h | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-)
include/configs/trats.h +22 -1
@@ -98,6 +98,7 @@#undef CONFIG_CMD_MTDPARTS#define CONFIG_CMD_MMC #define CONFIG_CMD_DFU +#define CONFIG_CMD_GPT /* FAT */ #define CONFIG_CMD_FAT
@@ -122,6 +123,24 @@#define CONFIG_BOOTBLOCK "10"#define CONFIG_ENV_COMMON_BOOT "${console} ${meminfo}" +/* Tizen - partitions definitions */ +#define PARTS_CSA "csa-mmc" +#define PARTS_BOOTLOADER "u-boot" +#define PARTS_KERNEL "kernel" +#define PARTS_ROOT "platform" +#define PARTS_DATA "data" +#define PARTS_CSC "csc" +#define PARTS_UMS "ums" + +#define PARTS_DEFAULT "8M("PARTS_CSA")"\ + ",60M("PARTS_BOOTLOADER")"\ + ",60M("PARTS_KERNEL")"\ + ",1G("PARTS_ROOT")"\ + ",3G("PARTS_DATA")"\ + ",150M("PARTS_CSC")"\ + ",-("PARTS_UMS")\0" +#define GPT_PARTS_NUM 7 +#define CONFIG_DFU_ALT \ "dfu_alt_info=" \ "u-boot mmc 80 400;" \
@@ -171,7 +190,8 @@"mmcbootpart=2\0" \"mmcrootpart=3\0" \"opts=always_resume=1\0" \ -CONFIG_DFU_ALT +"partitions=" PARTS_DEFAULT \ +CONFIG_DFU_ALT \/* Miscellaneous configurable options */ #define CONFIG_SYS_LONGHELP /* undef to save memory */
@@ -210,6 +230,7 @@#define CONFIG_ENV_OFFSET ((32 - 4) << 10)/* 32KiB - 4KiB */ #define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - GENERATED_GBL_DATA_SIZE)#define CONFIG_SYS_CACHELINE_SIZE 32
Signature · 1 line
1.7.2.3
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
In reply to Lukasz MajewskiHi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
e.g. http://patchwork.ozlabs.org/patch/179785/
I think, that we can cooperate to provide better EFI/GPT support.
In mine implementation the "gpt" command (with several sub commands) has been proposed
- we can discuss if this is a correct way to go.
Moreover, at this patch series a "weak" GUID generator is implemented. For now it is "good enough", since I consider the restoration as an emergency situation.
However,I wonder how can we provide better GUID (and in general random numbers pool) generator for u-boot.
Maybe md5sum command can be used with some running clock (WDT, or system clock from u-boot start up) data to provide better entropy?
Any ideas?
Regards,
Lukasz
Quoted 33 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration and display.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardLukasz Majewski (6):
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Replace theleXX_to_int()calls with ones defined at
<compiler.h>
gpt: Replacement of GPT structures members with ones indicating
endianness and size
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Tratscommon/Makefile | 1 + common/cmd_gpt.c | 182 ++++++++++++++++++++++++++ disk/part_efi.c | 334 +++++++++++++++++++++++++++++++++++++---------- disk/part_efi.h | 85 ++++++------ doc/README.gpt | 199 ++++++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/part.h | 2 + 7 files changed, 715 insertions(+), 111 deletions(-) create mode 100644 common/cmd_gpt.c create mode 100644 doc/README.gpt
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
Quoted 9 lines · Lukasz Majewski
Hi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
e.g. http://patchwork.ozlabs.org/patch/179785/
I think, that we can cooperate to provide better EFI/GPT support.
Quoted 7 lines
In mine implementation the "gpt" command (with several sub commands) has been proposed
- we can discuss if this is a correct way to go.Moreover, at this patch series a "weak" GUID generator is implemented. For now it is "good enough", since I consider the restoration as an emergency situation.
I think that (perhaps optionally) allowing the user to specify their own UUIDs would be a good idea; whatever was generating the script being executed might have access to a better entropy source.
Quoted 5 lines
However,I wonder how can we provide better GUID (and in general random numbers pool) generator for u-boot.
Maybe md5sum command can be used with some running clock (WDT, or system clock from u-boot start up) data to provide better entropy?
If there's a standard way of retrieving wall-clock, MAC address, ... it'd definitely be a good idea to include those entropy sources.
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
Hi Stephen,
Quoted 14 lines · Lukasz Majewski
Quoted 13 lines
Hi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
e.g. http://patchwork.ozlabs.org/patch/179785/
I think, that we can cooperate to provide better EFI/GPT support.
In mine implementation the "gpt" command (with several sub commands) has been proposed
- we can discuss if this is a correct way to go.
Quoted 7 lines
Quoted 3 lines
Moreover, at this patch series a "weak" GUID generator is implemented. For now it is "good enough", since I consider the restoration as an emergency situation.
I think that (perhaps optionally) allowing the user to specify their own UUIDs would be a good idea; whatever was generating the script being executed might have access to a better entropy source.
I think, that passing UUID as the command argument would be a better option than inventing own GUID generator, especially when tools like uuid were available.
Quoted 10 lines
Quoted 6 lines
However,I wonder how can we provide better GUID (and in general random numbers pool) generator for u-boot.
Maybe md5sum command can be used with some running clock (WDT, or system clock from u-boot start up) data to provide better entropy?
If there's a standard way of retrieving wall-clock, MAC address, ... it'd definitely be a good idea to include those entropy sources.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
In reply to Lukasz MajewskiQuoted 20 lines · Lukasz Majewski
Hi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
e.g. http://patchwork.ozlabs.org/patch/179785/
I think, that we can cooperate to provide better EFI/GPT support.
In mine implementation the "gpt" command (with several sub commands) has been proposed
- we can discuss if this is a correct way to go.Moreover, at this patch series a "weak" GUID generator is implemented. For now it is "good enough", since I consider the restoration as an emergency situation.
However,I wonder how can we provide better GUID (and in general random numbers pool) generator for u-boot.
Quoted 4 lines
Maybe md5sum command can be used with some running clock (WDT, or system clock from u-boot start up) data to provide better entropy?
Any ideas?
The question I'm asking is why we need partition creation support in u-boot in the first place? Next you need filesystem creation too?
Rob
Quoted 38 lines
Regards,
LukaszQuoted 33 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration and display.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardLukasz Majewski (6):
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Replace theleXX_to_int()calls with ones defined at
<compiler.h>
gpt: Replacement of GPT structures members with ones indicating
endianness and size
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Tratscommon/Makefile | 1 + common/cmd_gpt.c | 182 ++++++++++++++++++++++++++ disk/part_efi.c | 334 +++++++++++++++++++++++++++++++++++++---------- disk/part_efi.h | 85 ++++++------ doc/README.gpt | 199 ++++++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/part.h | 2 + 7 files changed, 715 insertions(+), 111 deletions(-) create mode 100644 common/cmd_gpt.c create mode 100644 doc/README.gpt
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
Hi Rob,
Quoted 2 lines
The question I'm asking is why we need partition creation support in u-boot in the first place?
Please consider following scenarios:
1. eMMC content is exported to the user (via UMS USB Mass Storage). Then user by chance or on purpose will corrupt MBR/GPT.
2. misuse of "mmc" command - user by chance writes mmc erase 0.
To unbrick the device one would simply use "gpt/part restore" command with already defined at ./include/config/{target}.h default settings for partitions.
Quoted 1 line
Next you need filesystem creation too?
I can use UMS to export eMMC to host PC (with restored partitions) and then use mkfs.* to create proper file system.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
Quoted 12 lines · Lukasz Majewski
Hi Rob,
Quoted 2 lines
The question I'm asking is why we need partition creation support in u-boot in the first place?
Please consider following scenarios:
1. eMMC content is exported to the user (via UMS USB Mass Storage). Then user by chance or on purpose will corrupt MBR/GPT.
2. misuse of "mmc" command - user by chance writes mmc erase 0.
Quoted 8 lines
To unbrick the device one would simply use "gpt/part restore" command with already defined at
./include/config/{target}.hdefault settings for partitions.Quoted 1 line
Next you need filesystem creation too?
I can use UMS to export eMMC to host PC (with restored partitions) and then use mkfs.* to create proper file system.
In that case, wouldn't you be exposing the entire eMMC device over UMS, and hence the user could just run fdisk/parted/... on the host, just like you're proposing they run mkfs on the host?
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions
Hi Stephen,
Quoted 17 lines · Lukasz Majewski
Quoted 16 lines
Hi Rob,
Quoted 2 lines
The question I'm asking is why we need partition creation support in u-boot in the first place?
Please consider following scenarios:
1. eMMC content is exported to the user (via UMS USB Mass Storage). Then user by chance or on purpose will corrupt MBR/GPT.
2. misuse of "mmc" command - user by chance writes mmc erase 0.
To unbrick the device one would simply use "gpt/part restore" command with already defined at
./include/config/{target}.hdefault settings for partitions.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Next you need filesystem creation too?
I can use UMS to export eMMC to host PC (with restored partitions) and then use mkfs.* to create proper file system.
In that case, wouldn't you be exposing the entire eMMC device over UMS, and hence the user could just run fdisk/parted/... on the host, just like you're proposing they run mkfs on the host?
This would be one option for restoring GPT table.
However, I believe, that there also should be a separate gpt command to do the trick and restore default GPT (with default partitions) only from u-boot (with no UMS interaction).
Additionally it is far more user friendly, when one type "gpt default" and default partitions are restored for a particular board (stored at ./include/configs/{board}.h .
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions - RESEND
In reply to Lukasz MajewskiHi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
e.g. http://patchwork.ozlabs.org/patch/179785/
I think, that we can cooperate to provide better EFI/GPT support.
In mine implementation the "gpt" command (with several sub commands) has been proposed
- we can discuss if this is a correct way to go.
Moreover, at this patch series a "weak" GUID generator is implemented. For now it is "good enough", since I consider the restoration as an emergency situation.
However,I wonder how can we provide better GUID (and in general random numbers pool) generator for u-boot.
Maybe md5sum command can be used with some running clock (WDT, or system clock from u-boot start up) data to provide better entropy?
Any ideas?
Regards,
Lukasz
p.s. I'm resending this patch, so please do not regard it as a spam.
Quoted 33 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration and display.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardLukasz Majewski (6):
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Replace theleXX_to_int()calls with ones defined at
<compiler.h>
gpt: Replacement of GPT structures members with ones indicating
endianness and size
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Tratscommon/Makefile | 1 + common/cmd_gpt.c | 182 ++++++++++++++++++++++++++ disk/part_efi.c | 334 +++++++++++++++++++++++++++++++++++++---------- disk/part_efi.h | 85 ++++++------ doc/README.gpt | 199 ++++++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/part.h | 2 + 7 files changed, 715 insertions(+), 111 deletions(-) create mode 100644 common/cmd_gpt.c create mode 100644 doc/README.gpt
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions - RESEND
Hi Lukasz,
Quoted 4 lines · Lukasz Majewski
Hi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
I'm not sure if Stephen got that - try "Stephen Warren" <[email protected]>.
Regards,
Simon
Quoted 70 lines
e.g. http://patchwork.ozlabs.org/patch/179785/
I think, that we can cooperate to provide better EFI/GPT support.
In mine implementation the "gpt" command (with several sub commands) has been proposed
- we can discuss if this is a correct way to go.Moreover, at this patch series a "weak" GUID generator is implemented. For now it is "good enough", since I consider the restoration as an emergency situation.
However,I wonder how can we provide better GUID (and in general random numbers pool) generator for u-boot.Maybe md5sum command can be used with some running clock (WDT, or system clock from u-boot start up) data to provide better entropy?
Any ideas?
Regards,
Lukaszp.s. I'm resending this patch, so please do not regard it as a spam.
Quoted 22 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration and display.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardLukasz Majewski (6):
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Replace theleXX_to_int()calls with ones defined at
<compiler.h>
gpt: Replacement of GPT structures members with ones indicating
endianness and size
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
TratsQuoted 11 lines
common/Makefile | 1 + common/cmd_gpt.c | 182 ++++++++++++++++++++++++++ disk/part_efi.c | 334 +++++++++++++++++++++++++++++++++++++---------- disk/part_efi.h | 85 ++++++------ doc/README.gpt | 199 ++++++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/part.h | 2 + 7 files changed, 715 insertions(+), 111 deletions(-) create mode 100644 common/cmd_gpt.c create mode 100644 doc/README.gpt--
Best regards,Lukasz Majewski
Samsung Poland R&D Center | Linux Platform Group
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] gpt: GUID/UUID - GPT restoration - open questions - RESEND
Hi Simon,
Quoted 4 lines
Hi Lukasz,
On Mon, Sep 3, 2012 at 2:28 AM, Lukasz Majewski
<[email protected]> wrote:
Quoted 8 lines
Quoted 4 lines
Hi Stephen,
I'm writing to you, since I've posted a patch series regarding GPT support for Samsung Trats board (you were on the CC).
I'm not sure if Stephen got that - try "Stephen Warren" <[email protected]>.
I've already received some some comments from Stephen.
I'm going to correct this patch series and provide version 2.
In short the GPT restoration needs some more work, especially at adding more abstraction to provide the code more useful.
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
cover gpt: GUID Partition Table (GPT) restoration
In reply to Lukasz MajewskiDear All,
Quoted 11 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration and display.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
Quoted 11 lines
Lukasz Majewski (6):
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Replace theleXX_to_int()calls with ones defined at
<compiler.h>
gpt: Replacement of GPT structures members with ones indicating
endianness and size
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Trats
Any ideas/comments ?
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
v2 cover gpt: GUID Partition Table (GPT) restoration
In reply to Lukasz MajewskiThis patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the part_efi.c file was performed to remove custom macros and make GPT related structures more readable.
Moreover the part_efi.h file has been moved to ./include directory to be easily available from other subsystems.
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
Chang Hyun Park (1):
gpt: The leXX_to_int() calls replaced with ones defined at
<compiler.h>
Lukasz Majewski (6):
vsprintf:fix: Change type returned by ustrtoul
part:efi: Move part_efi.h file to ./include
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Trats
common/Makefile | 1 + common/cmd_gpt.c | 405 +++++++++++++++++++++++++++++++++++++++++++++++ disk/part_efi.c | 210 ++++++++++++++++-------- disk/part_efi.h | 139 ---------------- doc/README.gpt | 207 ++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/exports.h | 2 +- include/part.h | 3 + include/part_efi.h | 143 +++++++++++++++++ lib/vsprintf.c | 2 +- 10 files changed, 923 insertions(+), 212 deletions(-) create mode 100644 common/cmd_gpt.c delete mode 100644 disk/part_efi.h create mode 100644 doc/README.gpt create mode 100644 include/part_efi.h
Signature · 1 line
1.7.2.3
PATCH v2 1/7 vsprintf:fix: Change type returned by ustrtoul
The ustrtoul shall convert string defined size (e.g. 1GiB) to unsigned long type (as its name implies).
Up till now it had returned int, which might cause problems with large numbers (GiB range), when interpreted as U2 signed numbers.
--- include/exports.h | 2 +- lib/vsprintf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/exports.h +1 -1
@@ -23,7 +23,7 @@ char *getenv (const char *name);int setenv (const char *varname,const char *varvalue);long simple_strtol (const char *cp,char **endp,unsigned int base);int strcmp (const char * cs,const char * ct); -int ustrtoul (const char *cp,char **endp,unsigned int base); +unsigned long ustrtoul (const char *cp,char **endp,unsigned int base);#if defined(CONFIG_CMD_I2C )int i2c_write (uchar ,uint ,int ,uchar * ,int );int i2c_read (uchar ,uint ,int ,uchar * ,int );
lib/vsprintf.c +1 -1
@@ -98,7 +98,7 @@ long simple_strtol(const char *cp,char **endp,unsigned int base)return simple_strtoul (cp,endp,base); } -int ustrtoul (const char *cp,char **endp,unsigned int base) +unsigned long ustrtoul (const char *cp,char **endp,unsigned int base) {unsigned long result =simple_strtoul (cp, endp, base);switch (**endp) {
Signature · 1 line
1.7.2.3
PATCH v2 2/7 part:efi: Move part_efi.h file to ./include
In reply to Lukasz MajewskiThis move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the part_efi.h file has been cleaned-up to supress checkpatch's warnings.
--- disk/part_efi.c | 2 +- disk/part_efi.h | 139 --------------------------------------------------- include/part_efi.h | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 140 deletions(-) delete mode 100644 disk/part_efi.h create mode 100644 include/part_efi.h
disk/part_efi.c +1 -1
@@ -34,7 +34,7 @@#include <command.h> #include <ide.h> #include <malloc.h> -#include "part_efi.h" +#include <part_efi.h> #include <linux/ctype.h> #if defined(CONFIG_CMD_IDE) || \
disk/part_efi.h deleted +0 -139
139 lines not on this page · raw message
include/part_efi.h new file +140 -0
140 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH v2 3/7 gpt:doc: GPT (GUID Partition Table) documentation
In reply to Lukasz MajewskiDocumentation of the GPT format.
---
Changes for v2:
- Typos correction.
- Adding guidlines about GPT restoration.
- Adding information about GUID generator
--- doc/README.gpt | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 207 insertions(+), 0 deletions(-) create mode 100644 doc/README.gpt
doc/README.gpt new file +207 -0
@@ -0,0 +1,207 @@ +# +# Copyright (C) 2012 Samsung Electronics +# +# Lukasz Majewski <[email protected]> +# +# +# 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.
Signature · 1 line
1.7.2.3
PATCH v2 4/7 gpt: The leXX_to_int() calls replaced with ones defined at <compiler.h>
In reply to Lukasz MajewskiFrom: Chang Hyun Park <[email protected]>
Custom definitions of le_XX_to_int functions have been replaced with standard ones, defined at <compiler.h>
Replacement of several GPT related structures members with ones indicating its endianness and proper size.
---
Changes for v2:
- Combining two commits regarding part_efi.{h|c}
--- disk/part_efi.c | 109 +++++++++++++++++++--------------------------------- include/part_efi.h | 85 +++++++++++++++++++++------------------- 2 files changed, 84 insertions(+), 110 deletions(-)
disk/part_efi.c +40 -69
@@ -44,34 +44,6 @@defined (CONFIG_MMC ) || \defined (CONFIG_SYSTEMACE ) -/* Convert char[2] in little endian format to the host format integer - */ -static inline unsigned short le16_to_int (unsigned char *le16) -{ -return ((le16[1 ] <<8 ) + le16[0 ]); -} - -/* Convert char[4] in little endian format to the host format integer -*/ -static inline unsigned long le32_to_int (unsigned char *le32) -{ -return ((le32[3 ] <<24 ) + (le32[2 ] <<16 ) + (le32[1 ] <<8 ) + le32[0 ]); -} - -/* Convert char[8] in little endian format to the host format integer -*/ -static inline unsigned long long le64_to_int (unsigned char *le64) -{ -return (((unsigned long long )le64[7 ] <<56 ) + - ((unsigned long long )le64[6 ] <<48 ) + - ((unsigned long long )le64[5 ] <<40 ) + - ((unsigned long long )le64[4 ] <<32 ) + - ((unsigned long long )le64[3 ] <<24 ) + - ((unsigned long long )le64[2 ] <<16 ) + - ((unsigned long long )le64[1 ] <<8 ) + - (unsigned long long )le64[0 ]); -} -/** * efi_crc32() - EFI version of crc32 function * @buf: buffer to calculate crc32 of
@@ -79,7 +51,7 @@ static inline unsigned long long le64_to_int(unsigned char *le64)* * Description: Returns EFI-style CRC32 value for @buf */ -static inline unsigned long efi_crc32 (const void *buf,unsigned long len) +static inline u32 efi_crc32 (const void *buf,u32 len) {return crc32 (0 , buf, len); }
@@ -137,13 +109,13 @@ void print_part_efi(block_dev_desc_t * dev_desc)debug ("%s: gpt-entry@%p\n" , __func__, gpt_pte);printf ("Part\tName\t\t\tStart LBA\tEnd LBA\n" ); -for (i =0 ; i <le32_to_int (gpt_head->num_partition_entries); i++) { +for (i =0 ; i <le32_to_cpu (gpt_head->num_partition_entries); i++) {if (is_pte_valid (&gpt_pte[i])) {printf ("%3d\t%-18s\t0x%08llX\t0x%08llX\n" , (i +1 ),print_efiname (&gpt_pte[i]), -le64_to_int (gpt_pte[i].starting_lba), -le64_to_int (gpt_pte[i].ending_lba)); + (u64 )le64_to_cpu (gpt_pte[i].starting_lba), + (u64 )le64_to_cpu (gpt_pte[i].ending_lba)); }else {break ;/* Stop at the first non valid PTE */ }
@@ -174,9 +146,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, }/* The ulong casting limits the maximum disk size to 2 TB */ - info->start = (ulong )le64_to_int (gpt_pte[part -1 ].starting_lba); + info->start = (u64 )le64_to_cpu (gpt_pte[part -1 ].starting_lba);/* The ending LBA is inclusive, to calculate size, add 1 to it */ - info->size = ((ulong )le64_to_int (gpt_pte[part -1 ].ending_lba) +1 ) + info->size = ((u64 )le64_to_cpu (gpt_pte[part -1 ].ending_lba) +1 ) - info->start; info->blksz =GPT_BLOCK_SIZE ;
@@ -215,7 +187,7 @@ int test_part_efi(block_dev_desc_t * dev_desc)static int pmbr_part_valid (struct partition *part) {if (part->sys_ind ==EFI_PMBR_OSTYPE_EFI_GPT && -le32_to_int (part->start_sect) ==1UL ) { +le32_to_cpu (part->start_sect) ==1UL ) {return 1 ; }
@@ -234,9 +206,8 @@ static int is_pmbr_valid(legacy_mbr * mbr) {int i =0 ; -if (!mbr ||le16_to_int (mbr->signature) !=MSDOS_MBR_SIGNATURE ) { +if (!mbr ||le16_to_cpu (mbr->signature) !=MSDOS_MBR_SIGNATURE )return 0 ; - }for (i =0 ; i <4 ; i++) {if (pmbr_part_valid (&mbr->partition_record[i])) {
@@ -259,8 +230,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)static int is_gpt_valid (block_dev_desc_t * dev_desc,unsigned long long lba,gpt_header * pgpt_head,gpt_entry ** pgpt_pte) { -unsigned char crc32_backup[4 ] = {0 }; -unsigned long calc_crc32; +u32 crc32_backup =0 ; +u32 calc_crc32;unsigned long long lastlba;if (!dev_desc || !pgpt_head) {
@@ -275,54 +246,54 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, }/* Check the GPT header signature */ -if (le64_to_int (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) { +if (le64_to_cpu (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) {printf ("GUID Partition Table Header signature is wrong:" "0x%llX != 0x%llX\n" , - (unsigned long long )le64_to_int (pgpt_head->signature), - (unsigned long long )GPT_HEADER_SIGNATURE ); + (u64 )le64_to_cpu (pgpt_head->signature), + (u64 )GPT_HEADER_SIGNATURE );return 0 ; }/* Check the GUID Partition Table CRC */ -memcpy (crc32_backup, pgpt_head->header_crc32,sizeof (crc32_backup)); -memset (pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); +memcpy (&crc32_backup, &pgpt_head->header_crc32,sizeof (crc32_backup)); +memset (&pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); calc_crc32 =efi_crc32 ((const unsigned char *)pgpt_head, -le32_to_int (pgpt_head->header_size)); +le32_to_cpu (pgpt_head->header_size)); -memcpy (pgpt_head->header_crc32, crc32_backup,sizeof (crc32_backup)); +memcpy (&pgpt_head->header_crc32, &crc32_backup,sizeof (crc32_backup)); -if (calc_crc32 !=le32_to_int (crc32_backup)) { +if (calc_crc32 !=le32_to_cpu (crc32_backup)) {printf ("GUID Partition Table Header CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (crc32_backup), calc_crc32); +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (crc32_backup), calc_crc32);return 0 ; }/* Check that the my_lba entry points to the LBA that contains the GPT */ -if (le64_to_int (pgpt_head->my_lba) != lba) { +if (le64_to_cpu (pgpt_head->my_lba) != lba) {printf ("GPT: my_lba incorrect: %llX != %llX\n" , - (unsigned long long )le64_to_int (pgpt_head->my_lba), - (unsigned long long )lba); + (u64 )le64_to_cpu (pgpt_head->my_lba), + (u64 )lba);return 0 ; }/* Check the first_usable_lba and last_usable_lba are within the disk. */ lastlba = (unsigned long long )dev_desc->lba; -if (le64_to_int (pgpt_head->first_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->first_usable_lba) > lastlba) {printf ("GPT: first_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), lastlba);return 0 ; } -if (le64_to_int (pgpt_head->last_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->last_usable_lba) > lastlba) {printf ("GPT: last_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);return 0 ; }debug ("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);/* Read and allocate Partition Table Entries */ *pgpt_pte =alloc_read_gpt_entries (dev_desc, pgpt_head);
@@ -333,13 +304,13 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,/* Check the GUID Partition Table Entry Array CRC */ calc_crc32 =efi_crc32 ((const unsigned char *)*pgpt_pte, -le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry)); +le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry)); -if (calc_crc32 !=le32_to_int (pgpt_head->partition_entry_array_crc32)) { +if (calc_crc32 !=le32_to_cpu (pgpt_head->partition_entry_array_crc32)) {printf ("GUID Partition Table Entry Array CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (pgpt_head->partition_entry_array_crc32), +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (pgpt_head->partition_entry_array_crc32), calc_crc32);free (*pgpt_pte);
@@ -370,12 +341,12 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,return NULL ; } - count =le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry); + count =le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry); -debug ("%s: count = %lu * %lu = %u\n" , __func__, -le32_to_int (pgpt_head->num_partition_entries), -le32_to_int (pgpt_head->sizeof_partition_entry), count); +debug ("%s: count = %u * %u = %u\n" , __func__, + (u32 )le32_to_cpu (pgpt_head->num_partition_entries), + (u32 )le32_to_cpu (pgpt_head->sizeof_partition_entry), count);/* Allocate memory for PTE, remember to FREE */ if (count !=0 ) {
@@ -390,7 +361,7 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,/* Read GPT Entries from device */ if (dev_desc->block_read (dev_desc->dev, - (unsigned long )le64_to_int (pgpt_head->partition_entry_lba), + (u64 )le64_to_cpu (pgpt_head->partition_entry_lba), (lbaint_t) (count /GPT_BLOCK_SIZE ), pte) != (count /GPT_BLOCK_SIZE )) {
include/part_efi.h +44 -41
124 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH v2 5/7 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Lukasz MajewskiThe restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
---
Changes for v2:
- Move GPT Header and Page Table Entries generation code to cmd_gpt.c
- Provide clean API to use set_gpt_table function for GPT restoration on a block device
--- disk/part_efi.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 3 ++ 2 files changed, 102 insertions(+), 0 deletions(-)
disk/part_efi.c +99 -0
@@ -403,4 +403,103 @@ static int is_pte_valid(gpt_entry * pte) return 1; } } + +/** +* set_protective_mbr(): Set the EFI protective MBR +* @param dev_desc - block device descriptor +* +* @return - zero on success, otherwise error +*/ +static int set_protective_mbr (block_dev_desc_t *dev_desc) +{ +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr)); +/* Append signature */ + p_mbr.signature =MSDOS_MBR_SIGNATURE ; + p_mbr.partition_record[0 ].sys_ind =EFI_PMBR_OSTYPE_EFI_GPT ; + p_mbr.partition_record[0 ].start_sect =1 ; + p_mbr.partition_record[0 ].nr_sects = (u32 ) dev_desc->lba; + +/* Write MBR sector to the MMC device */ +if (dev_desc->block_write (dev_desc->dev,0 ,1 , &p_mbr) !=1 ) { +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; + } + +return 0 ; +} + +/** +* set_gpt_table() - Restore the GUID Partition Table +* +* @param dev_desc - block device descriptor +* @param parts - number of partitions +* @param size - pointer to array with each partition size +* @param name - pointer to array with each partition name +* +* @return - zero on success, otherwise error +*/ +int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e) +{ +const int pte_blk_num = (GPT_ENTRY_NUMBERS *sizeof (gpt_entry)) / + dev_desc->blksz; +u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); + +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_e, +le32_to_cpu (gpt_h->num_partition_entries) * +le32_to_cpu (gpt_h->sizeof_partition_entry)); + gpt_h->partition_entry_array_crc32 =cpu_to_le32 (calc_crc32); + + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_h, +le32_to_cpu (gpt_h->header_size)); + gpt_h->header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the First GPT to the block right after the Legacy MBR */ +if (dev_desc->block_write (dev_desc->dev,1 ,1 , gpt_h) !=1 ) + goto err; + +if (dev_desc->block_write (dev_desc->dev,2 , pte_blk_num, gpt_e) + != pte_blk_num) + goto err; + +/* recalculate the values for the Second GPT Header*/ + val =le64_to_cpu (gpt_h->my_lba); + gpt_h->my_lba = gpt_h->alternate_lba; + gpt_h->alternate_lba =cpu_to_le64 (val); + gpt_h->header_crc32 =0 ; + + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_h, +le32_to_cpu (gpt_h->header_size)); + gpt_h->header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the Second GPT that is located at the end of the disk */ +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h->last_usable_lba +1 ), + pte_blk_num, gpt_e) != pte_blk_num) + goto err; + +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h->my_lba),1 , gpt_h) !=1 ) + goto err; + +printf ("GPT successfully written to block device!\n" ); +return 0 ; + + err: +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; +}#endif
include/part.h +3 -0
@@ -157,10 +157,13 @@ int test_part_amiga (block_dev_desc_t *dev_desc);#endif #ifdef CONFIG_EFI_PARTITION +#include <part_efi.h> /* disk/part_efi.c */ int get_partition_info_efi (block_dev_desc_t * dev_desc,int part,disk_partition_t *info);void print_part_efi (block_dev_desc_t *dev_desc);int test_part_efi (block_dev_desc_t *dev_desc); +int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e);#endif #endif /* _PART_H */
Signature · 1 line
1.7.2.3
PATCH v2 5/7 gpt: Support for GPT (GUID Partition Table) restoration
Quoted 5 lines · Lukasz Majewski
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>
[sinp]
Review
Quoted 2 lines
(quoted diff) +2
-0+ + printf("GPT successfully written to block device!\n");
puts() please. Thanks!
Signature · 1 line
Tom
PATCH v2 6/7 gpt: Support for new "gpt" command
In reply to Lukasz MajewskiNew command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the the gd->start_addr_sp for entrophy pool. Moreover the pool address is used as crc32 seed.
---
Changes for v2:
- gpt command now accepts device medium and its number (e.g. gpt mmc 0)
- UUIDs can be passed via u-boot prompt when used with gpt command
- Format of restored GPT has been changed - now key=value pairs are used 'name="PARTS_CSA",size=8MiB;\ ' 'name="PARTS_BOOTLOADER",size=60MiB; \'
- guid_gen now accepts "pool" pointer and guid pointer
- gd->start_addr_sp is used as a primary source of entrophy
- static buffers definitions have been removed
- remove memsize_to_blocks function with call to standard ustrtoul
- doxygen comments for functions added
--- common/Makefile | 1 + common/cmd_gpt.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+), 0 deletions(-) create mode 100644 common/cmd_gpt.c
common/Makefile +1 -0
@@ -185,6 +185,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o +COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o endif ifdef CONFIG_SPL_BUILD
common/cmd_gpt.c new file +405 -0
405 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH v2 6/7 gpt: Support for new "gpt" command
Quoted 8 lines · Lukasz Majewski
New command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with
CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the thegd->start_addr_spfor entrophy pool. Moreover the pool address is used as crc32 seed.Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>
[snip]
common/cmd_gpt.c line 166
Quoted 7 lines
common/cmd_gpt.c new file +7
-0+/* allocate remaining memory in last partition */ +if (i != parts -1 ) { + gpt_e[i].ending_lba = +cpu_to_le64 (offset + size[i] -1 ); + }else { + gpt_e[i].ending_lba = gpt_h->last_usable_lba; + }
Extra curly braces. That's all I've seen in this patch however, so getting close :)
Signature · 1 line
Tom
PATCH v2 7/7 gpt: Enable support for GPT partition table restoration at Samsung's Trats
In reply to Lukasz MajewskiEnable support for GPT partition table restoration at Samsung's Trats development board.
---
Changes for v2:
- New format for default GPT partitions (key=value pairs)
- replace size definitions with more readable description(1GiB instead of 1G)
--- include/configs/trats.h | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-)
include/configs/trats.h +22 -1
@@ -98,6 +98,7 @@#undef CONFIG_CMD_MTDPARTS#define CONFIG_CMD_MMC #define CONFIG_CMD_DFU +#define CONFIG_CMD_GPT /* FAT */ #define CONFIG_CMD_FAT
@@ -122,6 +123,24 @@#define CONFIG_BOOTBLOCK "10"#define CONFIG_ENV_COMMON_BOOT "${console} ${meminfo}" +/* Tizen - partitions definitions */ +#define PARTS_CSA "csa-mmc" +#define PARTS_BOOTLOADER "u-boot" +#define PARTS_KERNEL "kernel" +#define PARTS_ROOT "platform" +#define PARTS_DATA "data" +#define PARTS_CSC "csc" +#define PARTS_UMS "ums" + +#define PARTS_DEFAULT "name="PARTS_CSA",size=8MiB;"\ + "name="PARTS_BOOTLOADER",size=60MiB;"\ + "name="PARTS_KERNEL",size=60MiB;"\ + "name="PARTS_ROOT",size=1GiB;"\ + "name="PARTS_DATA",size=3GiB;"\ + "name="PARTS_CSC",size=150MiB;"\ + "name="PARTS_UMS",size=-\0" +#define GPT_PARTS_NUM 7 +#define CONFIG_DFU_ALT \ "dfu_alt_info=" \ "u-boot mmc 80 400;" \
@@ -171,7 +190,8 @@"mmcbootpart=2\0" \"mmcrootpart=3\0" \"opts=always_resume=1\0" \ -CONFIG_DFU_ALT +"partitions=" PARTS_DEFAULT \ +CONFIG_DFU_ALT \/* Miscellaneous configurable options */ #define CONFIG_SYS_LONGHELP /* undef to save memory */
@@ -210,6 +230,7 @@#define CONFIG_ENV_OFFSET ((32 - 4) << 10)/* 32KiB - 4KiB */ #define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - GENERATED_GBL_DATA_SIZE)#define CONFIG_SYS_CACHELINE_SIZE 32
Signature · 1 line
1.7.2.3
v2 cover gpt: GUID Partition Table (GPT) restoration
In reply to Lukasz MajewskiQuoted 6 lines · Lukasz Majewski
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.
Quoted 7 lines
Moreover the
part_efi.hfile has been moved to ./include directory to be easily available from other subsystems.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
I had two very minor comments. Aside from that, please make sure the series is checkpatch clean (I haven't checked). Thanks!
Signature · 1 line
Tom
v2 cover gpt: GUID Partition Table (GPT) restoration
Hi Tom,
Thanks for review.
Quoted 10 lines · Lukasz Majewski
Quoted 9 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.Moreover the
part_efi.hfile has been moved to ./include directory to be easily available from other subsystems.
Quoted 7 lines
Quoted 4 lines
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardI had two very minor comments. Aside from that, please make sure the series is checkpatch clean (I haven't checked). Thanks!
There is one little problem with the checkpatch:
The patch:
[PATCH v2 2/7] part:efi: Move part_efi.h file to ./include
"touches" some legacy code, and checkpatch complaints about e.g.:
WARNING: do not add new typedefs
#281: FILE: include/part_efi.h:97:
+typedef struct _gpt_header {
which I don't want to change in this patch series.
Moreover it complaints about:
WARNING: __packed is preferred over __attribute__((packed)) #303: FILE: include/part_efi.h:119:
+} __attribute__ ((packed)) gpt_entry_attributes;
which was changed at further patch (which I believe is a better place to do so):
[PATCH v2 4/7] gpt: The leXX_to_int() calls replaced with ones defined at <compiler.h>
To sum up - some checkpatch warnings appears since I've moved a legacy code to a new place.
Rest of those patches is checkpatch "clean".
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
v2 cover gpt: GUID Partition Table (GPT) restoration
Quoted 44 lines · Lukasz Majewski
Hi Tom,
Thanks for review.
Quoted 10 lines · Lukasz Majewski
Quoted 9 lines
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.Moreover the
part_efi.hfile has been moved to ./include directory to be easily available from other subsystems.Quoted 7 lines
Quoted 4 lines
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardI had two very minor comments. Aside from that, please make sure the series is checkpatch clean (I haven't checked). Thanks!
There is one little problem with the checkpatch:
The patch:
[PATCH v2 2/7] part:efi: Movepart_efi.hfile to ./include"touches" some legacy code, and checkpatch complaints about e.g.:
WARNING: do not add new typedefs
#281: FILE:include/part_efi.h:97:
+typedef struct_gpt_header{which I don't want to change in this patch series.
Moreover it complaints about:
WARNING:__packedis preferred over __attribute__((packed)) #303: FILE:include/part_efi.h:119:
+}__attribute__((packed))gpt_entry_attributes;
which was changed at further patch (which I believe is a better place to do so):
[PATCH v2 4/7] gpt: TheleXX_to_int()calls replaced with ones defined at <compiler.h>
Quoted 3 lines
To sum up - some checkpatch warnings appears since I've moved a legacy code to a new place.
Rest of those patches is checkpatch "clean".
Sounds good to me, thanks for the explanation.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120913/a2f34f6d/attachment.pgp>
v3 cover gpt: GUID Partition Table (GPT) restoration
In reply to Lukasz MajewskiThis patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the part_efi.c file was performed to remove custom macros and make GPT related structures more readable.
Moreover the part_efi.h file has been moved to ./include directory to be easily available from other subsystems.
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
Chang Hyun Park (1):
gpt: The leXX_to_int() calls replaced with ones defined at
<compiler.h>
Lukasz Majewski (6):
vsprintf:fix: Change type returned by ustrtoul
part:efi: Move part_efi.h file to ./include
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Support for new "gpt" command
gpt: Enable support for GPT partition table restoration at Samsung's
Trats
common/Makefile | 1 + common/cmd_gpt.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++ disk/part_efi.c | 210 ++++++++++++++++-------- disk/part_efi.h | 139 ---------------- doc/README.gpt | 207 ++++++++++++++++++++++++ include/configs/trats.h | 23 +++- include/exports.h | 2 +- include/part.h | 3 + include/part_efi.h | 143 +++++++++++++++++ lib/vsprintf.c | 2 +- 10 files changed, 922 insertions(+), 212 deletions(-) create mode 100644 common/cmd_gpt.c delete mode 100644 disk/part_efi.h create mode 100644 doc/README.gpt create mode 100644 include/part_efi.h
Signature · 1 line
1.7.2.3
PATCH v3 1/7 vsprintf:fix: Change type returned by ustrtoul
The ustrtoul shall convert string defined size (e.g. 1GiB) to unsigned long type (as its name implies).
Up till now it had returned int, which might cause problems with large numbers (GiB range), when interpreted as U2 signed numbers.
---
Changes for v3:
- None
--- include/exports.h | 2 +- lib/vsprintf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/exports.h +1 -1
@@ -23,7 +23,7 @@ char *getenv (const char *name);int setenv (const char *varname,const char *varvalue);long simple_strtol (const char *cp,char **endp,unsigned int base);int strcmp (const char * cs,const char * ct); -int ustrtoul (const char *cp,char **endp,unsigned int base); +unsigned long ustrtoul (const char *cp,char **endp,unsigned int base);#if defined(CONFIG_CMD_I2C )int i2c_write (uchar ,uint ,int ,uchar * ,int );int i2c_read (uchar ,uint ,int ,uchar * ,int );
lib/vsprintf.c +1 -1
@@ -98,7 +98,7 @@ long simple_strtol(const char *cp,char **endp,unsigned int base)return simple_strtoul (cp,endp,base); } -int ustrtoul (const char *cp,char **endp,unsigned int base) +unsigned long ustrtoul (const char *cp,char **endp,unsigned int base) {unsigned long result =simple_strtoul (cp, endp, base);switch (**endp) {
Signature · 1 line
1.7.2.3
PATCH v3 2/7 part:efi: Move part_efi.h file to ./include
In reply to Lukasz MajewskiThis move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the part_efi.h file has been cleaned-up to supress checkpatch's warnings.
---
Changes for v3:
- None
--- disk/part_efi.c | 2 +- disk/part_efi.h | 139 --------------------------------------------------- include/part_efi.h | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 140 deletions(-) delete mode 100644 disk/part_efi.h create mode 100644 include/part_efi.h
disk/part_efi.c +1 -1
@@ -34,7 +34,7 @@#include <command.h> #include <ide.h> #include <malloc.h> -#include "part_efi.h" +#include <part_efi.h> #include <linux/ctype.h> #if defined(CONFIG_CMD_IDE) || \
disk/part_efi.h deleted +0 -139
139 lines not on this page · raw message
include/part_efi.h new file +140 -0
140 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH v3 2/7 part:efi: Move part_efi.h file to ./include
Quoted 11 lines · On Thu, 13 Sep 2012 10:10:00 +0200 Lukasz Majewski <[email protected]>…
This move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the
part_efi.hfile has been cleaned-up to supress checkpatch's warnings.Signed-off-by Lukasz Majewski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>---
Changes for v3:
- None
Quoted 7 lines
--- disk/part_efi.c | 2 +- disk/part_efi.h | 139 --------------------------------------------------- include/part_efi.h | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 140 deletions(-) delete mode 100644 disk/part_efi.h create mode 100644 include/part_efi.h
use git format-patch's -M/-C flags when posting code movement/copying patches.
Kim
PATCH v3 3/7 gpt:doc: GPT (GUID Partition Table) documentation
In reply to Lukasz MajewskiDocumentation of the GPT format.
---
Changes for v2:
- Typos correction.
- Adding guidlines about GPT restoration.
- Adding information about GUID generator
Changes for v3:
- None
--- doc/README.gpt | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 207 insertions(+), 0 deletions(-) create mode 100644 doc/README.gpt
doc/README.gpt new file +207 -0
@@ -0,0 +1,207 @@ +# +# Copyright (C) 2012 Samsung Electronics +# +# Lukasz Majewski <[email protected]> +# +# +# 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.
Signature · 1 line
1.7.2.3
PATCH v3 3/7 gpt:doc: GPT (GUID Partition Table) documentation
doc/README.gpt line 176
Quoted 12 lines · Lukasz Majewski
Documentation of the GPT format.
doc/README.gpt +8
-0+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?
doc/README.gpt line 187
Quoted 11 lines
doc/README.gpt +11
-0+ - #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}
PATCH v3 3/7 gpt:doc: GPT (GUID Partition Table) documentation
Hi Stephen,
Quoted 22 lines · Lukasz Majewski
Quoted 11 lines
Documentation of the GPT format.
doc/README.gpt +7
-0+Example usage: +============== + +To restore GUID partition table one needs to: +1. at ./include/configs/{board}.h + - define "partitions=" environment variable with format: +Quoted 3 lines
"name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;"
+ - defineGPT_PARTS_NUMwith actual number of partitions (as
defined above)That seems unfortunate; the partitions variable and
GPT_PARTS_NUMdefine 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 updateGPT_PARTS_NUMwhen editing the hard-coded value?).
Quoted 2 lines
Instead, can't
GPT_PARTS_NUMbe 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.
Quoted 33 lines
Quoted 10 lines
doc/README.gpt +9
-0+ - #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 isQuoted 4 lines
acceptable.
+ When UUIDs are NOT provided, internal (rather weak) GUID
generator will be
+ used insteadHmmm. 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:
Quoted 8 lines
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).
Quoted 1 line
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.
Quoted 5 lines
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.
Quoted 9 lines
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.
Quoted 2 lines
gpt create mmc 0 ${partitions}
gpt set-name mmc 0 ${partition-id} ${new-name}
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH v3 3/7 gpt:doc: GPT (GUID Partition Table) documentation
Hi Stephen,
Quoted 89 lines
Quoted 23 lines · Lukasz Majewski
Quoted 11 lines
Documentation of the GPT format.
doc/README.gpt +7
-0+Example usage: +============== + +To restore GUID partition table one needs to: +1. at ./include/configs/{board}.h + - define "partitions=" environment variable with format: +Quoted 3 lines
"name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;"
+ - defineGPT_PARTS_NUMwith actual number of partitions (as
defined above)That seems unfortunate; the partitions variable and
GPT_PARTS_NUMdefine 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 updateGPT_PARTS_NUMwhen editing the hard-coded value?).Quoted 2 lines
Instead, can't
GPT_PARTS_NUMbe removed, and the code simply count the number of entries in the partitions variable?Yes, the
GPT_PARTS_NUMcan (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.Quoted 33 lines
Quoted 10 lines
doc/README.gpt +9
-0+ - #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 isQuoted 4 lines
acceptable.
+ When UUIDs are NOT provided, internal (rather weak) GUID
generator will be
+ used insteadHmmm. 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:
Quoted 8 lines
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).
Quoted 1 line
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)
Quoted 5 lines
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.
Quoted 5 lines
Quoted 5 lines
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.
Quoted 22 lines
Quoted 11 lines
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.
Quoted 2 lines
gpt create mmc 0 ${partitions}
gpt set-name mmc 0 ${partition-id} ${new-name}
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH v3 3/7 gpt:doc: GPT (GUID Partition Table) documentation
In reply to Lukasz MajewskiQuoted 3 lines · Lukasz Majewski
Hi Stephen,
Quoted 1 line · Lukasz Majewski
... [patch to implement GPT creation]
Quoted 29 lines
Quoted 11 lines
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).
Quoted 1 line
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)
Quoted 4 lines
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.
...
Quoted 8 lines
Quoted 4 lines
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.
PATCH v3 4/7 gpt: The leXX_to_int() calls replaced with ones defined at <compiler.h>
In reply to Lukasz MajewskiFrom: Chang Hyun Park <[email protected]>
Custom definitions of le_XX_to_int functions have been replaced with standard ones, defined at <compiler.h>
Replacement of several GPT related structures members with ones indicating its endianness and proper size.
---
Changes for v2:
- Combining two commits regarding part_efi.{h|c}
Changes for v3:
- None
--- disk/part_efi.c | 109 +++++++++++++++++++--------------------------------- include/part_efi.h | 85 +++++++++++++++++++++------------------- 2 files changed, 84 insertions(+), 110 deletions(-)
disk/part_efi.c +40 -69
@@ -44,34 +44,6 @@defined (CONFIG_MMC ) || \defined (CONFIG_SYSTEMACE ) -/* Convert char[2] in little endian format to the host format integer - */ -static inline unsigned short le16_to_int (unsigned char *le16) -{ -return ((le16[1 ] <<8 ) + le16[0 ]); -} - -/* Convert char[4] in little endian format to the host format integer -*/ -static inline unsigned long le32_to_int (unsigned char *le32) -{ -return ((le32[3 ] <<24 ) + (le32[2 ] <<16 ) + (le32[1 ] <<8 ) + le32[0 ]); -} - -/* Convert char[8] in little endian format to the host format integer -*/ -static inline unsigned long long le64_to_int (unsigned char *le64) -{ -return (((unsigned long long )le64[7 ] <<56 ) + - ((unsigned long long )le64[6 ] <<48 ) + - ((unsigned long long )le64[5 ] <<40 ) + - ((unsigned long long )le64[4 ] <<32 ) + - ((unsigned long long )le64[3 ] <<24 ) + - ((unsigned long long )le64[2 ] <<16 ) + - ((unsigned long long )le64[1 ] <<8 ) + - (unsigned long long )le64[0 ]); -} -/** * efi_crc32() - EFI version of crc32 function * @buf: buffer to calculate crc32 of
@@ -79,7 +51,7 @@ static inline unsigned long long le64_to_int(unsigned char *le64)* * Description: Returns EFI-style CRC32 value for @buf */ -static inline unsigned long efi_crc32 (const void *buf,unsigned long len) +static inline u32 efi_crc32 (const void *buf,u32 len) {return crc32 (0 , buf, len); }
@@ -137,13 +109,13 @@ void print_part_efi(block_dev_desc_t * dev_desc)debug ("%s: gpt-entry@%p\n" , __func__, gpt_pte);printf ("Part\tName\t\t\tStart LBA\tEnd LBA\n" ); -for (i =0 ; i <le32_to_int (gpt_head->num_partition_entries); i++) { +for (i =0 ; i <le32_to_cpu (gpt_head->num_partition_entries); i++) {if (is_pte_valid (&gpt_pte[i])) {printf ("%3d\t%-18s\t0x%08llX\t0x%08llX\n" , (i +1 ),print_efiname (&gpt_pte[i]), -le64_to_int (gpt_pte[i].starting_lba), -le64_to_int (gpt_pte[i].ending_lba)); + (u64 )le64_to_cpu (gpt_pte[i].starting_lba), + (u64 )le64_to_cpu (gpt_pte[i].ending_lba)); }else {break ;/* Stop at the first non valid PTE */ }
@@ -174,9 +146,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, }/* The ulong casting limits the maximum disk size to 2 TB */ - info->start = (ulong )le64_to_int (gpt_pte[part -1 ].starting_lba); + info->start = (u64 )le64_to_cpu (gpt_pte[part -1 ].starting_lba);/* The ending LBA is inclusive, to calculate size, add 1 to it */ - info->size = ((ulong )le64_to_int (gpt_pte[part -1 ].ending_lba) +1 ) + info->size = ((u64 )le64_to_cpu (gpt_pte[part -1 ].ending_lba) +1 ) - info->start; info->blksz =GPT_BLOCK_SIZE ;
@@ -215,7 +187,7 @@ int test_part_efi(block_dev_desc_t * dev_desc)static int pmbr_part_valid (struct partition *part) {if (part->sys_ind ==EFI_PMBR_OSTYPE_EFI_GPT && -le32_to_int (part->start_sect) ==1UL ) { +le32_to_cpu (part->start_sect) ==1UL ) {return 1 ; }
@@ -234,9 +206,8 @@ static int is_pmbr_valid(legacy_mbr * mbr) {int i =0 ; -if (!mbr ||le16_to_int (mbr->signature) !=MSDOS_MBR_SIGNATURE ) { +if (!mbr ||le16_to_cpu (mbr->signature) !=MSDOS_MBR_SIGNATURE )return 0 ; - }for (i =0 ; i <4 ; i++) {if (pmbr_part_valid (&mbr->partition_record[i])) {
@@ -259,8 +230,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)static int is_gpt_valid (block_dev_desc_t * dev_desc,unsigned long long lba,gpt_header * pgpt_head,gpt_entry ** pgpt_pte) { -unsigned char crc32_backup[4 ] = {0 }; -unsigned long calc_crc32; +u32 crc32_backup =0 ; +u32 calc_crc32;unsigned long long lastlba;if (!dev_desc || !pgpt_head) {
@@ -275,54 +246,54 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, }/* Check the GPT header signature */ -if (le64_to_int (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) { +if (le64_to_cpu (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) {printf ("GUID Partition Table Header signature is wrong:" "0x%llX != 0x%llX\n" , - (unsigned long long )le64_to_int (pgpt_head->signature), - (unsigned long long )GPT_HEADER_SIGNATURE ); + (u64 )le64_to_cpu (pgpt_head->signature), + (u64 )GPT_HEADER_SIGNATURE );return 0 ; }/* Check the GUID Partition Table CRC */ -memcpy (crc32_backup, pgpt_head->header_crc32,sizeof (crc32_backup)); -memset (pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); +memcpy (&crc32_backup, &pgpt_head->header_crc32,sizeof (crc32_backup)); +memset (&pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); calc_crc32 =efi_crc32 ((const unsigned char *)pgpt_head, -le32_to_int (pgpt_head->header_size)); +le32_to_cpu (pgpt_head->header_size)); -memcpy (pgpt_head->header_crc32, crc32_backup,sizeof (crc32_backup)); +memcpy (&pgpt_head->header_crc32, &crc32_backup,sizeof (crc32_backup)); -if (calc_crc32 !=le32_to_int (crc32_backup)) { +if (calc_crc32 !=le32_to_cpu (crc32_backup)) {printf ("GUID Partition Table Header CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (crc32_backup), calc_crc32); +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (crc32_backup), calc_crc32);return 0 ; }/* Check that the my_lba entry points to the LBA that contains the GPT */ -if (le64_to_int (pgpt_head->my_lba) != lba) { +if (le64_to_cpu (pgpt_head->my_lba) != lba) {printf ("GPT: my_lba incorrect: %llX != %llX\n" , - (unsigned long long )le64_to_int (pgpt_head->my_lba), - (unsigned long long )lba); + (u64 )le64_to_cpu (pgpt_head->my_lba), + (u64 )lba);return 0 ; }/* Check the first_usable_lba and last_usable_lba are within the disk. */ lastlba = (unsigned long long )dev_desc->lba; -if (le64_to_int (pgpt_head->first_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->first_usable_lba) > lastlba) {printf ("GPT: first_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), lastlba);return 0 ; } -if (le64_to_int (pgpt_head->last_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->last_usable_lba) > lastlba) {printf ("GPT: last_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);return 0 ; }debug ("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);/* Read and allocate Partition Table Entries */ *pgpt_pte =alloc_read_gpt_entries (dev_desc, pgpt_head);
@@ -333,13 +304,13 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,/* Check the GUID Partition Table Entry Array CRC */ calc_crc32 =efi_crc32 ((const unsigned char *)*pgpt_pte, -le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry)); +le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry)); -if (calc_crc32 !=le32_to_int (pgpt_head->partition_entry_array_crc32)) { +if (calc_crc32 !=le32_to_cpu (pgpt_head->partition_entry_array_crc32)) {printf ("GUID Partition Table Entry Array CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (pgpt_head->partition_entry_array_crc32), +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (pgpt_head->partition_entry_array_crc32), calc_crc32);free (*pgpt_pte);
@@ -370,12 +341,12 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,return NULL ; } - count =le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry); + count =le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry); -debug ("%s: count = %lu * %lu = %u\n" , __func__, -le32_to_int (pgpt_head->num_partition_entries), -le32_to_int (pgpt_head->sizeof_partition_entry), count); +debug ("%s: count = %u * %u = %u\n" , __func__, + (u32 )le32_to_cpu (pgpt_head->num_partition_entries), + (u32 )le32_to_cpu (pgpt_head->sizeof_partition_entry), count);/* Allocate memory for PTE, remember to FREE */ if (count !=0 ) {
@@ -390,7 +361,7 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,/* Read GPT Entries from device */ if (dev_desc->block_read (dev_desc->dev, - (unsigned long )le64_to_int (pgpt_head->partition_entry_lba), + (u64 )le64_to_cpu (pgpt_head->partition_entry_lba), (lbaint_t) (count /GPT_BLOCK_SIZE ), pte) != (count /GPT_BLOCK_SIZE )) {
include/part_efi.h +44 -41
124 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH v3 5/7 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Lukasz MajewskiThe restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
---
Changes for v2:
- Move GPT Header and Page Table Entries generation code to cmd_gpt.c
- Provide clean API to use set_gpt_table function for GPT restoration on a block device
Changes for v3:
- Replace printf with puts
--- disk/part_efi.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 3 ++ 2 files changed, 102 insertions(+), 0 deletions(-)
disk/part_efi.c +99 -0
@@ -403,4 +403,103 @@ static int is_pte_valid(gpt_entry * pte) return 1; } } + +/** +* set_protective_mbr(): Set the EFI protective MBR +* @param dev_desc - block device descriptor +* +* @return - zero on success, otherwise error +*/ +static int set_protective_mbr (block_dev_desc_t *dev_desc) +{ +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr)); +/* Append signature */ + p_mbr.signature =MSDOS_MBR_SIGNATURE ; + p_mbr.partition_record[0 ].sys_ind =EFI_PMBR_OSTYPE_EFI_GPT ; + p_mbr.partition_record[0 ].start_sect =1 ; + p_mbr.partition_record[0 ].nr_sects = (u32 ) dev_desc->lba; + +/* Write MBR sector to the MMC device */ +if (dev_desc->block_write (dev_desc->dev,0 ,1 , &p_mbr) !=1 ) { +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; + } + +return 0 ; +} + +/** +* set_gpt_table() - Restore the GUID Partition Table +* +* @param dev_desc - block device descriptor +* @param parts - number of partitions +* @param size - pointer to array with each partition size +* @param name - pointer to array with each partition name +* +* @return - zero on success, otherwise error +*/ +int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e) +{ +const int pte_blk_num = (GPT_ENTRY_NUMBERS *sizeof (gpt_entry)) / + dev_desc->blksz; +u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); + +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_e, +le32_to_cpu (gpt_h->num_partition_entries) * +le32_to_cpu (gpt_h->sizeof_partition_entry)); + gpt_h->partition_entry_array_crc32 =cpu_to_le32 (calc_crc32); + + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_h, +le32_to_cpu (gpt_h->header_size)); + gpt_h->header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the First GPT to the block right after the Legacy MBR */ +if (dev_desc->block_write (dev_desc->dev,1 ,1 , gpt_h) !=1 ) + goto err; + +if (dev_desc->block_write (dev_desc->dev,2 , pte_blk_num, gpt_e) + != pte_blk_num) + goto err; + +/* recalculate the values for the Second GPT Header*/ + val =le64_to_cpu (gpt_h->my_lba); + gpt_h->my_lba = gpt_h->alternate_lba; + gpt_h->alternate_lba =cpu_to_le64 (val); + gpt_h->header_crc32 =0 ; + + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_h, +le32_to_cpu (gpt_h->header_size)); + gpt_h->header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the Second GPT that is located at the end of the disk */ +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h->last_usable_lba +1 ), + pte_blk_num, gpt_e) != pte_blk_num) + goto err; + +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h->my_lba),1 , gpt_h) !=1 ) + goto err; + +puts ("GPT successfully written to block device!\n" ); +return 0 ; + + err: +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; +}#endif
include/part.h +3 -0
@@ -157,10 +157,13 @@ int test_part_amiga (block_dev_desc_t *dev_desc);#endif #ifdef CONFIG_EFI_PARTITION +#include <part_efi.h> /* disk/part_efi.c */ int get_partition_info_efi (block_dev_desc_t * dev_desc,int part,disk_partition_t *info);void print_part_efi (block_dev_desc_t *dev_desc);int test_part_efi (block_dev_desc_t *dev_desc); +int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e);#endif #endif /* _PART_H */
Signature · 1 line
1.7.2.3
PATCH v3 5/7 gpt: Support for GPT (GUID Partition Table) restoration
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 166
Quoted 7 lines · Lukasz Majewski
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
include/part.h +2
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e);
The API here isn't very generic; it requires the caller to have formatted the GPT entirely by itself, which means having complete knowledge of how to lay out a GPT header and partition table entry. Right now, all that knowledge is contained inside the implementation of the "gpt" command - what if some other unrelated code wanted to write a GPT; it'd have to duplicate everything.
I was thinking of a much more generic interface, where each partition is described using abstract structs, and the creation of the actual on-disk layout is handling inside the set_gpt_table() function. That would presumably allow the same abstract structs to be passed to e.g. set_mbr_partition_table() and a generic "ptable create" command to be created.
PATCH v3 5/7 gpt: Support for GPT (GUID Partition Table) restoration
Hi Stephen,
Quoted 6 lines · Lukasz Majewski
Quoted 4 lines
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
include/part.h +0
-0
Quoted 9 lines
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 166
Quoted 2 lines
include/part.h +2
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e);The API here isn't very generic; it requires the caller to have formatted the GPT entirely by itself, which means having complete knowledge of how to lay out a GPT header and partition table entry. Right now, all that knowledge is contained inside the implementation of the "gpt" command - what if some other unrelated code wanted to write a GPT; it'd have to duplicate everything.
I must admit, that you are correct here.
Quoted 7 lines
I was thinking of a much more generic interface, where each partition is described using abstract structs, and the creation of the actual on-disk layout is handling inside the
set_gpt_table()function. That would presumably allow the same abstract structs to be passed to e.g.set_mbr_partition_table()and a generic "ptable create" command to be created.
If I understood you correctly, you propose to devise an abstraction layer to store information about each partition - e.g.
struct partition {
char *name,
size_t size,
size_t start,
...
}then
struct disk {
struct partition p1,
struct partition p2,
...
}
And then pass this struct disk to set_gpt_table() function.
This would "clean" the partition related code and be a good starting point for further abstracting (if needed).
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH v3 6/7 gpt: Support for new "gpt" command
In reply to Lukasz MajewskiNew command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the the gd->start_addr_sp for entrophy pool. Moreover the pool address is used as crc32 seed.
---
Changes for v2:
- gpt command now accepts device medium and its number (e.g. gpt mmc 0)
- UUIDs can be passed via u-boot prompt when used with gpt command
- Format of restored GPT has been changed - now key=value pairs are used 'name="PARTS_CSA",size=8MiB;\ ' 'name="PARTS_BOOTLOADER",size=60MiB; \'
- guid_gen now accepts "pool" pointer and guid pointer
- gd->start_addr_sp is used as a primary source of entrophy
- static buffers definitions have been removed
- remove memsize_to_blocks function with call to standard ustrtoul
- doxygen comments for functions added
Changes for v3:
- Remove unnecessary braces
--- common/Makefile | 1 + common/cmd_gpt.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 405 insertions(+), 0 deletions(-) create mode 100644 common/cmd_gpt.c
common/Makefile +1 -0
@@ -185,6 +185,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o +COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o endif ifdef CONFIG_SPL_BUILD
common/cmd_gpt.c new file +404 -0
404 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH v3 7/7 gpt: Enable support for GPT partition table restoration at Samsung's Trats
In reply to Lukasz MajewskiEnable support for GPT partition table restoration at Samsung's Trats development board.
---
Changes for v2:
- New format for default GPT partitions (key=value pairs)
- replace size definitions with more readable description(1GiB instead of 1G)
Changes for v3:
- None
--- include/configs/trats.h | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-)
include/configs/trats.h +22 -1
@@ -98,6 +98,7 @@#undef CONFIG_CMD_MTDPARTS#define CONFIG_CMD_MMC #define CONFIG_CMD_DFU +#define CONFIG_CMD_GPT /* FAT */ #define CONFIG_CMD_FAT
@@ -122,6 +123,24 @@#define CONFIG_BOOTBLOCK "10"#define CONFIG_ENV_COMMON_BOOT "${console} ${meminfo}" +/* Tizen - partitions definitions */ +#define PARTS_CSA "csa-mmc" +#define PARTS_BOOTLOADER "u-boot" +#define PARTS_KERNEL "kernel" +#define PARTS_ROOT "platform" +#define PARTS_DATA "data" +#define PARTS_CSC "csc" +#define PARTS_UMS "ums" + +#define PARTS_DEFAULT "name="PARTS_CSA",size=8MiB;"\ + "name="PARTS_BOOTLOADER",size=60MiB;"\ + "name="PARTS_KERNEL",size=60MiB;"\ + "name="PARTS_ROOT",size=1GiB;"\ + "name="PARTS_DATA",size=3GiB;"\ + "name="PARTS_CSC",size=150MiB;"\ + "name="PARTS_UMS",size=-\0" +#define GPT_PARTS_NUM 7 +#define CONFIG_DFU_ALT \ "dfu_alt_info=" \ "u-boot mmc 80 400;" \
@@ -171,7 +190,8 @@"mmcbootpart=2\0" \"mmcrootpart=3\0" \"opts=always_resume=1\0" \ -CONFIG_DFU_ALT +"partitions=" PARTS_DEFAULT \ +CONFIG_DFU_ALT \/* Miscellaneous configurable options */ #define CONFIG_SYS_LONGHELP /* undef to save memory */
@@ -207,6 +227,7 @@#define CONFIG_ENV_OFFSET ((32 - 4) << 10)/* 32KiB - 4KiB */ #define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - GENERATED_GBL_DATA_SIZE)#define CONFIG_SYS_CACHELINE_SIZE 32
Signature · 1 line
1.7.2.3
v4 cover gpt: GUID Partition Table (GPT) restoration
In reply to Lukasz MajewskiThis patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the part_efi.c file was performed to remove custom macros and make GPT related structures more readable.
Moreover the part_efi.h file has been moved to ./include directory to be easily available from other subsystems.
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
Chang Hyun Park (1):
gpt: The leXX_to_int() calls replaced with ones defined at
<compiler.h>
Lukasz Majewski (5):
vsprintf:fix: Change type returned by ustrtoul
part:efi: Move part_efi.h file to ./include
gpt:doc: GPT (GUID Partition Table) documentation
gpt: Support for GPT (GUID Partition Table) restoration
gpt: Enable support for GPT partition table restoration at Samsung's
Trats
Piotr Wilczek (1):
gpt: Support for new "gpt" command
common/Makefile | 1 +
common/cmd_gpt.c | 300 ++++++++++++++++++++++++++++
disk/part_efi.c | 455 +++++++++++++++++++++++++++++++++++-------
doc/README.gpt | 209 +++++++++++++++++++
include/configs/trats.h | 29 +++-
include/part.h | 8 +
{disk => include}/part_efi.h | 89 +++++----
lib/vsprintf.c | 2 +-
8 files changed, 977 insertions(+), 116 deletions(-)
create mode 100644 common/cmd_gpt.c
create mode 100644 doc/README.gpt
rename {disk => include}/part_efi.h (66%)Signature · 1 line
1.7.5.4
PATCH v4 1/7 vsprintf:fix: Change type returned by ustrtoul
From: Lukasz Majewski <[email protected]>
The ustrtoul shall convert string defined size (e.g. 1GiB) to unsigned long type (as its name implies).
Up till now it had returned int, which might cause problems with large numbers (GiB range), when interpreted as U2 signed numbers.
---
Changes for v3:
- None
Changes for v4:
- None
--- lib/vsprintf.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
lib/vsprintf.c +1 -1
@@ -103,7 +103,7 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)return simple_strtoul (cp, endp, base); } -int ustrtoul (const char *cp,char **endp,unsigned int base) +unsigned long ustrtoul (const char *cp,char **endp,unsigned int base) {unsigned long result =simple_strtoul (cp, endp, base);switch (**endp) {
Signature · 1 line
1.7.5.4
PATCH v4 1/7 vsprintf:fix: Change type returned by ustrtoul
Quoted 7 lines · Piotr Wilczek
From: Lukasz Majewski <[email protected]>
The ustrtoul shall convert string defined size (e.g. 1GiB) to unsigned long type (as its name implies).
Up till now it had returned int, which might cause problems with large numbers (GiB range), when interpreted as U2 signed numbers.
PATCH v4 2/7 part:efi: Move part_efi.h file to ./include
In reply to Piotr WilczekFrom: Lukasz Majewski <[email protected]>
This move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the part_efi.h file has been cleaned-up to supress checkpatch's warnings.
---
Changes for v3:
- None
Changes for v4:
- None
---
{disk => include}/part_efi.h | 0
1 files changed, 0 insertions(+), 0 deletions(-)
rename {disk => include}/part_efi.h (100%)include/part_efi.h renamed from disk/part_efi.h +0 -0
Signature · 1 line
1.7.5.4
PATCH v4 2/7 part:efi: Move part_efi.h file to ./include
Quoted 8 lines · Piotr Wilczek
From: Lukasz Majewski <[email protected]>
This move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the
part_efi.hfile has been cleaned-up to supress checkpatch's warnings.{disk => include}/part_efi.h | 0
I can understand the "gpt" command perhaps needing access to the GPT-specific types, but I would hope that anything DFU-related would be using types from include/part.h; I don't imagine that DFU would need to know anything about GPT at all?
PATCH v4 2/7 part:efi: Move part_efi.h file to ./include
Quoted 8 lines · Stephen Warren
Quoted 6 lines · Piotr Wilczek
From: Lukasz Majewski <[email protected]>
This move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the
part_efi.hfile has been cleaned-up to supress checkpatch's warnings.
Quoted 6 lines
Quoted 1 line
{disk => include}/part_efi.h | 0I can understand the "gpt" command perhaps needing access to the GPT-specific types, but I would hope that anything DFU-related would be using types from
include/part.h; I don't imagine that DFU would need to know anything about GPT at all?
Indeed. DFU must not get coupled to GPT (or for that matter, partitions) in the general code. There should be "DFU write to a GPT-using backing store" code, if that's needed. Not all eMMC would be GPT-using, for example.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20121119/585a5e55/attachment.pgp>
PATCH v4 2/7 part:efi: Move part_efi.h file to ./include
Hi Tom,
Quoted 16 lines · Stephen Warren
Quoted 8 lines · Piotr Wilczek
Quoted 6 lines
From: Lukasz Majewski <[email protected]>
This move is necessary to export gpt header and GPT partition entries to be used with other commands or subsystems (like DFU in the future) Additionally the
part_efi.hfile has been cleaned-up to supress checkpatch's warnings.Quoted 6 lines
Quoted 1 line
{disk => include}/part_efi.h | 0I can understand the "gpt" command perhaps needing access to the GPT-specific types, but I would hope that anything DFU-related would be using types from
include/part.h; I don't imagine that DFU would need to know anything about GPT at all?
Quoted 5 lines
Indeed. DFU must not get coupled to GPT (or for that matter, partitions) in the general code. There should be "DFU write to a GPT-using backing store" code, if that's needed. Not all eMMC would be GPT-using, for example.
Yes, the commit description is now a bit misleading. The idea here is to have access to part_efi.h from gpt command.
DFU will use higher level of abstraction (as Stephen once suggested).
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH v4 3/7 gpt:doc: GPT (GUID Partition Table) documentation
In reply to Piotr WilczekFrom: Lukasz Majewski <[email protected]>
Documentation of the GPT format.
---
Changes for v2:
- Typos correction.
- Adding guidlines about GPT restoration.
- Adding information about GUID generator
Changes for v3:
- None
Changes for v4:
- Updated documentation
--- doc/README.gpt | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 209 insertions(+), 0 deletions(-) create mode 100644 doc/README.gpt
doc/README.gpt new file +209 -0
@@ -0,0 +1,209 @@ +# +# Copyright (C) 2012 Samsung Electronics +# +# Lukasz Majewski <[email protected]> +# +# +# 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=..,size=..,uuid=..;..." + values for every key can be passed as text or environment variable + examples: + "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" + "name=${uboot_name},size=${uboot_size},uuid=${uboot_uuid};..." + +2. From u-boot prompt type: + gpt mmc 0 + or + gpt mmc 0 partitions + or pass partitions list as text: + gpt mmc 0 "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" + + 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.
Signature · 1 line
1.7.5.4
PATCH v4 3/7 gpt:doc: GPT (GUID Partition Table) documentation
doc/README.gpt line 38
Quoted 7 lines · Piotr Wilczek
Documentation of the GPT format.
doc/README.gpt +3
-0+Introduction: +============= +This document describes the GPT partition table format when used with u-boot.
Why "when used with U-Boot"; U-Boot shouldn't influence the GPT structure at all.
doc/README.gpt line 47
Quoted 4 lines
doc/README.gpt +4
-0+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
I don't think "stored" is too likely; "displayed" is more likely.
Quoted 2 lines
+Example usage:
+==============
I would change that headline to something like "Creating GPTs in U-Boot"; all the text above describes the GPT format itself, whereas this text describes the specifics of some U-Boot commands, and so is not an example of the preceding text.
Quoted 2 lines
+To restore GUID partition table one needs to:
+1. at./include/configs/{board}.h
I don't think "at ./include/configs/{board}.h" is correct; you need to define the partitions variable in the environment. The config file is one way you could do this. I would re-write this as:
1. Define partition layout in the environment. ./include/configs/{board}.h may provide a value that describes the recommended layout if desired.
doc/README.gpt line 184
Quoted 11 lines
doc/README.gpt +11
-0+ - define "partitions=" environment variable with format: + "name=..,size=..,uuid=..;..." + values for every key can be passed as text or environment variable + examples: + "name=u-boot,size=60M;name=kernel,size=60M;name=platform,size=1G;" + "name=${uboot_name},size=${uboot_size},uuid=${uboot_uuid};..." + +2. From u-boot prompt type: + gpt mmc 0 + or + gpt mmc 0 partitions
Shouldn't that be "${partitions}" not "partitions"?
doc/README.gpt line 196
Quoted 3 lines
doc/README.gpt +3
-0+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).
What does "(16B)" mean here?
PATCH v4 4/7 gpt: The leXX_to_int() calls replaced with ones defined at <compiler.h>
In reply to Piotr WilczekFrom: Chang Hyun Park <[email protected]>
Custom definitions of le_XX_to_int functions have been replaced with standard ones, defined at <compiler.h>
Replacement of several GPT related structures members with ones indicating its endianness and proper size.
---
Changes for v2:
- Combining two commits regarding part_efi.{h|c}
Changes for v3:
- None
changes for v4:
- None
--- disk/part_efi.c | 113 +++++++++++++++++++-------------------------------- include/part_efi.h | 89 +++++++++++++++++++++-------------------- 2 files changed, 88 insertions(+), 114 deletions(-)
disk/part_efi.c +42 -71
@@ -34,7 +34,7 @@#include <command.h> #include <ide.h> #include <malloc.h> -#include "part_efi.h" +#include <part_efi.h> #include <linux/ctype.h> #if defined(CONFIG_CMD_IDE) || \
@@ -44,34 +44,6 @@defined (CONFIG_MMC ) || \defined (CONFIG_SYSTEMACE ) -/* Convert char[2] in little endian format to the host format integer - */ -static inline unsigned short le16_to_int (unsigned char *le16) -{ -return ((le16[1 ] <<8 ) + le16[0 ]); -} - -/* Convert char[4] in little endian format to the host format integer -*/ -static inline unsigned long le32_to_int (unsigned char *le32) -{ -return ((le32[3 ] <<24 ) + (le32[2 ] <<16 ) + (le32[1 ] <<8 ) + le32[0 ]); -} - -/* Convert char[8] in little endian format to the host format integer -*/ -static inline unsigned long long le64_to_int (unsigned char *le64) -{ -return (((unsigned long long )le64[7 ] <<56 ) + - ((unsigned long long )le64[6 ] <<48 ) + - ((unsigned long long )le64[5 ] <<40 ) + - ((unsigned long long )le64[4 ] <<32 ) + - ((unsigned long long )le64[3 ] <<24 ) + - ((unsigned long long )le64[2 ] <<16 ) + - ((unsigned long long )le64[1 ] <<8 ) + - (unsigned long long )le64[0 ]); -} -/** * efi_crc32() - EFI version of crc32 function * @buf: buffer to calculate crc32 of
@@ -79,7 +51,7 @@ static inline unsigned long long le64_to_int(unsigned char *le64)* * Description: Returns EFI-style CRC32 value for @buf */ -static inline unsigned long efi_crc32 (const void *buf,unsigned long len) +static inline u32 efi_crc32 (const void *buf,u32 len) {return crc32 (0 , buf, len); }
@@ -171,14 +143,14 @@ void print_part_efi(block_dev_desc_t * dev_desc)printf ("\tType UUID\n" );printf ("\tPartition UUID\n" ); -for (i =0 ; i <le32_to_int (gpt_head->num_partition_entries); i++) { +for (i =0 ; i <le32_to_cpu (gpt_head->num_partition_entries); i++) {/* Stop at the first non valid PTE */ if (!is_pte_valid (&gpt_pte[i]))break ;printf ("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n" , (i +1 ), -le64_to_int (gpt_pte[i].starting_lba), -le64_to_int (gpt_pte[i].ending_lba), + (u64 )le64_to_cpu (gpt_pte[i].starting_lba), + (u64 )le64_to_cpu (gpt_pte[i].ending_lba),print_efiname (&gpt_pte[i]));printf ("\tattrs:\t0x%016llx\n" , gpt_pte[i].attributes.raw);uuid_string (gpt_pte[i].partition_type_guid.b, uuid);
@@ -211,7 +183,7 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,return -1 ; } -if (part >le32_to_int (gpt_head->num_partition_entries) || +if (part >le32_to_cpu (gpt_head->num_partition_entries) || !is_pte_valid (&gpt_pte[part -1 ])) {printf ("%s: *** ERROR: Invalid partition number %d ***\n" , __func__, part);
@@ -219,9 +191,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, }/* The ulong casting limits the maximum disk size to 2 TB */ - info->start = (ulong )le64_to_int (gpt_pte[part -1 ].starting_lba); + info->start = (u64 )le64_to_cpu (gpt_pte[part -1 ].starting_lba);/* The ending LBA is inclusive, to calculate size, add 1 to it */ - info->size = ((ulong )le64_to_int (gpt_pte[part -1 ].ending_lba) +1 ) + info->size = ((u64 )le64_to_cpu (gpt_pte[part -1 ].ending_lba) +1 ) - info->start; info->blksz =GPT_BLOCK_SIZE ;
@@ -264,7 +236,7 @@ int test_part_efi(block_dev_desc_t * dev_desc)static int pmbr_part_valid (struct partition *part) {if (part->sys_ind ==EFI_PMBR_OSTYPE_EFI_GPT && -le32_to_int (part->start_sect) ==1UL ) { +le32_to_cpu (part->start_sect) ==1UL ) {return 1 ; }
@@ -283,9 +255,8 @@ static int is_pmbr_valid(legacy_mbr * mbr) {int i =0 ; -if (!mbr ||le16_to_int (mbr->signature) !=MSDOS_MBR_SIGNATURE ) { +if (!mbr ||le16_to_cpu (mbr->signature) !=MSDOS_MBR_SIGNATURE )return 0 ; - }for (i =0 ; i <4 ; i++) {if (pmbr_part_valid (&mbr->partition_record[i])) {
@@ -308,8 +279,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)static int is_gpt_valid (block_dev_desc_t * dev_desc,unsigned long long lba,gpt_header * pgpt_head,gpt_entry ** pgpt_pte) { -unsigned char crc32_backup[4 ] = {0 }; -unsigned long calc_crc32; +u32 crc32_backup =0 ; +u32 calc_crc32;unsigned long long lastlba;if (!dev_desc || !pgpt_head) {
@@ -324,54 +295,54 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, }/* Check the GPT header signature */ -if (le64_to_int (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) { +if (le64_to_cpu (pgpt_head->signature) !=GPT_HEADER_SIGNATURE ) {printf ("GUID Partition Table Header signature is wrong:" "0x%llX != 0x%llX\n" , - (unsigned long long )le64_to_int (pgpt_head->signature), - (unsigned long long )GPT_HEADER_SIGNATURE ); + (u64 )le64_to_cpu (pgpt_head->signature), + (u64 )GPT_HEADER_SIGNATURE );return 0 ; }/* Check the GUID Partition Table CRC */ -memcpy (crc32_backup, pgpt_head->header_crc32,sizeof (crc32_backup)); -memset (pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); +memcpy (&crc32_backup, &pgpt_head->header_crc32,sizeof (crc32_backup)); +memset (&pgpt_head->header_crc32,0 ,sizeof (pgpt_head->header_crc32)); calc_crc32 =efi_crc32 ((const unsigned char *)pgpt_head, -le32_to_int (pgpt_head->header_size)); +le32_to_cpu (pgpt_head->header_size)); -memcpy (pgpt_head->header_crc32, crc32_backup,sizeof (crc32_backup)); +memcpy (&pgpt_head->header_crc32, &crc32_backup,sizeof (crc32_backup)); -if (calc_crc32 !=le32_to_int (crc32_backup)) { +if (calc_crc32 !=le32_to_cpu (crc32_backup)) {printf ("GUID Partition Table Header CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (crc32_backup), calc_crc32); +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (crc32_backup), calc_crc32);return 0 ; }/* Check that the my_lba entry points to the LBA that contains the GPT */ -if (le64_to_int (pgpt_head->my_lba) != lba) { +if (le64_to_cpu (pgpt_head->my_lba) != lba) {printf ("GPT: my_lba incorrect: %llX != %llX\n" , - (unsigned long long )le64_to_int (pgpt_head->my_lba), - (unsigned long long )lba); + (u64 )le64_to_cpu (pgpt_head->my_lba), + (u64 )lba);return 0 ; }/* Check the first_usable_lba and last_usable_lba are within the disk. */ lastlba = (unsigned long long )dev_desc->lba; -if (le64_to_int (pgpt_head->first_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->first_usable_lba) > lastlba) {printf ("GPT: first_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), lastlba); +le64_to_cpu (pgpt_head->first_usable_lba), lastlba);return 0 ; } -if (le64_to_int (pgpt_head->last_usable_lba) > lastlba) { +if (le64_to_cpu (pgpt_head->last_usable_lba) > lastlba) {printf ("GPT: last_usable_lba incorrect: %llX > %llX\n" , -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);return 0 ; }debug ("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n" , -le64_to_int (pgpt_head->first_usable_lba), -le64_to_int (pgpt_head->last_usable_lba), lastlba); + (u64 )le64_to_cpu (pgpt_head->first_usable_lba), + (u64 )le64_to_cpu (pgpt_head->last_usable_lba), lastlba);/* Read and allocate Partition Table Entries */ *pgpt_pte =alloc_read_gpt_entries (dev_desc, pgpt_head);
@@ -382,13 +353,13 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,/* Check the GUID Partition Table Entry Array CRC */ calc_crc32 =efi_crc32 ((const unsigned char *)*pgpt_pte, -le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry)); +le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry)); -if (calc_crc32 !=le32_to_int (pgpt_head->partition_entry_array_crc32)) { +if (calc_crc32 !=le32_to_cpu (pgpt_head->partition_entry_array_crc32)) {printf ("GUID Partition Table Entry Array CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (pgpt_head->partition_entry_array_crc32), +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (pgpt_head->partition_entry_array_crc32), calc_crc32);free (*pgpt_pte);
@@ -419,12 +390,12 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,return NULL ; } - count =le32_to_int (pgpt_head->num_partition_entries) * -le32_to_int (pgpt_head->sizeof_partition_entry); + count =le32_to_cpu (pgpt_head->num_partition_entries) * +le32_to_cpu (pgpt_head->sizeof_partition_entry); -debug ("%s: count = %lu * %lu = %zu\n" , __func__, -le32_to_int (pgpt_head->num_partition_entries), -le32_to_int (pgpt_head->sizeof_partition_entry), count); +debug ("%s: count = %u * %u = %zu\n" , __func__, + (u32 )le32_to_cpu (pgpt_head->num_partition_entries), + (u32 )le32_to_cpu (pgpt_head->sizeof_partition_entry), count);/* Allocate memory for PTE, remember to FREE */ if (count !=0 ) {
@@ -440,7 +411,7 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,/* Read GPT Entries from device */ if (dev_desc->block_read (dev_desc->dev, - (unsigned long )le64_to_int (pgpt_head->partition_entry_lba), + (u64 )le64_to_cpu (pgpt_head->partition_entry_lba), (lbaint_t) (count /GPT_BLOCK_SIZE ), pte) != (count /GPT_BLOCK_SIZE )) {
include/part_efi.h +46 -43
131 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
From: Lukasz Majewski <[email protected]>
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
---
Changes for v2:
- Move GPT Header and Page Table Entries generation code to cmd_gpt.c
- Provide clean API to use set_gpt_table function for GPT restoration on a block device
Changes for v3:
- Replace printf with puts
Changes for v4:
- Add public functions for fill gpt header and entries
- Add public function for fill and save gpt tables on the basis of simple partions list information
--- disk/part_efi.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 8 ++ 2 files changed, 350 insertions(+), 0 deletions(-)
disk/part_efi.c +342 -0
@@ -37,6 +37,8 @@#include <part_efi.h> #include <linux/ctype.h> +DECLARE_GLOBAL_DATA_PTR ; + #if defined(CONFIG_CMD_IDE) || \ defined(CONFIG_CMD_SATA) || \ defined(CONFIG_CMD_SCSI) || \
@@ -71,6 +73,16 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,static int is_pte_valid (gpt_entry * pte); +static int set_protective_mbr (block_dev_desc_t *dev_desc); + +static void guid_dump (u8 *guid,int i); + +static void guid_gen (const u32 *pool,u8 *guid); + +static int convert_uuid (char *uuid,u8 *dst); + +static void set_part_name (efi_char16_t *part_name,char *name); +static char *print_efiname (gpt_entry *pte) {static char name[PARTNAME_SZ +1 ];
@@ -225,6 +237,197 @@ int test_part_efi(block_dev_desc_t * dev_desc)return 0 ; } +/** +* set_gpt_table() - Restore the GUID Partition Table +* +* @param dev_desc - block device descriptor +* @param parts - number of partitions +* @param size - pointer to array with each partition size +* @param name - pointer to array with each partition name +* +* @return - zero on success, otherwise error +*/ +int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e) +{ +const int pte_blk_num = (GPT_ENTRY_NUMBERS *sizeof (gpt_entry)) / + dev_desc->blksz; +u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_e, +le32_to_cpu (gpt_h->num_partition_entries) * +le32_to_cpu (gpt_h->sizeof_partition_entry)); + gpt_h->partition_entry_array_crc32 =cpu_to_le32 (calc_crc32); + + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_h, +le32_to_cpu (gpt_h->header_size)); + gpt_h->header_crc32 =cpu_to_le32 (calc_crc32); + +/* Write the First GPT to the block right after the Legacy MBR */ +if (dev_desc->block_write (dev_desc->dev,1 ,1 , gpt_h) !=1 ) + goto err; + +if (dev_desc->block_write (dev_desc->dev,2 , pte_blk_num, gpt_e) + != pte_blk_num) + goto err; + +/* recalculate the values for the Second GPT Header*/ + val =le64_to_cpu (gpt_h->my_lba); + gpt_h->my_lba = gpt_h->alternate_lba; + gpt_h->alternate_lba =cpu_to_le64 (val); + gpt_h->header_crc32 =0 ; + + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_h, +le32_to_cpu (gpt_h->header_size)); + gpt_h->header_crc32 =cpu_to_le32 (calc_crc32); + +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h->last_usable_lba +1 ), + pte_blk_num, gpt_e) != pte_blk_num) + goto err; + +if (dev_desc->block_write (dev_desc->dev, +le32_to_cpu (gpt_h->my_lba),1 , gpt_h) !=1 ) + goto err; + +puts ("GPT successfully written to block device!\n" ); +return 0 ; + + err: +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; +} + +/** +* gpt_fill_pte(): Fill the GPT partition table entry +* +* @param gpt_h - GPT header representation +* @param gpt_e - GPT partition table entries +* @param partitions - list of partitions +* @param parts - number of partitions +*/ +void gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts) +{ +u32 offset = (u32 )le32_to_cpu (gpt_h->first_usable_lba); +u8 guid[sizeof (efi_guid_t)]; +char *str_uuid; +ulong start; +int i; + +for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i]->start; +if (start && (offset <= start)) + gpt_e[i].starting_lba =cpu_to_le32 (start); +else + gpt_e[i].starting_lba =cpu_to_le32 (offset); + + offset =le32_to_cpu (gpt_e[i].starting_lba) + + partitions[i]->size; +if (offset >= gpt_h->last_usable_lba) { +printf ("Partitions layout excedds disk size\n" ); +return ; + } +/* partition ending lba */ +if (i != parts -1 ) + gpt_e[i].ending_lba = +cpu_to_le64 (offset -1 ); +else + gpt_e[i].ending_lba = gpt_h->last_usable_lba; + +/* partition type GUID*/ +memcpy (gpt_e[i].partition_type_guid.b, + &PARTITION_BASIC_DATA_GUID ,16 ); + + str_uuid =NULL ; +#ifdef CONFIG_PARTITION_UUIDS + str_uuid = partitions[i]->uuid; +#endif +if (convert_uuid (str_uuid, gpt_e[i].unique_partition_guid.b)) { +guid_gen ((((u32 *) gd->start_addr_sp) - i -1 ), + guid); +memcpy (gpt_e[i].unique_partition_guid.b, guid, +sizeof (efi_guid_t)); + } + +/* partition attributes */ +memset (&gpt_e[i].attributes,0 , +sizeof (gpt_entry_attributes)); + +/* partition name */ +set_part_name (gpt_e[i].partition_name, + (char *)partitions[i]->name); + +debug ("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%lx\n" , + __func__, partitions[i]->name, i, + offset, i, partitions[i]->size); + } +} + +/** +* gpt_fill_header(): Fill the GPT header +* +* @param dev_desc - block device descriptor +* @param gpt_h - GPT header representation +*/ +void gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h) +{ +u8 guid[sizeof (gpt_h->disk_guid.b)]; +char *s; + + gpt_h->signature =cpu_to_le64 (GPT_HEADER_SIGNATURE ); + gpt_h->revision =cpu_to_le32 (GPT_HEADER_REVISION_V1 ); + gpt_h->header_size =cpu_to_le32 (sizeof (gpt_header)); + gpt_h->my_lba =cpu_to_le64 (1 ); + gpt_h->alternate_lba =cpu_to_le64 (dev_desc->lba -1 ); + gpt_h->first_usable_lba =cpu_to_le64 (34 ); + gpt_h->last_usable_lba =cpu_to_le64 (dev_desc->lba -34 ); + gpt_h->partition_entry_lba =cpu_to_le64 (2 ); + gpt_h->num_partition_entries =cpu_to_le32 (GPT_ENTRY_NUMBERS ); + gpt_h->sizeof_partition_entry =cpu_to_le32 (sizeof (gpt_entry)); + gpt_h->header_crc32 =0 ; + gpt_h->partition_entry_array_crc32 =0 ; + + s =getenv ("uuid_gpt_disk" ); +if (!convert_uuid (s, gpt_h->disk_guid.b)) { +guid_gen ((u32 *)gd->start_addr_sp, guid); +memcpy (gpt_h->disk_guid.b, guid,sizeof (efi_guid_t)); + } +} + +/** +* gpt_fill(): Fill the GPT header +* +* @param dev_desc - block device descriptor +* @param partitions - list of partitions +* @param parts - number of partitions +*/ +void gpt_fill (block_dev_desc_t *dev_desc,disk_partition_t *partitions[], +const int parts_count) +{ +gpt_header *gpt_h =calloc (sizeof (gpt_header),1 ); +gpt_entry *gpt_e =calloc (sizeof (gpt_entry),GPT_ENTRY_NUMBERS ); + +/* Generate Primary GPT header (LBA1) */ +gpt_fill_header (dev_desc, gpt_h); +gpt_fill_pte (gpt_h, gpt_e, partitions, parts_count); + +puts ("save the GPT ...\n" ); +set_gpt_table (dev_desc, gpt_h, gpt_e); + +free (gpt_e); +free (gpt_h); +} +/* * Private functions */
@@ -453,4 +656,143 @@ static int is_pte_valid(gpt_entry * pte) return 1; } } + +/** +* set_protective_mbr(): Set the EFI protective MBR +* @param dev_desc - block device descriptor +* +* @return - zero on success, otherwise error +*/ +static int set_protective_mbr (block_dev_desc_t *dev_desc) +{ +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr)); +/* Append signature */ + p_mbr.signature =MSDOS_MBR_SIGNATURE ; + p_mbr.partition_record[0 ].sys_ind =EFI_PMBR_OSTYPE_EFI_GPT ; + p_mbr.partition_record[0 ].start_sect =1 ; + p_mbr.partition_record[0 ].nr_sects = (u32 ) dev_desc->lba; + +/* Write MBR sector to the MMC device */ +if (dev_desc->block_write (dev_desc->dev,0 ,1 , &p_mbr) !=1 ) { +printf ("** Can't write to device %d **\n" , + dev_desc->dev); +return -1 ; + } + +return 0 ; +} + +#ifdef DEBUG +/** +* guid_dump(): Dump guid content +* +* @param guid - pinter to guid +* @param i - number of bytes to dump +*/ +static void guid_dump (u8 *guid,int i) +{ +int k; + +debug ("GUID: " ); +for (k =0 ; k < i; k++, guid++) +debug (" %x " , *guid); +debug ("\n" ); +} +#else +static void guid_dump (u8 *guid,int i) {} +#endif + +/** +* guid_gen(): Generate UUID +* +* @param pool - pointer to pseudo random data (e.g. SP) +* @param guid - pointer to guid table +* +* @return - generated UUID table +* +* NOTE: The entrophy of this function is small +*/ +static void guid_gen (const u32 *pool,u8 *guid) +{ +int k =0 ; +u32 *ptr = (u32 *) guid; + +debug ("%s: pool: 0x%p guid: 0x%p\n" , __func__, pool, guid); +for (k =0 ; k <4 ; k++) + *(ptr + k) =crc32 ((u32 ) pool, (const void *) (pool - k),512 ); + +guid_dump (guid,sizeof (efi_guid_t)); +} + +/** +* convert_uuid(); Convert UUID stored as string to bytes +* +* @param uuid - UUID represented as string +* @param dst - GUID buffer +* +* @return return 0 on successful conversion +*/ +static int convert_uuid (char *uuid,u8 *dst) +{ +efi_guid_t guid; +u16 b, c, d; +u64 e; +u32 a; +u8 *p; +u8 i; + +const u8 uuid_str_len =36 ; + +/* The UUID is written in text: */ +/* 1 9 14 19 24 */ +/* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */ + +debug ("%s: uuid: %s\n" , __func__, uuid); + +if (strlen (uuid) != uuid_str_len) +return -1 ; + +for (i =0 ; i < uuid_str_len; i++) { +if ((i ==8 ) || (i ==13 ) || (i ==18 ) || (i ==23 )) { +if (uuid[i] !='-' ) +return -1 ; + }else { +if (!isxdigit (uuid[i])) +return -1 ; + } + } + + a = (u32 )simple_strtoul (uuid,NULL ,16 ); + b = (u16 )simple_strtoul (uuid +9 ,NULL ,16 ); + c = (u16 )simple_strtoul (uuid +14 ,NULL ,16 ); + d = (u16 )simple_strtoul (uuid +19 ,NULL ,16 ); + e = (u64 )simple_strtoull (uuid +24 ,NULL ,16 ); + + p = (u8 *) &e; + guid =EFI_GUID (a, b, c, d >>8 , d &0xFF , + *(p +5 ), *(p +4 ), *(p +3 ), + *(p +2 ), *(p +1 ) , *p); + +guid_dump (guid.b,sizeof (efi_guid_t)); +memcpy (dst, guid.b,sizeof (efi_guid_t)); + +return 0 ; +} + +static void set_part_name (efi_char16_t *part_name,char *name) +{ +int k, j; +char p[PARTNAME_SZ ]; + +memset (p,0x00 ,sizeof (p)); +for (k =0 , j =0 ; k <strlen (name); k++, j +=2 ) { + p[j] = *(name + k); + p[j +1 ] ='.' ; + } +memcpy (part_name, p,strlen (p)); +} +#endif
include/part.h +8 -0
@@ -176,10 +176,18 @@ int test_part_amiga (block_dev_desc_t *dev_desc);#endif #ifdef CONFIG_EFI_PARTITION +#include <part_efi.h> /* disk/part_efi.c */ int get_partition_info_efi (block_dev_desc_t * dev_desc,int part,disk_partition_t *info);void print_part_efi (block_dev_desc_t *dev_desc);int test_part_efi (block_dev_desc_t *dev_desc); +int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e); +void gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts); +void gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h); +void gpt_fill (block_dev_desc_t *dev_desc,disk_partition_t *partitions[], +const int parts_count);#endif #endif /* _PART_H */
Signature · 1 line
1.7.5.4
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc);
Quoted 13 lines · Piotr Wilczek
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
include/part.h +7
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e); +void gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts); +void gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h); +void gpt_fill (block_dev_desc_t *dev_desc,disk_partition_t *partitions[], +const int parts_count);
Why const?
Some documentation for these functions (particularly high-level information such as which order you'd expect to call them and why/what for) would be useful in the header rather than the .c file; the header is where people would go to find out what functions they can call, so making them also go look in the .c file would be a bit annoying.
disk/part_efi.c static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, · line 84
Quoted 11 lines
disk/part_efi.c +9
-0+static int set_protective_mbr (block_dev_desc_t *dev_desc); + +static void guid_dump (u8 *guid,int i); + +static void guid_gen (const u32 *pool,u8 *guid); + +static int convert_uuid (char *uuid,u8 *dst); + +static void set_part_name (efi_char16_t *part_name,char *name);
There probably should be a CONFIG_ option required to enable this new feature, so people who don't want it don't suffer code bloat.
Do you really need the blank lines between prototypes?
I suspect you can re-order the functions so that none of the prototypes are needed anyway.
Quoted 2 lines
+/**
+ *set_gpt_table()- Restore the GUID Partition Table
"write" would probably be better than "set".
Quoted 5 lines
+ *
+ * @paramdev_desc- block device descriptor
+ * @param parts - number of partitions
+ * @param size - pointer to array with each partition size
+ * @param name - pointer to array with each partition name
Those last 3 lines don't match the prototype.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 251
Quoted 4 lines
+ * @return - zero on success, otherwise error
+ */disk/part_efi.c +2
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e)
Presumably the code assumes that gpt_e always has 128(?) entries. Instead of taking a pointer, should the function take an array:gpt_entry gpt_e[GPT_ENTRY_NUMBERS] to enforce this?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 254
Quoted 3 lines
disk/part_efi.c +3
-0+{ +const int pte_blk_num = (GPT_ENTRY_NUMBERS *sizeof (gpt_entry)) / + dev_desc->blksz;
Related, this hard-codes the number of ptes as GPT_ENTRY_NUMBERS, whereas ...
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 266
Quoted 12 lines
disk/part_efi.c +12
-0+u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_e, +le32_to_cpu (gpt_h->num_partition_entries) * +le32_to_cpu (gpt_h->sizeof_partition_entry));
... here, gpt_h->num_partition_entries is used instead. Should both places use the same size (entry count) definition?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 279
Quoted 3 lines
disk/part_efi.c +3
-0+if (dev_desc->block_write (dev_desc->dev,2 , pte_blk_num, gpt_e) + != pte_blk_num) + goto err;
Here, we assume GPT_ENTRY_NUMBERS entries in gpt_e. If the array isn't that big, the block_write() above will read past the end of it.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 300
Quoted 1 line
disk/part_efi.c +1
-0+puts ("GPT successfully written to block device!\n" );
Isn't that something that a command should be doing, not a utility function? I'd rather have this function not print anything, except perhaps on errors, just like typical Unix command-line applications.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 318
Quoted 2 lines
disk/part_efi.c +2
-0+void gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts)
Why is partitions an array of pointers rather than an array of partitions?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 320
Quoted 2 lines
disk/part_efi.c +2
-0+{ +u32 offset = (u32 )le32_to_cpu (gpt_h->first_usable_lba);
I don't think there should be a space after the cast. The same comment probably applies elsewhere.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 332
Quoted 7 lines
disk/part_efi.c +7
-0+for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i]->start; +if (start && (offset <= start)) + gpt_e[i].starting_lba =cpu_to_le32 (start); +else + gpt_e[i].starting_lba =cpu_to_le32 (offset);
That seems a little odd. The else branch seems fine when !start, but what about when (start && (offset > start))? Shouldn't that be an error, rather than just ignoring the requested start value?
Why can't partitions be out of order? IIRC, the GPT spec allows it.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 345
Quoted 6 lines
disk/part_efi.c +6
-0+/* partition ending lba */ +if (i != parts -1 ) + gpt_e[i].ending_lba = +cpu_to_le64 (offset -1 ); +else + gpt_e[i].ending_lba = gpt_h->last_usable_lba;
Why extend the last partition to fill the disk; why not simply always use the requested size? If a "fill to max size" option is implemented, the user might not want it to apply to the last partition, but perhaps some arbitrary partition in the middle of the list.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 349
Quoted 3 lines
disk/part_efi.c +3
-0+/* partition type GUID*/ +memcpy (gpt_e[i].partition_type_guid.b, + &PARTITION_BASIC_DATA_GUID ,16 );
Shouldn't that be a user-specifiable option too? I suppose we could add that later.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 354
Quoted 4 lines
disk/part_efi.c +4
-0+ str_uuid =NULL ; +#ifdef CONFIG_PARTITION_UUIDS + str_uuid = partitions[i]->uuid; +#endif
I think it should be required to enable that feature if creating GPTs; writing a GPT without a value UUID seems wrong.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 360
Quoted 6 lines
disk/part_efi.c +6
-0+if (convert_uuid (str_uuid, gpt_e[i].unique_partition_guid.b)) { +guid_gen ((((u32 *) gd->start_addr_sp) - i -1 ), + guid); +memcpy (gpt_e[i].unique_partition_guid.b, guid, +sizeof (efi_guid_t)); + }
Shouldn't there be a difference between no specified UUID, and an error converting a specified UUID?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 364
Quoted 3 lines
disk/part_efi.c +3
-0+/* partition attributes */ +memset (&gpt_e[i].attributes,0 , +sizeof (gpt_entry_attributes));
(Perhaps in the future) We should allow specifying attributes too.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 393
Quoted 4 lines
disk/part_efi.c +3
-0+void gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h) + gpt_h->first_usable_lba = cpu_to_le64(34); + gpt_h->last_usable_lba =cpu_to_le64 (dev_desc->lba -34 );
Is lba the number of LBAs or the last LBA number? include/part.h says its the number of LBAs, in which case I think that should be dev_desc->lba - 1 - 34?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 400
Quoted 1 line
disk/part_efi.c +1
-0+ s =getenv ("uuid_gpt_disk" );
I'd rather not depend on environment variables; can't this be a command-line parameter to the gpt command?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 415
Quoted 2 lines
disk/part_efi.c +2
-0+void gpt_fill (block_dev_desc_t *dev_desc,disk_partition_t *partitions[], +const int parts_count)
Rename to gpt_write()?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 424
Quoted 1 line
disk/part_efi.c +1
-0+puts ("save the GPT ...\n" );
Again, why print anything here?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 425
Quoted 1 line
disk/part_efi.c +1
-0+set_gpt_table (dev_desc, gpt_h, gpt_e);
Oh, so is set_gpt_table() an internal-only function? If so, shouldn't it be static and not in the header file?
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 671
Quoted 6 lines
disk/part_efi.c +6
-0+static int set_protective_mbr (block_dev_desc_t *dev_desc) +{ +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr));
Why use a stack variable and memset() here, but use calloc() in gpt_fill() above? That seems inconsistent.
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 706
Quoted 13 lines
disk/part_efi.c +13
-0+#ifdef DEBUG +static void guid_dump (u8 *guid,int i) +{ +int k; + +debug ("GUID: " ); +for (k =0 ; k < i; k++, guid++) +debug (" %x " , *guid); +debug ("\n" ); +} +#else +static void guid_dump (u8 *guid,int i) {} +#endif
Wouldn't using the existing uuid_string be better?
Quoted 1 line
+static int
convert_uuid(char *uuid, u8 *dst)
It's not too clear from the function name what kind of conversion is being applied. string_uuid() would be more consistent with the existing uuid_string(), or perhaps even better string_to_uuid().
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 793
Quoted 5 lines
disk/part_efi.c +4
-0+static void set_part_name (efi_char16_t *part_name,char *name) + for (k = 0, j = 0; k < strlen(name); k++, j += 2) { + p[j] = *(name + k); + p[j +1 ] ='.' ;
Not '\0'?
disk/part_efi.c
Quoted 2 lines
disk/part_efi.c +2
-0+ } +memcpy (part_name, p,strlen (p));
Why not write directly to part_name?
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
Dear Stephen,
Quoted 22 lines
-----Original Message-----
From: Stephen Warren [mailto:swarren at wwwdotorg.org]
Sent: Monday, November 19, 2012 9:17 PM
To: Piotr Wilczek
Cc: u-boot at lists.denx.de; Minkyu Kang; Kyungmin Park; Chang Hyun Park; Lukasz Majewski; Stephen Warren; Tom Rini; Rob Herring
Subject: Re: [PATCH v4 5/7] gpt: Support for GPT (GUID Partition Table) restorationQuoted 1 line · Piotr Wilczek
The restoration of GPT table (both primary and secondary) is now
possible.
Quoted 9 lines
Simple GUID generation is supported.
include/part.h +5
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e);void +gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts);void +gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h);
Quoted 6 lines
Quoted 1 line
+void gpt_fill(block_dev_desc_t
*dev_desc,disk_partition_t*partitions[],
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 190
Quoted 1 line
include/part.h +1
-0+ const int parts_count);Why const?
The const is not necessary.
Quoted 6 lines
Some documentation for these functions (particularly high-level information such as which order you'd expect to call them and why/what for) would be useful in the header rather than the .c file; the header is where people would go to find out what functions they can call, so making them also go look in the .c file would be a bit annoying.
That documentation should be moved to header files.
Quoted 15 lines
disk/part_efi.c static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, · line 84
Quoted 11 lines
disk/part_efi.c +9
-0+static int set_protective_mbr (block_dev_desc_t *dev_desc); + +static void guid_dump (u8 *guid,int i); + +static void guid_gen (const u32 *pool,u8 *guid); + +static int convert_uuid (char *uuid,u8 *dst); + +static void set_part_name (efi_char16_t *part_name,char *name);There probably should be a
CONFIG_option required to enable this new feature, so people who don't want it don't suffer code bloat.
Quoted 5 lines
Do you really need the blank lines between prototypes?
I suspect you can re-order the functions so that none of the prototypes are needed anyway.
I try to reorder the functions and eliminate prototypes.
Quoted 5 lines
Quoted 2 lines
+/**
+ *set_gpt_table()- Restore the GUID Partition Table"write" would probably be better than "set".
Yes, "write" is better.
Quoted 8 lines
Quoted 5 lines
+ *
+ * @paramdev_desc- block device descriptor
+ * @param parts - number of partitions
+ * @param size - pointer to array with each partition size
+ * @param name - pointer to array with each partition nameThose last 3 lines don't match the prototype.
I should fix it.
Quoted 44 lines
disk/part_efi.c
Quoted 3 lines
+ * @return - zero on success, otherwise error */ int
disk/part_efi.c +2
-0+set_gpt_table (block_dev_desc_t *dev_desc, + gpt_header *gpt_h, gpt_entry *gpt_e)Presumably the code assumes that
gpt_ealways has 128(?) entries. Instead of taking a pointer, should the function take an array:gpt_entrygpt_e[GPT_ENTRY_NUMBERS] to enforce this?disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 254
Quoted 3 lines
disk/part_efi.c +3
-0+{ +const int pte_blk_num = (GPT_ENTRY_NUMBERS *sizeof (gpt_entry)) / + dev_desc->blksz;Related, this hard-codes the number of ptes as
GPT_ENTRY_NUMBERS, whereas ...disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 266
Quoted 12 lines
disk/part_efi.c +12
-0+u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 =efi_crc32 ((const unsigned char *)gpt_e, +le32_to_cpu (gpt_h->num_partition_entries) * +le32_to_cpu (gpt_h->sizeof_partition_entry));... here,
gpt_h->num_partition_entriesis used instead. Should both places use the same size (entry count) definition?disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 279
Quoted 3 lines
disk/part_efi.c +3
-0+if (dev_desc->block_write (dev_desc->dev,2 , pte_blk_num, gpt_e) + != pte_blk_num) + goto err;Here, we assume
GPT_ENTRY_NUMBERSentries ingpt_e. If the array isn't that big, theblock_write()above will read past the end of it.disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 300
Quoted 1 line
disk/part_efi.c +1
-0+puts ("GPT successfully written to block device!\n" );Isn't that something that a command should be doing, not a utility function? I'd rather have this function not print anything, except perhaps on errors, just like typical Unix command-line applications.
Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 318
Quoted 2 lines
disk/part_efi.c +2
-0+void gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts)Why is partitions an array of pointers rather than an array of partitions?
The partitions is a variable size array stack allocated and each element points to heap allocated disk_partition. I think of how to reorganize this part of the code.
Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 320
Quoted 2 lines
disk/part_efi.c +2
-0+{ +u32 offset = (u32 )le32_to_cpu (gpt_h->first_usable_lba);I don't think there should be a space after the cast. The same comment probably applies elsewhere.
Quoted 12 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 332
Quoted 7 lines
disk/part_efi.c +7
-0+for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i]->start; +if (start && (offset <= start)) + gpt_e[i].starting_lba =cpu_to_le32 (start); +else + gpt_e[i].starting_lba =cpu_to_le32 (offset);That seems a little odd. The else branch seems fine when !start, but what about when (start && (offset > start))? Shouldn't that be an error, rather than just ignoring the requested start value?
The idea is that if the user provided start address and the partitions does not overlap, the partition is located at the start address. Otherwise partitions are located next to each other.
Quoted 21 lines
Why can't partitions be out of order? IIRC, the GPT spec allows it.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 345
Quoted 6 lines
disk/part_efi.c +6
-0+/* partition ending lba */ +if (i != parts -1 ) + gpt_e[i].ending_lba = +cpu_to_le64 (offset -1 ); +else + gpt_e[i].ending_lba = gpt_h->last_usable_lba;Why extend the last partition to fill the disk; why not simply always use the requested size? If a "fill to max size" option is implemented, the user might not want it to apply to the last partition, but perhaps some arbitrary partition in the middle of the list.
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 349
Quoted 3 lines
disk/part_efi.c +3
-0+/* partition type GUID*/ +memcpy (gpt_e[i].partition_type_guid.b, + &PARTITION_BASIC_DATA_GUID ,16 );Shouldn't that be a user-specifiable option too? I suppose we could add that later.
Quoted 8 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 354
Quoted 4 lines
disk/part_efi.c +4
-0+ str_uuid =NULL ; +#ifdef CONFIG_PARTITION_UUIDS + str_uuid = partitions[i]->uuid; +#endif I think it should be required to enable that feature if creating GPTs; writing a GPT without a value UUID seems wrong.
Yes, it should be checked if CONFIG_PARTITION_UUIDS is defined at all.
Quoted 11 lines
disk/part_efi.c
Quoted 1 line
disk/part_efi.c +1
-0+ if (convert_uuid(str_uuid,gpt_e[i].unique_partition_guid.b)) {
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 360
Quoted 5 lines
disk/part_efi.c +5
-0+guid_gen ((((u32 *) gd->start_addr_sp) - i -1 ), + guid); +memcpy (gpt_e[i].unique_partition_guid.b, guid, +sizeof (efi_guid_t)); + }Shouldn't there be a difference between no specified UUID, and an error converting a specified UUID?
Yes, it's a good idea.
Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 364
Quoted 3 lines
disk/part_efi.c +3
-0+/* partition attributes */ +memset (&gpt_e[i].attributes,0 , +sizeof (gpt_entry_attributes));(Perhaps in the future) We should allow specifying attributes too.
Ok
Quoted 14 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 393
Quoted 4 lines
disk/part_efi.c +3
-0+void gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h) + gpt_h->first_usable_lba = cpu_to_le64(34); + gpt_h->last_usable_lba =cpu_to_le64 (dev_desc->lba -34 );Is lba the number of LBAs or the last LBA number?
include/part.hsays its the number of LBAs, in which case I think that should be dev_desc-disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 400
Quoted 3 lines
lba - 1 - 34?
disk/part_efi.c +1
-0+ s =getenv ("uuid_gpt_disk" );I'd rather not depend on environment variables; can't this be a command-line parameter to the gpt command?
Quoted 6 lines
Quoted 1 line
+void gpt_fill(block_dev_desc_t
*dev_desc,disk_partition_t*partitions[],
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 415
Quoted 1 line
disk/part_efi.c +1
-0+ const int parts_count)Rename to
gpt_write()?
Ok.
Quoted 9 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 424
Quoted 1 line
disk/part_efi.c +1
-0+puts ("save the GPT ...\n" );Again, why print anything here?
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 425
Quoted 1 line
disk/part_efi.c +1
-0+set_gpt_table (dev_desc, gpt_h, gpt_e);Oh, so is
set_gpt_table()an internal-only function? If so, shouldn't it be static and not in the header file?
It could be used by some other code in future.
Quoted 37 lines
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 671
Quoted 5 lines
disk/part_efi.c +5
-0+static int set_protective_mbr (block_dev_desc_t *dev_desc) { +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr));Why use a stack variable and
memset()here, but usecalloc()ingpt_fill()above? That seems inconsistent.disk/part_efi.c static int is_pte_valid(gpt_entry * pte)
Quoted 11 lines
disk/part_efi.c +11
-0+#ifdef DEBUG +static void guid_dump (u8 *guid,int i) { +int k; + +debug ("GUID: " ); +for (k =0 ; k < i; k++, guid++) +debug (" %x " , *guid); +debug ("\n" ); +} +#else +static void guid_dump (u8 *guid,int i) {}#endif Wouldn't using the existing
uuid_stringbe better?Quoted 1 line
+static int
convert_uuid(char *uuid, u8 *dst)It's not too clear from the function name what kind of conversion is being applied.
string_uuid()would be more consistent with the existinguuid_string(), or perhaps even betterstring_to_uuid().disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 793
Quoted 5 lines
disk/part_efi.c +4
-0+static void set_part_name (efi_char16_t *part_name,char *name) + for (k = 0, j = 0; k < strlen(name); k++, j += 2) { + p[j] = *(name + k); + p[j +1 ] ='.' ;Not '\0'?
Quoted 4 lines
disk/part_efi.c
Quoted 2 lines
disk/part_efi.c +2
-0+ } +memcpy (part_name, p,strlen (p));Why not write directly to
part_name?
Right, I fix it.
Best regards,
Piotr Wilczek
--
Samsung Poland R&D Center | Linux Platform Group
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
Hi Piotr,
Quoted 76 lines
Dear Stephen,
Quoted 22 lines
-----Original Message-----
From: Stephen Warren [mailto:swarren at wwwdotorg.org]
Sent: Monday, November 19, 2012 9:17 PM
To: Piotr Wilczek
Cc: u-boot at lists.denx.de; Minkyu Kang; Kyungmin Park; Chang Hyun Park; Lukasz Majewski; Stephen Warren; Tom Rini; Rob Herring
Subject: Re: [PATCH v4 5/7] gpt: Support for GPT (GUID Partition Table) restorationQuoted 1 line · Piotr Wilczek
The restoration of GPT table (both primary and secondary) is now
possible.
Quoted 9 lines
Simple GUID generation is supported.
include/part.h +5
-0+int set_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e);void +gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts);void +gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h);Quoted 6 lines
Quoted 1 line
+void gpt_fill(block_dev_desc_t
*dev_desc,disk_partition_t*partitions[],
include/part.h int test_part_amiga (block_dev_desc_t *dev_desc); · line 190
Quoted 1 line
include/part.h +1
-0+ const int parts_count);Why const?
The const is not necessary.
Quoted 7 lines
Some documentation for these functions (particularly high-level information such as which order you'd expect to call them and why/what for) would be useful in the header rather than the .c file; the header is where people would go to find out what functions they can call, so making them also go look in the .c file would be a bit annoying.
That documentation should be moved to header files.
Quoted 15 lines
disk/part_efi.c static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, · line 84
Quoted 11 lines
disk/part_efi.c +9
-0+static int set_protective_mbr (block_dev_desc_t *dev_desc); + +static void guid_dump (u8 *guid,int i); + +static void guid_gen (const u32 *pool,u8 *guid); + +static int convert_uuid (char *uuid,u8 *dst); + +static void set_part_name (efi_char16_t *part_name,char *name);There probably should be a
CONFIG_option required to enable this new feature, so people who don't want it don't suffer code bloat.Quoted 5 lines
Do you really need the blank lines between prototypes?
I suspect you can re-order the functions so that none of the prototypes are needed anyway.
I try to reorder the functions and eliminate prototypes.
Quoted 5 lines
Quoted 2 lines
+/**
+ *set_gpt_table()- Restore the GUID Partition Table"write" would probably be better than "set".
Yes, "write" is better.
Quoted 6 lines
Quoted 5 lines
+ *
+ * @paramdev_desc- block device descriptor
+ * @param parts - number of partitions
+ * @param size - pointer to array with each partition size
+ * @param name - pointer to array with each partition name
Quoted 46 lines
Quoted 2 lines
Those last 3 lines don't match the prototype.
I should fix it.
Quoted 42 lines
disk/part_efi.c
Quoted 3 lines
+ * @return - zero on success, otherwise error */ int
disk/part_efi.c +2
-0+set_gpt_table (block_dev_desc_t *dev_desc, + gpt_header *gpt_h, gpt_entry *gpt_e)Presumably the code assumes that
gpt_ealways has 128(?) entries. Instead of taking a pointer, should the function take an array:gpt_entrygpt_e[GPT_ENTRY_NUMBERS] to enforce this?disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 254
Quoted 4 lines
disk/part_efi.c +2
-0+{ + const int pte_blk_num = (GPT_ENTRY_NUMBERS *
sizeof(gpt_entry)) /disk/part_efi.c +1
-0+ dev_desc->blksz;Related, this hard-codes the number of ptes as
GPT_ENTRY_NUMBERS, whereas ...Quoted 11 lines
disk/part_efi.c +11
-0+u32 calc_crc32; +u64 val; + +debug ("max lba: %x\n" , (u32 ) dev_desc->lba); +/* Setup the Protective MBR */ +if (set_protective_mbr (dev_desc) <0 ) + goto err; + +/* Generate CRC for the Primary GPT Header */ + calc_crc32 = efi_crc32((const unsigned char *)gpt_e, +Quoted 3 lines
le32_to_cpu(gpt_h->num_partition_entries)*
+le32_to_cpu(gpt_h->sizeof_partition_entry));... here,
gpt_h->num_partition_entriesis used instead. Should both places use the same size (entry count) definition?disk/part_efi.c
Quoted 4 lines
disk/part_efi.c +1
-0+ if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_num,
gpt_e)disk/part_efi.c +2
-0+ != pte_blk_num) + goto err;Here, we assume
GPT_ENTRY_NUMBERSentries ingpt_e. If the array isn't that big, theblock_write()above will read past the end of it.
The code allocates (and thereafter reads) the GPT_ENTRY_NUMBERS (which is 128) * sizeof(struct pte). It will be changed to allocate only as much space as needed.
Quoted 37 lines
Quoted 7 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 300
Quoted 2 lines
disk/part_efi.c +1
-0+puts ("GPT successfully written to block device!\n" );Isn't that something that a command should be doing, not a utility function? I'd rather have this function not print anything, except perhaps on errors, just like typical Unix command-line applications.
Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 318
Quoted 2 lines
disk/part_efi.c +2
-0+void gpt_fill_pte (gpt_header *gpt_h,gpt_entry *gpt_e, +disk_partition_t *partitions[],int parts)Why is partitions an array of pointers rather than an array of partitions?
The partitions is a variable size array stack allocated and each element points to heap allocated
disk_partition. I think of how to reorganize this part of the code.Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 320
Quoted 2 lines
disk/part_efi.c +2
-0+{ +u32 offset = (u32 )le32_to_cpu (gpt_h->first_usable_lba);I don't think there should be a space after the cast. The same comment probably applies elsewhere.
Quoted 14 lines
Quoted 9 lines
disk/part_efi.c +5
-0+for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i]->start; +if (start && (offset <= start)) + gpt_e[i].starting_lba =
cpu_to_le32(start);disk/part_efi.c +2
-0+else + gpt_e[i].starting_lba =
cpu_to_le32(offset);That seems a little odd. The else branch seems fine when !start, but what about when (start && (offset > start))? Shouldn't that be an error, rather than just ignoring the requested start value?
Quoted 19 lines
The idea is that if the user provided start address and the partitions does not overlap, the partition is located at the start address. Otherwise partitions are located next to each other.
Quoted 15 lines
Why can't partitions be out of order? IIRC, the GPT spec allows it.
Quoted 7 lines
disk/part_efi.c +6
-0+/* partition ending lba */ +if (i != parts -1 ) + gpt_e[i].ending_lba = +cpu_to_le64 (offset -1 ); +else + gpt_e[i].ending_lba =
gpt_h->last_usable_lba;Why extend the last partition to fill the disk; why not simply always use the requested size? If a "fill to max size" option is implemented, the user might not want it to apply to the last partition, but perhaps some arbitrary partition in the middle of the list.
Yes, you are right. User shall have the option to specify the size for the last partition. I think, that it is welcome to specify a special "mark" (e.g. size=- or size=0) to express that we want partition's size up to the end of the device.
Quoted 33 lines
Quoted 8 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 349
Quoted 4 lines
disk/part_efi.c +3
-0+/* partition type GUID*/ +memcpy (gpt_e[i].partition_type_guid.b, + &PARTITION_BASIC_DATA_GUID ,16 );Shouldn't that be a user-specifiable option too? I suppose we could add that later.
Quoted 8 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 354
Quoted 4 lines
disk/part_efi.c +4
-0+ str_uuid =NULL ; +#ifdef CONFIG_PARTITION_UUIDS + str_uuid = partitions[i]->uuid; +#endif I think it should be required to enable that feature if creating GPTs; writing a GPT without a value UUID seems wrong.
Yes, it should be checked if
CONFIG_PARTITION_UUIDSis defined at all.Quoted 13 lines
disk/part_efi.c
Quoted 1 line
disk/part_efi.c +1
-0+ if (convert_uuid(str_uuid,gpt_e[i].unique_partition_guid.b)) {
disk/part_efi.c
Quoted 7 lines
disk/part_efi.c +1
-0+ guid_gen((((u32 *) gd->start_addr_sp) -i - 1),
disk/part_efi.c +2
-0+ guid); + memcpy(gpt_e[i].unique_partition_guid.b,guid,
disk/part_efi.c +2
-0+ sizeof(efi_guid_t)); + }Shouldn't there be a difference between no specified UUID, and an error converting a specified UUID?
Yes, it's a good idea.
Quoted 18 lines
Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 364
Quoted 3 lines
disk/part_efi.c +3
-0+/* partition attributes */ +memset (&gpt_e[i].attributes,0 , +sizeof (gpt_entry_attributes));(Perhaps in the future) We should allow specifying attributes too.
Ok
Quoted 10 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 393
Quoted 5 lines
+void
gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h)disk/part_efi.c +2
-0+ gpt_h->first_usable_lba =cpu_to_le64 (34 ); + gpt_h->last_usable_lba =cpu_to_le64 (dev_desc->lba -34 );Is lba the number of LBAs or the last LBA number?
include/part.hsays its the number of LBAs, in which case I think that should be dev_desc-Quoted 1 line
lba - 1 - 34?
LBA is the number of blocks. So the addressable range is 0 to LBA-1. The last_usable_lba is calculated with following equation (it is similar with parted tool):
lba - 2 - ptes_size = lba -2 -32 = lba - 34
ptes_size = number_of_entries(128) * sizeof(pte_entry) (128) / sector_size (512) = 32
Quoted 5 lines
Quoted 5 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 400
Quoted 2 lines
disk/part_efi.c +1
-0+ s =getenv ("uuid_gpt_disk" );I'd rather not depend on environment variables; can't this be a command-line parameter to the gpt command?
I think, that the uuid_gpt_disk shall be added as another key=value to the partitions.
e.g. gpt uuid_gpt_disk=6aa01a70-349d-11e2-ae74-001fd09285c0;name=boot,size=100MiB,uuid=xx;name=kernel, size=200MiB,uuid=yy;....
Quoted 12 lines
Quoted 7 lines
Quoted 2 lines
+void gpt_fill(block_dev_desc_t
*dev_desc,disk_partition_t*partitions[],
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 415
Quoted 1 line
disk/part_efi.c +1
-0+ const int parts_count)Rename to
gpt_write()?Ok.
Quoted 3 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 424
Quoted 1 line
disk/part_efi.c +1
-0+puts ("save the GPT ...\n" );Again, why print anything here?
Will be changed to debug().
Quoted 16 lines
Quoted 6 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 425
Quoted 2 lines
disk/part_efi.c +1
-0+set_gpt_table (dev_desc, gpt_h, gpt_e);Oh, so is
set_gpt_table()an internal-only function? If so, shouldn't it be static and not in the header file?It could be used by some other code in future.
Quoted 8 lines
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 671
Quoted 5 lines
disk/part_efi.c +5
-0+static int set_protective_mbr (block_dev_desc_t *dev_desc) { +legacy_mbr p_mbr; + +/* Setup the Protective MBR */ +memset ((u32 *) &p_mbr,0x00 ,sizeof (p_mbr));Why use a stack variable and
memset()here, but usecalloc()ingpt_fill()above? That seems inconsistent.
Good point. Consistency will be provided in the next version.
Quoted 14 lines
Quoted 14 lines
disk/part_efi.c static int is_pte_valid(gpt_entry * pte)
Quoted 12 lines
disk/part_efi.c +11
-0+#ifdef DEBUG +static void guid_dump (u8 *guid,int i) { +int k; + +debug ("GUID: " ); +for (k =0 ; k < i; k++, guid++) +debug (" %x " , *guid); +debug ("\n" ); +} +#else +static void guid_dump (u8 *guid,int i) {}#endif Wouldn't using the existing
uuid_stringbe better?
Since the guid_gen will be removed in a next version (the correct UUID will be provided from command line/env), the guid_dump will be removed as well.
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
+static int
convert_uuid(char *uuid, u8 *dst)It's not too clear from the function name what kind of conversion is being applied.
string_uuid()would be more consistent with the existinguuid_string(), or perhaps even betterstring_to_uuid().
Quoted 7 lines
Quoted 7 lines
disk/part_efi.c static int is_pte_valid(gpt_entry * pte) · line 793
Quoted 5 lines
disk/part_efi.c +4
-0+static void set_part_name (efi_char16_t *part_name,char *name) + for (k = 0, j = 0; k < strlen(name); k++, j += 2) { + p[j] = *(name + k); + p[j +1 ] ='.' ;Not '\0'?
Yes, this is a mistake. Will be fixed.
Quoted 13 lines
Quoted 5 lines
disk/part_efi.c
Quoted 3 lines
disk/part_efi.c +2
-0+ } +memcpy (part_name, p,strlen (p));Why not write directly to
part_name?Right, I fix it.
Best regards,
Piotr Wilczek
--
Samsung Poland R&D Center | Linux Platform Group
Signature · 5 lines
Best regards, Lukasz Majewski Samsung Poland R&D Center | Linux Platform Group
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
Quoted 20 lines · Lukasz Majewski
Hi Piotr,
Quoted 17 lines
Dear Stephen,
Quoted 15 lines
Stephen Warren wrote at Monday, November 19, 2012 9:17 PM:
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 393
Quoted 8 lines · Piotr Wilczek
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
+void
gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h)disk/part_efi.c +2
-0+ gpt_h->first_usable_lba =cpu_to_le64 (34 ); + gpt_h->last_usable_lba =cpu_to_le64 (dev_desc->lba -34 );Is lba the number of LBAs or the last LBA number?
include/part.hsays its the number of LBAs, in which case I think that should be dev_desc-Quoted 1 line
lba - 1 - 34?
Quoted 8 lines
LBA is the number of blocks. So the addressable range is 0 to LBA-1. The
last_usable_lbais calculated with following equation (it is similar with parted tool):lba - 2 -
ptes_size= lba -2 -32 = lba - 34
ptes_size=number_of_entries(128)*sizeof(pte_entry)(128) /sector_size(512) = 32
Ah right, I was forgetting that there is no protective MBR at the end of the disk, so 1 less sector is used there.
Quoted 11 lines
Quoted 4 lines
Quoted 4 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 400
Quoted 1 line
disk/part_efi.c +1
-0+ s =getenv ("uuid_gpt_disk" );I'd rather not depend on environment variables; can't this be a command-line parameter to the gpt command?
I think, that the
uuid_gpt_diskshall be added as another key=value to the partitions.e.g. gpt uuid_gpt_disk=6aa01a70-349d-11e2-ae74-001fd09285c0;name=boot,size=100MiB,uuid=xx;name=kernel, size=200MiB,uuid=yy;....
I guess that'd work. Note that means the calculation of # of partitions based on counting the # of ; different. Perhaps a separate command-line argument would be simpler?
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Piotr WilczekQuoted 6 lines · Piotr Wilczek
Dear Stephen,
Quoted 4 lines
Stephen Warren wrote at Monday, November 19, 2012 9:17 PM:
Quoted 2 lines · Piotr Wilczek
The restoration of GPT table (both primary and secondary) is now possible. Simple GUID generation is supported.
...
Quoted 12 lines
Quoted 11 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 332
Quoted 7 lines
disk/part_efi.c +7
-0+for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i]->start; +if (start && (offset <= start)) + gpt_e[i].starting_lba =cpu_to_le32 (start); +else + gpt_e[i].starting_lba =cpu_to_le32 (offset);That seems a little odd. The else branch seems fine when !start, but what about when (start && (offset > start))? Shouldn't that be an error, rather than just ignoring the requested start value?
Quoted 3 lines
The idea is that if the user provided start address and the partitions does not overlap, the partition is located at the start address. Otherwise partitions are located next to each other.
But if the user provided a start address, shouldn't it always be honored exactly, or any error generated; silently ignoring a start address when there's an overlap seems wrong. Also, the overlap checking seems a little simplistic; it should really sort the partition array and then walk through checking for overlaps, rather than maintaining a single "highest used offset", since there's no requirement for the physical order of partitions to match the order in the partition table, hence why I asked:
Quoted 7 lines
Quoted 5 lines
Why can't partitions be out of order? IIRC, the GPT spec allows it.
Oh, so is
set_gpt_table()an internal-only function? If so, shouldn't it be static and not in the header file?It could be used by some other code in future.
Perhaps. It can always be made non-static at that time.
PATCH v4 5/7 gpt: Support for GPT (GUID Partition Table) restoration
Quoted 36 lines
-----Original Message-----
From: Stephen Warren [mailto:swarren at wwwdotorg.org]
Sent: Saturday, November 24, 2012 7:06 PM
To: Piotr Wilczek
Cc: u-boot at lists.denx.de; 'Minkyu Kang'; 'Kyungmin Park'; 'Chang Hyun Park'; Lukasz Majewski; 'Stephen Warren'; 'Tom Rini'; 'Rob Herring'
Subject: Re: [PATCH v4 5/7] gpt: Support for GPT (GUID Partition Table) restorationQuoted 5 lines · Piotr Wilczek
Dear Stephen,
Quoted 3 lines
Stephen Warren wrote at Monday, November 19, 2012 9:17 PM:
Quoted 1 line · Piotr Wilczek
The restoration of GPT table (both primary and secondary) is now
possible.
Quoted 1 line
Quoted 1 line
Quoted 1 line
Simple GUID generation is supported.
...
Quoted 12 lines
Quoted 11 lines
disk/part_efi.c int test_part_efi(block_dev_desc_t * dev_desc) · line 332
Quoted 7 lines
disk/part_efi.c +7
-0+for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i]->start; +if (start && (offset <= start)) + gpt_e[i].starting_lba =cpu_to_le32 (start); +else + gpt_e[i].starting_lba =cpu_to_le32 (offset);That seems a little odd. The else branch seems fine when !start, but what about when (start && (offset > start))? Shouldn't that be an error, rather than just ignoring the requested start value?
Quoted 1 line
The idea is that if the user provided start address and the
partitions
Quoted 2 lines
does not overlap, the partition is located at the start address. Otherwise partitions are located next to each other.
Quoted 9 lines
But if the user provided a start address, shouldn't it always be honored exactly, or any error generated; silently ignoring a start address when there's an overlap seems wrong. Also, the overlap checking seems a little simplistic; it should really sort the partition array and then walk through checking for overlaps, rather than maintaining a single "highest used offset", since there's no requirement for the physical order of partitions to match the order in the partition table, hence why I asked:
You are right. Ignoring start address when there's overlap is a bad idea and I change the code.
The overlap check method is simple: the offset points to the first address where the next partition can start. At first it is equal to the first usable lba, then is increased by size of the previous partition (now I see that there's a bug in the code I posted, it should be: offset += partitions[i]->size);
I think that this simple overlap check method should be enough at the moment.
Quoted 10 lines
Quoted 4 lines
Quoted 4 lines
Why can't partitions be out of order? IIRC, the GPT spec allows it.
Oh, so is
set_gpt_table()an internal-only function? If so,shouldn't
Quoted 3 lines
Quoted 1 line
it be static and not in the header file?
It could be used by some other code in future.
Perhaps. It can always be made non-static at that time.
Making it non-static I say that it was designed to be used by other code.
PATCH v4 6/7 gpt: Support for new "gpt" command
In reply to Piotr WilczekNew command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the the gd->start_addr_sp for entrophy pool. Moreover the pool address is used as crc32 seed.
---
Changes for v2:
- gpt command now accepts device medium and its number (e.g. gpt mmc 0)
- UUIDs can be passed via u-boot prompt when used with gpt command
- Format of restored GPT has been changed - now key=value pairs are used 'name="PARTS_CSA",size=8MiB;\ ' 'name="PARTS_BOOTLOADER",size=60MiB; \'
- guid_gen now accepts "pool" pointer and guid pointer
- gd->start_addr_sp is used as a primary source of entrophy
- static buffers definitions have been removed
- remove memsize_to_blocks function with call to standard ustrtoul
- doxygen comments for functions added
Changes for v3:
- Remove unnecessary braces
Changes for v4:
- partions list can be passed as environment variable or directly as text
- each value in partions list can be passed as environment variable
--- common/Makefile | 1 + common/cmd_gpt.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 0 deletions(-) create mode 100644 common/cmd_gpt.c
common/Makefile +1 -0
@@ -192,6 +192,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o +COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o endif ifdef CONFIG_SPL_BUILD
common/cmd_gpt.c new file +300 -0
300 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH v4 6/7 gpt: Support for new "gpt" command
Quoted 7 lines · Piotr Wilczek
New command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with
CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the thegd->start_addr_spfor entrophy pool. Moreover the pool address is used as crc32 seed.
common/cmd_gpt.c line 294
Quoted 7 lines
common/cmd_gpt.c +6
-0+U_BOOT_CMD (gpt,CONFIG_SYS_MAXARGS ,1 , do_gpt, +"GUID Partition Table" , +"<interface> <dev> <partions list>\n" +" partions list is in format: name=..,size=..,uuid=..;...\n" +" and can be passed as env or string ex.:\n" + " gpt mmc 0 partitions\n"
I don't think that form makes sense. The user should just pass "${partitions}" instead. The command can't know for certain whether the user actually intended to pass the text "partitions" and made a mistake, or whether they passed an environment variable. If you really want to be able to pass an environment variable name, an explicit command-line option such as:
gpt mmc 0 name=... # definition on cmd-line
gpt mmc 0 --from-environment partitions # definition in environment
seems best.
common/cmd_gpt.c line 299
Quoted 5 lines
common/cmd_gpt.c +5
-0+" gpt mmc 0 \"name=..,size=..;name=..,size=..;...\"\n" +" gpt mmc 0 \"name=${part1_name},size=..;name=..,size=..;...\"\n" +" - GUID partition table restoration\n" +" Restore GPT information on a device connected\n" +" to interface\n"
Is writing a GPT to a device the only thing the gpt command will ever do. It seems best to require the user to write "gpt write mmc 0 ..." from the very start, so that if e.g. "gpt fix-crcs" or "gpt interactive-edit" or "gpt delete-partition 5" are implemented in the future, existing scripts won't have to change to add the "write" parameter.
Quoted 2 lines
+/**
+ *extract_env(): Convert string from '&{env_name}' to 'env_name'
s/&/$/
It's doing more than that; it locates that syntax within an arbitrary string and ignores anything before "${" or after "}". Is that intentional?
common/cmd_gpt.c line 49
Quoted 8 lines
common/cmd_gpt.c +7
-0+static int extract_env (char *p) + p1 =strstr (p,"${" ); + p2 =strstr (p,"}" ); + +if (p1 && p2) { + *p2 ='\0' ; +memmove (p, p+2 , p2-p1-1 );
s/-1/-2/ I think, since the length of "${" is 2 not 1.
Spaces around operators? s/p+2/p + 2/ for example.
Quoted 4 lines
+/**
+ *extract_val(): Extract value from a key=value pair
+ *
+ * @param p - pointer to string
Pointer to pointer to string, given its type?
Quoted 2 lines
+ * @param tab - table to store extracted value
+ * @param i - actual tab element to work on
Table? Why not just pass in char **tab and get rid of "i".
common/cmd_gpt.c line 70
Quoted 4 lines
common/cmd_gpt.c +4
-0+static int extract_val (char **p,char *tab[],int i,char *key) +{ +char *t, *e, *tok = *p; +char *k;
Those variable names are not exactly descriptive.
common/cmd_gpt.c line 79
Quoted 8 lines
common/cmd_gpt.c +8
-0+ t =strsep (&tok,"," ); + k = t; +strsep (&t,"=" ); + +if (key &&strcmp (k, key)) +return -2 ; + +if (extract_env (t) ==0 ) {
Hmm. That only allows key=${value}. What about key=text${envothertext or key=${env1}foo${env2}? Isn't there some generic code that can already expand environment variables within strings so we don't have to re-invent it here?
common/cmd_gpt.c line 91
Quoted 6 lines
common/cmd_gpt.c +6
-0+ tab[i] =calloc (strlen (t) +1 ,1 ); +if (tab[i] ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +return -1 ; + } +strcpy (tab[i], t);
Isn't strdup() available?
common/cmd_gpt.c line 109
Quoted 4 lines
common/cmd_gpt.c +4
-0+static int set_gpt_info (block_dev_desc_t *dev_desc,char *str_part, +disk_partition_t *partitions[],const int parts_count) +{ +char *ps[parts_count];
Can we call this sizes? Can't we call strtoul() and store int sizes[] rather than storing the strings first and then converting to integers in a separate piece of disconnected code?
common/cmd_gpt.c line 125
Quoted 1 line
common/cmd_gpt.c +1
-0+printf ("PARTITIONS: %s\n" , s);
Why print that?
common/cmd_gpt.c line 131
Quoted 6 lines
common/cmd_gpt.c +6
-0+ ss =calloc (strlen (s) +1 ,1 ); +if (ss ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +return -1 ; + } +memcpy (ss, s,strlen (s) +1 );
Use strdup().
That duplicates the strdup() in do_gpt() some of the time.
common/cmd_gpt.c line 133
Quoted 1 line
common/cmd_gpt.c +1
-0+for (i =0 , p = ss; i < parts_count; i++) {
Why not calculate parts_count here, rather than splitting the parsing logic between this function and gpt_mmc_default()?
Quoted 4 lines
common/cmd_gpt.c +4
-0+ tok =strsep (&p,";" ); +if (tok ==NULL ) +break ; +
common/cmd_gpt.c line 147
Quoted 10 lines
common/cmd_gpt.c +10
-0+if (extract_val (&tok, name, i,"name" )) { + ret =-1 ; + goto err; + } + +if (extract_val (&tok, ps, i,"size" )) { + ret =-1 ; +free (name[i]); + goto err; + }
I think that requires the parameters to be passed in order name=foo,size=5,uuid=xxx. That seems inflexible. The syntax may as well just be value,value,value rather than key=value,key=value,key=value in that case (although the keys are useful in order to understand the data, so I'd prefer parsing flexibility rather than removing key=).
common/cmd_gpt.c line 151
Quoted 3 lines
common/cmd_gpt.c +3
-0+if (extract_val (&tok, uuid, i,"uuid" )) { +/* uuid string length equals 37 */ + uuid[i] =calloc (37 ,1 );
Shouldn't storage for the UUID always be allocated? After all, one must always be written even if the user didn't explicitly specify one, so U-Boot makes it up.
common/cmd_gpt.c line 167
Quoted 3 lines
common/cmd_gpt.c +3
-0+ p = ps[i]; + size[i] =ustrtoul (p, &p,0 ); + size[i] /= dev_desc->blksz;
What if the size isn't rounded correctly?
common/cmd_gpt.c line 172
Quoted 3 lines
common/cmd_gpt.c +3
-0+for (i =0 ; i < parts_count; i++) { + partitions[i]->size = size[i]; + partitions[i]->blksz = dev_desc->blksz;
Why not just write to partitions[] directly in the first place instead of using temporary variables and then copying them?
common/cmd_gpt.c line 204
Quoted 8 lines
common/cmd_gpt.c +7
-0+static int gpt_mmc_default (int dev,char *str_part) + struct mmc *mmc = find_mmc_device(dev); + +if (mmc ==NULL ) { +printf ("%s: mmc dev %d NOT available\n" , __func__, dev); +return CMD_RET_FAILURE ; + }
Why is this tied to MMC; shouldn't it work for e.g. USB storage as well? Use get_device_and_partition() instead.
common/cmd_gpt.c line 206
Quoted 1 line
common/cmd_gpt.c +1
-0+puts ("Using default GPT UUID\n" );
Even when the user explicitly supplied a partition layout on the command-line? Why print anything at all?
common/cmd_gpt.c line 228
Quoted 2 lines
common/cmd_gpt.c +2
-0+/* allocate memory for partitions */ +disk_partition_t *partitions[part_count];
Don't variable declarations have to be at the start of a block in U-Boot?
Quoted 6 lines
common/cmd_gpt.c +6
-0+static int do_gpt (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]) +{ +int ret =CMD_RET_SUCCESS ; +char *str_part =NULL ; +int dev =0 ; +
common/cmd_gpt.c line 275
Quoted 10 lines
common/cmd_gpt.c +10
-0+if (argc <3 ) +return CMD_RET_USAGE ; + +if (argc ==4 ) { + str_part =strdup (argv[3 ]); +if (!str_part) { +printf ("%s: malloc failed!\n" , __func__); +return CMD_RET_FAILURE ; + } + }
The help text doesn't indicate that any of the command parameters are optional...
Why does this need to strdup() anything anyway?
PATCH v4 6/7 gpt: Support for new "gpt" command
Dear Stephen,
Quoted 34 lines
-----Original Message-----
From: Stephen Warren [mailto:swarren at wwwdotorg.org]
Sent: Monday, November 19, 2012 10:35 PM
To: Piotr Wilczek
Cc: u-boot at lists.denx.de; Minkyu Kang; Kyungmin Park; Chang Hyun Park; Lukasz Majewski; Stephen Warren; Tom Rini; Rob Herring
Subject: Re: [PATCH v4 6/7] gpt: Support for new "gpt" commandQuoted 1 line · Piotr Wilczek
New command - "gpt" is supported. It restores the GPT partition
table.
Quoted 1 line
It looks into the "partitions" environment variable for partitions
definition.
Quoted 3 lines
It can be enabled at target configuration file with
CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the thegd->start_addr_spfor entrophy pool. Moreover the pool address isused as crc32 seed.
common/cmd_gpt.c line 294
Quoted 8 lines
common/cmd_gpt.c +6
-0+U_BOOT_CMD (gpt,CONFIG_SYS_MAXARGS ,1 , do_gpt, +"GUID Partition Table" , +"<interface> <dev> <partions list>\n" +" partions list is in format: name=..,size=..,uuid=..;...\n" +" and can be passed as env or string ex.:\n" + " gpt mmc 0 partitions\n"I don't think that form makes sense. The user should just pass "${partitions}" instead. The command can't know for certain whether the user actually intended to pass the text "partitions" and made a mistake, or whether they passed an environment variable. If you really want to be able to pass an environment variable name, an explicit command-line option such as:
Quoted 5 lines
gpt mmc 0 name=... # definition on cmd-line
gpt mmc 0 --from-environment partitions # definition in environmentseems best.
The intention was that the command automatically figures out whether user passed environmental variable or directly partitions as text. Then the command splits this string, checks if it is a valid partitions list and if so the table is written to mmc. That is how the code is supposed to work.
The question here is, if it should work like that. If it is desired that user explicitly states that the partitions list is passed from environmental, then I should change the code.
Quoted 14 lines
common/cmd_gpt.c
Quoted 2 lines
common/cmd_gpt.c +2
-0+" gpt mmc 0 \"name=..,size=..;name=..,size=..;...\"\n" + " gpt mmc 0\"name=${part1_name},size=..;name=..,size=..;...\"\n"
common/cmd_gpt.c line 299
Quoted 3 lines
common/cmd_gpt.c +3
-0+" - GUID partition table restoration\n" +" Restore GPT information on a device connected\n" +" to interface\n" Is writing a GPT to a device the only thing the gpt command will ever do. It seems best to require the user to write "gpt write mmc 0 ..." from the very start, so that if e.g. "gpt fix-crcs" or "gpt interactive-edit" or "gpt delete-partition 5" are implemented in the future, existing scripts won't have to change to add the "write" parameter.
I agree that the parameter "write" should be implemented.
Quoted 9 lines
Quoted 2 lines
+/**
+ *extract_env(): Convert string from '&{env_name}' to 'env_name's/&/$/
It's doing more than that; it locates that syntax within an arbitrary string and ignores anything before "${" or after "}". Is that intentional?
Yes, it was. The u-boot's shell expands to one only, so it allow to pass any partition parameter as env when the partitions list itself is passed as env.
Quoted 11 lines
common/cmd_gpt.c line 49
Quoted 8 lines
common/cmd_gpt.c +7
-0+static int extract_env (char *p) + p1 =strstr (p,"${" ); + p2 =strstr (p,"}" ); + +if (p1 && p2) { + *p2 ='\0' ; +memmove (p, p+2 , p2-p1-1 );s/-1/-2/ I think, since the length of "${" is 2 not 1.
p2-p1-1 gives length of the env name + trailing zero.
p2-p1-2 would give only the env's length and the trailing zero wouldn't be moved.
Quoted 2 lines
Spaces around operators? s/p+2/p + 2/ for example.
Yes
Quoted 7 lines
Quoted 4 lines
+/**
+ *extract_val(): Extract value from a key=value pair
+ *
+ * @param p - pointer to stringPointer to pointer to string, given its type?
Right
Quoted 11 lines
Quoted 2 lines
+ * @param tab - table to store extracted value
+ * @param i - actual tab element to work onTable? Why not just pass in char **tab and get rid of "i".
common/cmd_gpt.c line 70
Quoted 3 lines
common/cmd_gpt.c +3
-0+static int extract_val (char **p,char *tab[],int i,char *key) { +char *t, *e, *tok = *p; +char *k;Those variable names are not exactly descriptive.
I change the names.
Quoted 5 lines
Quoted 5 lines
common/cmd_gpt.c +5
-0+ t =strsep (&tok,"," ); + k = t; +strsep (&t,"=" ); + +if (key &&strcmp (k, key))
Quoted 9 lines
common/cmd_gpt.c line 79
Quoted 3 lines
common/cmd_gpt.c +3
-0+return -2 ; + +if (extract_env (t) ==0 ) {Hmm. That only allows key=${value}. What about key=text${envothertext or key=${env1}foo${env2}? Isn't there some generic code that can already expand environment variables within strings so we don't have to re-invent it here?
I check it.
Quoted 9 lines
common/cmd_gpt.c line 91
Quoted 6 lines
common/cmd_gpt.c +6
-0+ tab[i] =calloc (strlen (t) +1 ,1 ); +if (tab[i] ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +return -1 ; + } +strcpy (tab[i], t);Isn't
strdup()available?
Yes, it is.
Quoted 8 lines
common/cmd_gpt.c line 109
Quoted 3 lines
common/cmd_gpt.c +3
-0+static int set_gpt_info (block_dev_desc_t *dev_desc,char *str_part, +disk_partition_t *partitions[],const int parts_count) { +char *ps[parts_count];Can we call this sizes? Can't we call
strtoul()and store int sizes[] rather than storing the strings first and then converting to integers in a separate piece of disconnected code?
If the size parameter is passed as env (and the partitions list is passed as env) it has to be expanded manually and string allocation then needed. If we decide to remove this feature then you are right.
Quoted 4 lines
common/cmd_gpt.c line 125
Quoted 1 line
common/cmd_gpt.c +1
-0+printf ("PARTITIONS: %s\n" , s);Why print that?
Right.
Quoted 9 lines
common/cmd_gpt.c line 131
Quoted 6 lines
common/cmd_gpt.c +6
-0+ ss =calloc (strlen (s) +1 ,1 ); +if (ss ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +return -1 ; + } +memcpy (ss, s,strlen (s) +1 );Use
strdup().
Ok.
Quoted 7 lines
That duplicates the
strdup()indo_gpt()some of the time.common/cmd_gpt.c line 133
Quoted 1 line
common/cmd_gpt.c +1
-0+for (i =0 , p = ss; i < parts_count; i++) {Why not calculate
parts_counthere, rather than splitting the parsing logic between this function andgpt_mmc_default()?
The 'parts_count' is needed for dynamic array size for 'partions' and it is to passed to the 'gpt_fill' function. However I think of how to organize it all in a better way.
Quoted 12 lines
Quoted 12 lines
common/cmd_gpt.c +12
-0+ tok =strsep (&p,";" ); +if (tok ==NULL ) +break ; + +if (extract_val (&tok, name, i,"name" )) { + ret =-1 ; + goto err; + } + +if (extract_val (&tok, ps, i,"size" )) { + ret =-1 ; +free (name[i]);
Quoted 9 lines
common/cmd_gpt.c
Quoted 2 lines
common/cmd_gpt.c +2
-0+ goto err; + }I think that requires the parameters to be passed in order name=foo,size=5,uuid=xxx. That seems inflexible. The syntax may as well just be value,value,value rather than key=value,key=value,key=value in that case (although the keys are useful in order to understand the data, so I'd prefer parsing flexibility rather than removing key=).
I would say that the "key=value" is flexible. The 'extract_env' function tells you if the requested key was provided or not. Also, the order of keys is not important.
Quoted 8 lines
common/cmd_gpt.c line 151
Quoted 3 lines
common/cmd_gpt.c +3
-0+if (extract_val (&tok, uuid, i,"uuid" )) { +/* uuid string length equals 37 */ + uuid[i] =calloc (37 ,1 );Shouldn't storage for the UUID always be allocated? After all, one must always be written even if the user didn't explicitly specify one, so U- Boot makes it up.
The 'set_gpt_info' was designed in a way that allocations for ps, name and uuid are done when the value is assigned to them (the 'extract_env' function). It just consistent with that.
Quoted 6 lines
common/cmd_gpt.c line 167
Quoted 3 lines
common/cmd_gpt.c +3
-0+ p = ps[i]; + size[i] =ustrtoul (p, &p,0 ); + size[i] /= dev_desc->blksz;What if the size isn't rounded correctly?
Some checking should be added.
Quoted 7 lines
common/cmd_gpt.c line 172
Quoted 3 lines
common/cmd_gpt.c +3
-0+for (i =0 ; i < parts_count; i++) { + partitions[i]->size = size[i]; + partitions[i]->blksz = dev_desc->blksz;Why not just write to partitions[] directly in the first place instead of using temporary variables and then copying them?
The only advantage is that the partitions[] is modified only when the key extraction was successful.
Quoted 18 lines
common/cmd_gpt.c line 204
Quoted 8 lines
common/cmd_gpt.c +7
-0+static int gpt_mmc_default (int dev,char *str_part) + struct mmc *mmc = find_mmc_device(dev); + +if (mmc ==NULL ) { +printf ("%s: mmc dev %d NOT available\n" , __func__, dev); +return CMD_RET_FAILURE ; + }Why is this tied to MMC; shouldn't it work for e.g. USB storage as well?
Useget_device_and_partition()instead.common/cmd_gpt.c line 206
Quoted 1 line
common/cmd_gpt.c +1
-0+puts ("Using default GPT UUID\n" );Even when the user explicitly supplied a partition layout on the command-line? Why print anything at all?
Quoted 6 lines
common/cmd_gpt.c line 228
Quoted 2 lines
common/cmd_gpt.c +2
-0+/* allocate memory for partitions */ +disk_partition_t *partitions[part_count];Don't variable declarations have to be at the start of a block in U- Boot?
Yes, you are right.
Quoted 20 lines
Quoted 6 lines
common/cmd_gpt.c +6
-0+static int do_gpt (cmd_tbl_t *cmdtp,int flag,int argc,char *const +argv[]) { +int ret =CMD_RET_SUCCESS ; +char *str_part =NULL ; +int dev =0 ; +common/cmd_gpt.c line 275
Quoted 10 lines
common/cmd_gpt.c +10
-0+if (argc <3 ) +return CMD_RET_USAGE ; + +if (argc ==4 ) { + str_part =strdup (argv[3 ]); +if (!str_part) { +printf ("%s: malloc failed!\n" , __func__); +return CMD_RET_FAILURE ; + } + }The help text doesn't indicate that any of the command parameters are optional...
Quoted 1 line
Why does this need to
strdup()anything anyway?
Best regards,
Piotr Wilczek
--
Samsung Poland R&D Center | Linux Platform Group
PATCH v4 6/7 gpt: Support for new "gpt" command
Quoted 31 lines · Piotr Wilczek
Dear Stephen,
Quoted 24 lines
Stephen Warren wrote at Monday, November 19, 2012 10:35 PM:
Quoted 7 lines · Piotr Wilczek
New command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with
CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the thegd->start_addr_spfor entrophy pool. Moreover the pool address is used as crc32 seed.common/cmd_gpt.c line 294
Quoted 7 lines
common/cmd_gpt.c +6
-0+U_BOOT_CMD (gpt,CONFIG_SYS_MAXARGS ,1 , do_gpt, +"GUID Partition Table" , +"<interface> <dev> <partions list>\n" +" partions list is in format: name=..,size=..,uuid=..;...\n" +" and can be passed as env or string ex.:\n" + " gpt mmc 0 partitions\n"I don't think that form makes sense. The user should just pass "${partitions}" instead. The command can't know for certain whether the user actually intended to pass the text "partitions" and made a mistake, or whether they passed an environment variable. If you really want to be able to pass an environment variable name, an explicit command-line option such as:
Quoted 4 lines
gpt mmc 0 name=... # definition on cmd-line
gpt mmc 0 --from-environment partitions # definition in environmentseems best.
Quoted 8 lines
The intention was that the command automatically figures out whether user passed environmental variable or directly partitions as text. Then the command splits this string, checks if it is a valid partitions list and if so the table is written to mmc. That is how the code is supposed to work.
The question here is, if it should work like that. If it is desired that user explicitly states that the partitions list is passed from environmental, then I should change the code.
I personally prefer things to be explicit; that way, there can't be any corner-case that isn't covered by the automatic mode.
Quoted 11 lines
Quoted 8 lines
Quoted 2 lines
+/**
+ *extract_env(): Convert string from '&{env_name}' to 'env_name's/&/$/
It's doing more than that; it locates that syntax within an arbitrary string and ignores anything before "${" or after "}". Is that intentional?
Yes, it was. The u-boot's shell expands to one only, so it allow to pass any partition parameter as env when the partitions list itself is passed as env.
OK. The issue here is that the comment doesn't exactly describe what the code is doing.
Also, what if the user wrote "foo${var}bar"; I can't recall if the code handles that correct; is the result of that just "${var}", or do "foo" and "bar" actually make it into the result string?
Quoted 11 lines
Quoted 11 lines
common/cmd_gpt.c line 49
Quoted 8 lines
common/cmd_gpt.c +7
-0+static int extract_env (char *p) + p1 =strstr (p,"${" ); + p2 =strstr (p,"}" ); + +if (p1 && p2) { + *p2 ='\0' ; +memmove (p, p+2 , p2-p1-1 );s/-1/-2/ I think, since the length of "${" is 2 not 1.
Quoted 3 lines
p2-p1-1 gives length of the env name + trailing zero.
p2-p1-2 would give only the env's length and the trailing zero wouldn't be moved.
Ah right. I tend to write things like that as:
p2-p1-2+1 /* strlen("${")==2, length '\0'==1
to make it obvious what's going on
Quoted 21 lines
Quoted 12 lines
Quoted 12 lines
common/cmd_gpt.c +12
-0+ tok =strsep (&p,";" ); +if (tok ==NULL ) +break ; + +if (extract_val (&tok, name, i,"name" )) { + ret =-1 ; + goto err; + } + +if (extract_val (&tok, ps, i,"size" )) { + ret =-1 ; +free (name[i]);Quoted 9 lines
common/cmd_gpt.c
Quoted 2 lines
common/cmd_gpt.c +2
-0+ goto err; + }I think that requires the parameters to be passed in order name=foo,size=5,uuid=xxx. That seems inflexible. The syntax may as well just be value,value,value rather than key=value,key=value,key=value in that case (although the keys are useful in order to understand the data, so I'd prefer parsing flexibility rather than removing key=).
Quoted 3 lines
I would say that the "key=value" is flexible. The '
extract_env' function tells you if the requested key was provided or not. Also, the order of keys is not important.
The order of the keys shouldn't be important, but doesn't the code above expect to find key "name" first, then key "size", etc., in tha specific order, as it walks through the string?
PATCH v4 6/7 gpt: Support for new "gpt" command
Quoted 48 lines
-----Original Message-----
From: Stephen Warren [mailto:swarren at wwwdotorg.org]
Sent: Saturday, November 24, 2012 7:01 PM
To: Piotr Wilczek
Cc: u-boot at lists.denx.de; 'Minkyu Kang'; 'Kyungmin Park'; 'Chang Hyun Park'; Lukasz Majewski; 'Stephen Warren'; 'Tom Rini'; 'Rob Herring'
Subject: Re: [PATCH v4 6/7] gpt: Support for new "gpt" commandQuoted 5 lines · Piotr Wilczek
Dear Stephen,
Quoted 3 lines
Stephen Warren wrote at Monday, November 19, 2012 10:35 PM:
Quoted 1 line · Piotr Wilczek
New command - "gpt" is supported. It restores the GPT partition
table.
Quoted 1 line
Quoted 1 line
Quoted 1 line
It looks into the "partitions" environment variable for partitions
definition.
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
It can be enabled at target configuration file with
CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the thegd->start_addr_spfor entrophy pool. Moreover the pool address isused as crc32 seed.
Quoted 20 lines
Quoted 20 lines
common/cmd_gpt.c line 294
Quoted 9 lines
common/cmd_gpt.c +6
-0+U_BOOT_CMD (gpt,CONFIG_SYS_MAXARGS ,1 , do_gpt, +"GUID Partition Table" , +"<interface> <dev> <partions list>\n" +" partions list is in format: name=..,size=..,uuid=..;...\n" +" and can be passed as env or string ex.:\n" + " gpt mmc 0 partitions\n"I don't think that form makes sense. The user should just pass "${partitions}" instead. The command can't know for certain whether the user actually intended to pass the text "partitions" and made a mistake, or whether they passed an environment variable. If you really want to be able to pass an environment variable name, an explicit command-line option such as:
gpt mmc 0 name=... # definition on cmd-line
gpt mmc 0 --from-environment partitions # definition in environmentQuoted 6 lines
Quoted 1 line
seems best.
The intention was that the command automatically figures out whether user passed environmental variable or directly partitions as text. Then the command splits this string, checks if it is a valid partitions list and if so the table is written to mmc. That is how
Quoted 9 lines
the code is supposed to work.
Quoted 4 lines
The question here is, if it should work like that. If it is desired that user explicitly states that the partitions list is passed from environmental, then I should change the code.
I personally prefer things to be explicit; that way, there can't be any corner-case that isn't covered by the automatic mode.
Ok. The partitions list will be passed in two methods:
gpt create mmc 0 ${partitions_env_name} - from environmental or
gpt create mmc 0 "name=..,size=..,uuid=..;..." - form text
In both cases any partition parameter can also be passes as env:
gpt create mmc 0 "name=..,size=${part1_size},uuid=..;..."
Quoted 12 lines
Quoted 6 lines
Quoted 6 lines
Quoted 2 lines
+/**
+ *extract_env(): Convert string from '&{env_name}' to 'env_name's/&/$/
It's doing more than that; it locates that syntax within an
arbitrary
Quoted 5 lines
Quoted 2 lines
string and ignores anything before "${" or after "}". Is that intentional?
Yes, it was. The u-boot's shell expands to one only, so it allow to pass any partition parameter as env when the partitions list itself
Quoted 8 lines
is passed as env.
OK. The issue here is that the comment doesn't exactly describe what the code is doing.
Also, what if the user wrote "foo${var}bar"; I can't recall if the code handles that correct; is the result of that just "${var}", or do "foo" and "bar" actually make it into the result string?
The 'bar' will be dropped, but to drop 'foo' a small modification is needed.
Quoted 44 lines
Quoted 12 lines
Quoted 12 lines
common/cmd_gpt.c line 49
Quoted 9 lines
common/cmd_gpt.c +7
-0+static int extract_env (char *p) + p1 =strstr (p,"${" ); + p2 =strstr (p,"}" ); + +if (p1 && p2) { + *p2 ='\0' ; +memmove (p, p+2 , p2-p1-1 );s/-1/-2/ I think, since the length of "${" is 2 not 1.
Quoted 3 lines
p2-p1-1 gives length of the env name + trailing zero. p2-p1-2 would give only the env's length and the trailing zero wouldn't be moved.
Ah right. I tend to write things like that as:
p2-p1-2+1 /* strlen("${")==2, length '\0'==1
to make it obvious what's going on
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
common/cmd_gpt.c +12
-0+ tok =strsep (&p,";" ); +if (tok ==NULL ) +break ; + +if (extract_val (&tok, name, i,"name" )) { + ret =-1 ; + goto err; + } + +if (extract_val (&tok, ps, i,"size" )) { + ret =-1 ; +free (name[i]);Quoted 8 lines
Quoted 8 lines
common/cmd_gpt.c
Quoted 2 lines
common/cmd_gpt.c +2
-0+ goto err; + }I think that requires the parameters to be passed in order name=foo,size=5,uuid=xxx. That seems inflexible. The syntax may as well just be value,value,value rather than key=value,key=value,key=value in that case (although the keys are useful in order to understand the data, so I'd prefer parsing
flexibility rather than removing key=).
Quoted 1 line
Quoted 1 line
Quoted 8 lines
Quoted 2 lines
I would say that the "key=value" is flexible. The '
extract_env' function tells you if the requested key was provided or not. Also,the
Quoted 1 line
order of keys is not important.
The order of the keys shouldn't be important, but doesn't the code above expect to find key "name" first, then key "size", etc., in tha specific order, as it walks through the string?
The key name is passed to 'extract_val' and the function should search that key no matter what order the keys appear in searched string. I check it again.
PATCH v4 6/7 gpt: Support for new "gpt" command
Quoted 26 lines · Piotr Wilczek
Stephen Warren wrote at Saturday, November 24, 2012 7:01 PM:
Quoted 24 lines · Piotr Wilczek
Quoted 13 lines
Dear Stephen,
Quoted 11 lines
Stephen Warren wrote at Monday, November 19, 2012 10:35 PM:
Quoted 8 lines · Piotr Wilczek
New command - "gpt" is supported. It restores the GPT partition table. It looks into the "partitions" environment variable for partitions definition. It can be enabled at target configuration file with
CONFIG_CMD_GPT. Simple UUID generator has been implemented. It uses the thegd->start_addr_spfor entrophy pool. Moreover the pool address is used as crc32 seed.+/**
+ *extract_env(): Convert string from '&{env_name}' to 'env_name'Quoted 8 lines
Quoted 5 lines
s/&/$/
It's doing more than that; it locates that syntax within an arbitrary string and ignores anything before "${" or after "}". Is that intentional?
Yes, it was. The u-boot's shell expands to one only, so it allow to pass any partition parameter as env when the partitions list itself
is passed as env.
Quoted 8 lines
Quoted 6 lines
OK. The issue here is that the comment doesn't exactly describe what the code is doing.
Also, what if the user wrote "foo${var}bar"; I can't recall if the code handles that correct; is the result of that just "${var}", or do "foo" and "bar" actually make it into the result string?
The 'bar' will be dropped, but to drop 'foo' a small modification is needed.
Rather than modify the code to drop "foo", why not modify it so that "bar" and "foo" are included in the result? That seem more like what the user desired, and is consistent with what any other shell or scripting language would do. If not, please return an error in this case so that bad syntax can be fixed.
PATCH v4 7/7 gpt: Enable support for GPT partition table restoration at Samsung's Trats
In reply to Piotr WilczekFrom: Lukasz Majewski <[email protected]>
Enable support for GPT partition table restoration at Samsung's Trats development board.
---
Changes for v2:
- New format for default GPT partitions (key=value pairs)
- replace size definitions with more readable description(1GiB instead of 1G)
Changes for v3:
- None
Changes for v4:
- Modified default partitions list
--- include/configs/trats.h | 29 ++++++++++++++++++++++++++++- 1 files changed, 28 insertions(+), 1 deletions(-)
include/configs/trats.h +28 -1
@@ -98,6 +98,7 @@#undef CONFIG_CMD_MTDPARTS#define CONFIG_CMD_MMC #define CONFIG_CMD_DFU +#define CONFIG_CMD_GPT /* FAT */ #define CONFIG_CMD_FAT
@@ -122,6 +123,25 @@#define CONFIG_BOOTBLOCK "10"#define CONFIG_ENV_COMMON_BOOT "${console} ${meminfo}" +/* Tizen - partitions definitions */ +#define PARTS_CSA "csa-mmc" +#define PARTS_BOOTLOADER "u-boot" +#define PARTS_BOOT "boot" +#define PARTS_ROOT "platform" +#define PARTS_DATA "data" +#define PARTS_CSC "csc" +#define PARTS_UMS "ums" + +#define PARTS_DEFAULT \ + "name="PARTS_CSA",size=8MiB,uuid=${uuid_gpt_"PARTS_CSA"};" \ + "name="PARTS_BOOTLOADER",size=60MiB," \ + "uuid=${uuid_gpt_"PARTS_BOOTLOADER"};" \ + "name="PARTS_BOOT",size=100MiB,uuid=${uuid_gpt_"PARTS_BOOT"};" \ + "name="PARTS_ROOT",size=1GiB,uuid=${uuid_gpt_"PARTS_ROOT"};" \ + "name="PARTS_DATA",size=3GiB,uuid=${uuid_gpt_"PARTS_DATA"};" \ + "name="PARTS_CSC",size=150MiB,uuid=${uuid_gpt_"PARTS_CSC"};" \ + "name="PARTS_UMS",size=-,uuid=${uuid_gpt_"PARTS_UMS"}\0" \ +#define CONFIG_DFU_ALT \ "dfu_alt_info=" \ "u-boot mmc 80 400;" \
@@ -171,7 +191,9 @@"mmcbootpart=2\0" \"mmcrootpart=3\0" \"opts=always_resume=1\0" \ -CONFIG_DFU_ALT +"uuid_gpt_disk=\0" \ +"partitions=" PARTS_DEFAULT \ +CONFIG_DFU_ALT \/* Miscellaneous configurable options */ #define CONFIG_SYS_LONGHELP /* undef to save memory */
@@ -208,6 +230,11 @@#define CONFIG_DOS_PARTITION +/* GPT */ +#define CONFIG_EFI_PARTITION +#define CONFIG_PARTITION_UUIDS +#define DEFAULT_PARTITIONS_ENV "partitions" +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - GENERATED_GBL_DATA_SIZE)#define CONFIG_SYS_CACHELINE_SIZE 32
Signature · 1 line
1.7.5.4
PATCH v4 4/7 gpt: The leXX_to_int() calls replaced with ones defined at <compiler.h>
In reply to Piotr Wilczekdisk/part_efi.c void print_part_efi(block_dev_desc_t * dev_desc) · line 153
Quoted 13 lines · Piotr Wilczek
Custom definitions of
le_XX_to_intfunctions have been replaced with standard ones, defined at <compiler.h>Replacement of several GPT related structures members with ones indicating its endianness and proper size.
disk/part_efi.c +2
-2printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1), - le64_to_int(gpt_pte[i].starting_lba), - le64_to_int(gpt_pte[i].ending_lba), + (u64) le64_to_cpu(gpt_pte[i].starting_lba), + (u64) le64_to_cpu(gpt_pte[i].ending_lba),
I don't think there should be a space after the cast. Why doesn't le64_to_cpu() return a u64? The same comments apply to many diffs in this patch.
disk/part_efi.c static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, · line 318
Quoted 7 lines
disk/part_efi.c +3
-3-if (calc_crc32 !=le32_to_int (crc32_backup)) { +if (calc_crc32 !=le32_to_cpu (crc32_backup)) {printf ("GUID Partition Table Header CRC is wrong:" -"0x%08lX != 0x%08lX\n" , -le32_to_int (crc32_backup), calc_crc32); +"0x%x != 0x%x\n" , + (u32 )le32_to_cpu (crc32_backup), calc_crc32);
Indentation looks wrong (some lines use spaces, some TABs).
disk/part_efi.c static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, · line 362
Quoted 7 lines
disk/part_efi.c +3
-3-if (calc_crc32 !=le32_to_int (pgpt_head->partition_entry_array_crc32)) { +if (calc_crc32 !=le32_to_cpu (pgpt_head->partition_entry_array_crc32)) { printf("GUID Partition Table Entry Array CRC is wrong:" - "0x%08lX != 0x%08lX\n", - le32_to_int(pgpt_head->partition_entry_array_crc32), + "0x%x != 0x%x\n", + (u32)le32_to_cpu(pgpt_head->partition_entry_array_crc32),
Same here.
Aside from that, briefly,
v4 cover gpt: GUID Partition Table (GPT) restoration
In reply to Piotr WilczekQuoted 10 lines · Piotr Wilczek
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.Moreover the
part_efi.hfile has been moved to ./include directory to be easily available from other subsystems.The GPT detailed description has been written to README.gpt file.
Please make sure that 0/7 of v5 includes the summary of changes from v4 (and from v3 and v2 and ...). patman helps you get this for free, btw :) Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20121119/1b02de87/attachment.pgp>
v4 cover gpt: GUID Partition Table (GPT) restoration
In reply to Piotr WilczekQuoted 6 lines · Piotr Wilczek
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.
Quoted 7 lines
Moreover the
part_efi.hfile has been moved to ./include directory to be easily available from other subsystems.The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development board
OK, for me, now at least, building for trats is broken after the whole series is applied, along with every other board (I believe) that enabled GPT today. Please investigate and post a v5, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20121206/68fe640c/attachment.pgp>
v4 cover gpt: GUID Partition Table (GPT) restoration
Dear Tom,
--
Samsung Poland R&D Center | Linux Platform Group
Quoted 19 lines
-----Original Message-----
From: Tom Rini [mailto:tom.rini at gmail.com] On Behalf Of Tom Rini
Sent: Thursday, December 06, 2012 9:41 PM
To: Piotr Wilczek
Cc: u-boot at lists.denx.de; Stephen Warren; Kyungmin Park
Subject: Re: [U-Boot] [PATCH v4 0/7] gpt: GUID Partition Table (GPT) restorationQuoted 9 lines · Piotr Wilczek
This patch series provides a new command - "gpt" for eMMC partition table (in the GPT format) restoration.
As a pre-work, some cleanup at the
part_efi.cfile was performed to remove custom macros and make GPT related structures more readable.Moreover the
part_efi.hfile has been moved to ./include directory to be easily available from other subsystems.
Quoted 9 lines
Quoted 4 lines
The GPT detailed description has been written to README.gpt file.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardOK, for me, now at least, building for trats is broken after the whole series is applied, along with every other board (I believe) that enabled GPT today. Please investigate and post a v5, thanks!
I should send v5 very soon.
Quoted 2 lines
--
Tom
Regards,
Piotr Wilczek