gpt: GUID Partition Table (GPT) restoration
Subsystems (2)
v5 cover gpt: GUID Partition Table (GPT) restoration
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.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 | 333 +++++++++++++++++++++++++++++++++++
disk/part_efi.c | 394 ++++++++++++++++++++++++++++++++++--------
doc/README.gpt | 201 +++++++++++++++++++++
include/configs/trats.h | 28 ++-
include/exports.h | 2 +-
include/part.h | 52 ++++++
{disk => include}/part_efi.h | 89 +++++-----
lib/vsprintf.c | 2 +-
9 files changed, 982 insertions(+), 120 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.9.5
PATCH v5 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 in v5:
- changed return type in ustrtoul function decalration
Changes in v4:
- None
Changes in v3:
- None
Changes in v2:
- 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
@@ -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.9.5
PATCH v5 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.
Additionally the part_efi.h file has been cleaned-up to supress checkpatch's warnings.
---
Changes in v5:
- None
Changes in v4:
- None
Changes in v3:
- None
Changes in v2:
- None
{disk => include}/part_efi.h | 0
1 file 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.9.5
PATCH v5 3/7 gpt:doc: GPT (GUID Partition Table) documentation
In reply to Piotr WilczekFrom: Lukasz Majewski <[email protected]>
Documentation of the GPT format.
---
Changes in v5:
- Updated documentation
Changes in v4:
- Updated documentation
Changes in v3:
- None
Changes in v2:
- Typos correction.
- Adding guidlines about GPT restoration.
- Adding information about GUID generator
doc/README.gpt | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 doc/README.gpt
doc/README.gpt new file +201 -0
@@ -0,0 +1,201 @@ +# +# 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 and usage of +the gpt command in 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 x 10^38. +More often UUID is displayed as 32 hexadecimal digits, in 5 groups, +separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters +(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 + + +Creating GPT partitions in U-Boot: +============== + +To restore GUID partition table one needs to: +1. Define partition layout in the environment. + Format of partitions layout: + "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; + name=kernel,size=60MiB,uuid=...;" + or + "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, + size=${uboot_size},uuid=${uboot_uuid};" + + Fields 'name', 'size' and 'uuid' are mandatory for every partition. + The field 'start' is optional. + +2. Define 'CONFIG_EFI_PARTITION' and 'CONFIG_CMD_GPT' + +2. From u-boot prompt type: + gpt write mmc 0 $partitions + + +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.9.5
PATCH v5 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 in v5:
- removed unncessary casting
Changes in v4:
- None
Changes in v3:
- None
Changes in v2:
- Combining two commits regarding part_efi.{h|c}
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), +le64_to_cpu (gpt_pte[i].starting_lba), +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 ); +le64_to_cpu (pgpt_head->signature), +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" , +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); +le64_to_cpu (pgpt_head->my_lba), + 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); +le64_to_cpu (pgpt_head->first_usable_lba), +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" , +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), +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.9.5
PATCH v5 5/7 gpt: Support for GPT (GUID Partition Table) restoration
In reply to Piotr WilczekFrom: Lukasz Majewski <[email protected]>
The restoration of GPT table (both primary and secondary) is now possible. Function 'gpt_restore' presents example of partition restoration process.
---
Changes in v5:
- changed function name 'set_gpt_table' to 'write_gpt_table'
- changed function name 'gpt_fill' to 'gpt_restore'
- moved function documentation to header file
- removed guid generation
- fixed partition layout check
Changes in 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
Changes in v3:
- Replace printf with puts
Changes in 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 | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- include/part.h | 52 ++++++++++ 2 files changed, 330 insertions(+), 3 deletions(-)
disk/part_efi.c +278 -3
@@ -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) || \
@@ -62,13 +64,10 @@ static inline u32 efi_crc32(const void *buf, u32 len)static int pmbr_part_valid (struct partition *part);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); -static gpt_entry *alloc_read_gpt_entries (block_dev_desc_t * dev_desc,gpt_header * pgpt_head); -static int is_pte_valid (gpt_entry * pte);static char *print_efiname (gpt_entry *pte)
@@ -114,6 +113,7 @@ static inline int is_bootable(gpt_entry *p) sizeof(efi_guid_t)); } +#ifdef CONFIG_EFI_PARTITION /* * Public Functions (include/part.h) */
@@ -225,6 +225,281 @@ int test_part_efi(block_dev_desc_t * dev_desc) return 0; } +/** +* 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 */ + p_mbr =calloc (1 ,sizeof (p_mbr)); +if (p_mbr ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +return -1 ; + } +/* 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); +free (p_mbr); +return -1 ; + } + +free (p_mbr); +return 0 ; +} + +/** +* string_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 string_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); + +memcpy (dst, guid.b,sizeof (efi_guid_t)); + +return 0 ; +} + +int write_gpt_table (block_dev_desc_t *dev_desc, +gpt_header *gpt_h,gpt_entry *gpt_e) +{ +const int pte_blk_num = (gpt_h->num_partition_entries + *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; + +debug ("GPT successfully written to block device!\n" ); +return 0 ; + + err: +printf ("** Can't write to device %d **\n" , dev_desc->dev); +return -1 ; +} + +int 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); +ulong start; +int i, k; +size_t name_len; +#ifdef CONFIG_PARTITION_UUIDS +char *str_uuid; +#endif + +for (i =0 ; i < parts; i++) { +/* partition starting lba */ + start = partitions[i].start; +if (start && (start < offset)) { +printf ("Partition overlap\n" ); +return -1 ; + } +if (start) { + gpt_e[i].starting_lba =cpu_to_le64 (start); + offset = start + partitions[i].size; + }else { + gpt_e[i].starting_lba =cpu_to_le64 (offset); + offset += partitions[i].size; + } +if (offset >= gpt_h->last_usable_lba) { +printf ("Partitions layout exceds disk size\n" ); +return -1 ; + } +/* partition ending lba */ +if ((i == parts -1 ) && (partitions[i].size ==0 )) +/* extend the last partition to maximuim */ + gpt_e[i].ending_lba = gpt_h->last_usable_lba; +else + gpt_e[i].ending_lba =cpu_to_le64 (offset -1 ); + +/* partition type GUID */ +memcpy (gpt_e[i].partition_type_guid.b, + &PARTITION_BASIC_DATA_GUID ,16 ); + +#ifdef CONFIG_PARTITION_UUIDS + str_uuid = partitions[i].uuid; +if (string_uuid (str_uuid, gpt_e[i].unique_partition_guid.b)) { +printf ("Partition no. %d: invalid guid: %s\n" , + i, str_uuid); +return -1 ; + } +#endif + +/* partition attributes */ +memset (&gpt_e[i].attributes,0 , +sizeof (gpt_entry_attributes)); + +/* partition name */ + name_len =sizeof (gpt_e[i].partition_name) + /sizeof (efi_char16_t); +for (k =0 ; k < name_len; k++) + gpt_e[i].partition_name[k] = + (efi_char16_t)(partitions[i].name[k]); + +debug ("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%lx\n" , + __func__, partitions[i].name, i, + offset, i, partitions[i].size); + } + +return 0 ; +} + +int gpt_fill_header (block_dev_desc_t *dev_desc,gpt_header *gpt_h, +char *str_guid,int parts_count) +{ + 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 ; + +if (string_uuid (str_guid, gpt_h->disk_guid.b)) +return -1 ; + +return 0 ; +} + +int gpt_restore (block_dev_desc_t *dev_desc,char *str_disk_guid, +disk_partition_t *partitions,int parts_count) +{ +int ret; + +gpt_header *gpt_h =calloc (1 ,sizeof (gpt_header)); +if (gpt_h ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +return -1 ; + } + +gpt_entry *gpt_e =calloc (GPT_ENTRY_NUMBERS ,sizeof (gpt_entry)); +if (gpt_e ==NULL ) { +printf ("%s: calloc failed!\n" , __func__); +free (gpt_h); +return -1 ; + } + +/* Generate Primary GPT header (LBA1) */ + ret =gpt_fill_header (dev_desc, gpt_h, str_disk_guid, parts_count); +if (ret) + goto err; + +/* Generate partition entries */ + ret =gpt_fill_pte (gpt_h, gpt_e, partitions, parts_count); +if (ret) + goto err; + +/* Write GPT partition table */ + ret =write_gpt_table (dev_desc, gpt_h, gpt_e); + +err: +free (gpt_e); +free (gpt_h); +return ret; +} +#endif +/* * Private functions */
include/part.h +52 -0
62 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v5 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 given environment variable for partitions definition. It can be enabled at target configuration file with CONFIG_CMD_GPT.
---
Changes in v5:
- rewritten 'do_gpt', 'gpt_mmc_default', 'set_gpt_info', 'extract_env', and 'extract_val' functions
- 'extract_val' function return value for given key (keys can be in any order)
- add 'write' command
Changes in v4:
- partions list can be passed as environment variable or directly as text
- each value in partions list can be passed as environment variable
Changes in v3:
- Remove unnecessary braces
Changes in 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 | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 334 insertions(+) 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 +333 -0
333 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v5 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 in v5:
- Modified partitions list format
Changes in v4:
- Modified default partitions list
Changes in v3:
- None
Changes in 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 | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-)
include/configs/trats.h +27 -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,26 @@#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 \ + "uuid_disk=${uuid_gpt_disk};" \ + "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 +192,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 */
@@ -208,6 +230,10 @@#define CONFIG_DOS_PARTITION +/* GPT */ +#define CONFIG_EFI_PARTITION +#define CONFIG_PARTITION_UUIDS +#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.9.5
v5 cover gpt: GUID Partition Table (GPT) restoration
In reply to Piotr WilczekQuoted 30 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.
Tested at:
- Exynos4210 rev.1 - TRATS Samsung development boardChang Hyun Park (1):
gpt: TheleXX_to_int()calls replaced with ones defined at
<compiler.h>Lukasz Majewski (5):
vsprintf:fix: Change type returned by ustrtoul
part:efi: Movepart_efi.hfile 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
TratsPiotr Wilczek (1):
gpt: Support for new "gpt" command
Quoted 13 lines
common/Makefile | 1 +
common/cmd_gpt.c | 333 +++++++++++++++++++++++++++++++++++
disk/part_efi.c | 394 ++++++++++++++++++++++++++++++++++--------
doc/README.gpt | 201 +++++++++++++++++++++
include/configs/trats.h | 28 ++-
include/exports.h | 2 +-
include/part.h | 52 ++++++
{disk => include}/part_efi.h | 89 +++++-----
lib/vsprintf.c | 2 +-
9 files changed, 982 insertions(+), 120 deletions(-)
create mode 100644 common/cmd_gpt.c
create mode 100644 doc/README.gpt
rename {disk => include}/part_efi.h (66%)Applied to u-boot/master, 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/20121214/ce960373/attachment.pgp>