@ -69,6 +69,7 @@ static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry)
/* Check MBR boot signature. */
if ( ( mbr_sector [ LEGACY_PARTITION_BLOCK_SIZE - 2 ] ! = MBR_SIGNATURE_FIRST ) | |
( mbr_sector [ LEGACY_PARTITION_BLOCK_SIZE - 1 ] ! = MBR_SIGNATURE_SECOND ) ) {
WARN ( " MBR boot signature failure \n " ) ;
return - ENOENT ;
}
@ -102,15 +103,21 @@ static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
result = io_seek ( image_handle , IO_SEEK_SET , header_offset ) ;
if ( result ! = 0 ) {
WARN ( " Failed to seek into the GPT image at offset (%zu) \n " ,
header_offset ) ;
return result ;
}
result = io_read ( image_handle , ( uintptr_t ) & header ,
sizeof ( gpt_header_t ) , & bytes_read ) ;
if ( ( result ! = 0 ) | | ( sizeof ( gpt_header_t ) ! = bytes_read ) ) {
WARN ( " GPT header read error(%i) or read mismatch occurred "
" expected(%zu) and actual(%zu) \n " , result ,
sizeof ( gpt_header_t ) , bytes_read ) ;
return result ;
}
if ( memcmp ( header . signature , GPT_SIGNATURE ,
sizeof ( header . signature ) ) ! = 0 ) {
sizeof ( header . signature ) ) ! = 0 ) {
WARN ( " GPT header signature failure \n " ) ;
return - EINVAL ;
}
@ -141,6 +148,9 @@ static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
return 0 ;
}
/*
* Load a single MBR entry based on details from MBR header .
*/
static int load_mbr_entry ( uintptr_t image_handle , mbr_entry_t * mbr_entry ,
int part_number )
{
@ -165,6 +175,7 @@ static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry,
/* Check MBR boot signature. */
if ( ( mbr_sector [ LEGACY_PARTITION_BLOCK_SIZE - 2 ] ! = MBR_SIGNATURE_FIRST ) | |
( mbr_sector [ LEGACY_PARTITION_BLOCK_SIZE - 1 ] ! = MBR_SIGNATURE_SECOND ) ) {
WARN ( " MBR Entry boot signature failure \n " ) ;
return - ENOENT ;
}
offset = ( uintptr_t ) & mbr_sector +
@ -175,6 +186,9 @@ static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry,
return 0 ;
}
/*
* Load MBR entries based on max number of partition entries .
*/
static int load_mbr_entries ( uintptr_t image_handle )
{
mbr_entry_t mbr_entry ;
@ -192,33 +206,60 @@ static int load_mbr_entries(uintptr_t image_handle)
return 0 ;
}
/*
* Try to read and load a single GPT entry .
*/
static int load_gpt_entry ( uintptr_t image_handle , gpt_entry_t * entry )
{
size_t bytes_read ;
size_t bytes_read = 0U ;
int result ;
assert ( entry ! = NULL ) ;
result = io_read ( image_handle , ( uintptr_t ) entry , sizeof ( gpt_entry_t ) ,
& bytes_read ) ;
if ( sizeof ( gpt_entry_t ) ! = bytes_read )
& bytes_read ) ;
if ( ( result ! = 0 ) | | ( sizeof ( gpt_entry_t ) ! = bytes_read ) ) {
WARN ( " GPT Entry read error(%i) or read mismatch occurred "
" expected(%zu) and actual(%zu) \n " , result ,
sizeof ( gpt_entry_t ) , bytes_read ) ;
return - EINVAL ;
}
return result ;
}
static int verify_partition_gpt ( uintptr_t image_handle )
/*
* Retrieve each entry in the partition table , parse the data from each
* entry and store them in the list of partition table entries .
*/
static int load_partition_gpt ( uintptr_t image_handle ,
unsigned long long part_lba )
{
const signed long long gpt_entry_offset = LBA ( part_lba ) ;
gpt_entry_t entry ;
int result , i ;
result = io_seek ( image_handle , IO_SEEK_SET , gpt_entry_offset ) ;
if ( result ! = 0 ) {
WARN ( " Failed to seek (%i), Failed loading GPT partition "
" table entries \n " , result ) ;
return result ;
}
for ( i = 0 ; i < list . entry_count ; i + + ) {
result = load_gpt_entry ( image_handle , & entry ) ;
assert ( result = = 0 ) ;
if ( result ! = 0 ) {
WARN ( " Failed to load gpt entry data(%i) error is (%i) \n " ,
i , result ) ;
return result ;
}
result = parse_gpt_entry ( & entry , & list . list [ i ] ) ;
if ( result ! = 0 ) {
break ;
}
}
if ( i = = 0 ) {
WARN ( " No Valid GPT Entries found \n " ) ;
return - EINVAL ;
}
/*
@ -231,18 +272,104 @@ static int verify_partition_gpt(uintptr_t image_handle)
return 0 ;
}
/*
* Try retrieving and parsing the backup - GPT header and backup GPT entries .
* Last 33 blocks contains the backup - GPT entries and header .
*/
static int load_backup_gpt ( unsigned int image_id , unsigned int sector_nums )
{
int result ;
unsigned long long part_lba = 0 ;
size_t gpt_header_offset ;
uintptr_t dev_handle , image_spec , image_handle ;
io_block_spec_t * block_spec ;
int part_num_entries ;
result = plat_get_image_source ( image_id , & dev_handle , & image_spec ) ;
if ( result ! = 0 ) {
WARN ( " Failed to obtain reference to image id=%u (%i) \n " ,
image_id , result ) ;
return result ;
}
block_spec = ( io_block_spec_t * ) image_spec ;
/*
* We need to read 32 blocks of GPT entries and one block of GPT header
* try mapping only last 33 last blocks from the image to read the
* Backup - GPT header and its entries .
*/
part_num_entries = ( PLAT_PARTITION_MAX_ENTRIES / 4 ) ;
/* Move the offset base to LBA-33 */
block_spec - > offset + = LBA ( sector_nums - part_num_entries ) ;
/*
* Set length as LBA - 33 , 32 blocks of backup - GPT entries and one
* block of backup - GPT header .
*/
block_spec - > length = LBA ( part_num_entries + 1 ) ;
result = io_open ( dev_handle , image_spec , & image_handle ) ;
if ( result ! = 0 ) {
WARN ( " Failed to access image id (%i) \n " , result ) ;
return result ;
}
INFO ( " Trying to retrieve back-up GPT header \n " ) ;
/* Last block is backup-GPT header, after the end of GPT entries */
gpt_header_offset = LBA ( part_num_entries ) ;
result = load_gpt_header ( image_handle , gpt_header_offset , & part_lba ) ;
if ( ( result ! = 0 ) | | ( part_lba = = 0 ) ) {
ERROR ( " Failed to retrieve Backup GPT header, "
" Partition maybe corrupted \n " ) ;
goto out ;
}
/*
* Note we mapped last 33 blocks ( LBA - 33 ) , first block here starts with
* entries while last block was header .
*/
result = load_partition_gpt ( image_handle , 0 ) ;
out :
io_close ( image_handle ) ;
return result ;
}
/*
* Load a GPT partition , Try retrieving and parsing the primary GPT header ,
* if its corrupted try loading backup GPT header and then retrieve list
* of partition table entries found from the GPT .
*/
static int load_primary_gpt ( uintptr_t image_handle , unsigned int first_lba )
{
int result ;
unsigned long long part_lba ;
size_t gpt_header_offset ;
/* Try to load Primary GPT header from LBA1 */
gpt_header_offset = LBA ( first_lba ) ;
result = load_gpt_header ( image_handle , gpt_header_offset , & part_lba ) ;
if ( ( result ! = 0 ) | | ( part_lba = = 0 ) ) {
WARN ( " Failed to retrieve Primary GPT header, "
" trying to retrieve back-up GPT header \n " ) ;
return result ;
}
return load_partition_gpt ( image_handle , part_lba ) ;
}
/*
* Load the partition table info based on the image id provided .
*/
int load_partition_table ( unsigned int image_id )
{
uintptr_t dev_handle , image_handle , image_spec = 0 ;
mbr_entry_t mbr_entry ;
int result ;
size_t gpt_header_offset ;
unsigned long long part_lba = 0 , gpt_entry_offset = 0 ;
result = plat_get_image_source ( image_id , & dev_handle , & image_spec ) ;
if ( result ! = 0 ) {
WARN ( " Failed to obtain reference to image id=%u (%i) \n " ,
image_id , result ) ;
image_id , result ) ;
return result ;
}
@ -255,34 +382,27 @@ int load_partition_table(unsigned int image_id)
result = load_mbr_header ( image_handle , & mbr_entry ) ;
if ( result ! = 0 ) {
WARN ( " Failed to access image id=%u (%i) \n " , image_id , result ) ;
return resul t;
goto ou t;
}
if ( mbr_entry . type = = PARTITION_TYPE_GPT ) {
/* Try to load GPT header from LBA-1 */
gpt_header_offset = mbr_entry . first_lba * PLAT_PARTITION_BLOCK_SIZE ;
result = load_gpt_header ( image_handle , gpt_header_offset , & part_lba ) ;
if ( result ! = 0 | | part_lba = = 0 ) {
WARN ( " Failed to retrieve Primary GPT header \n " ) ;
return result ;
}
gpt_entry_offset = part_lba * PLAT_PARTITION_BLOCK_SIZE ;
result = io_seek ( image_handle , IO_SEEK_SET , gpt_entry_offset ) ;
result = load_primary_gpt ( image_handle , mbr_entry . first_lba ) ;
if ( result ! = 0 ) {
WARN ( " Failed to seek (%i), "
" Failed loading GPT partition table entries \n " ,
result ) ;
return result ;
io_close ( image_handle ) ;
return load_backup_gpt ( BKUP_GPT_IMAGE_ID ,
mbr_entry . sector_nums ) ;
}
result = verify_partition_gpt ( image_handle ) ;
} else {
result = load_mbr_entries ( image_handle ) ;
}
out :
io_close ( image_handle ) ;
return result ;
}
/*
* Try retrieving a partition table entry based on the name of the partition .
*/
const partition_entry_t * get_partition_entry ( const char * name )
{
int i ;
@ -295,6 +415,9 @@ const partition_entry_t *get_partition_entry(const char *name)
return NULL ;
}
/*
* Try retrieving a partition table entry based on the GUID .
*/
const partition_entry_t * get_partition_entry_by_type ( const uuid_t * type_uuid )
{
int i ;
@ -308,6 +431,9 @@ const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid)
return NULL ;
}
/*
* Try retrieving a partition table entry based on the UUID .
*/
const partition_entry_t * get_partition_entry_by_uuid ( const uuid_t * part_uuid )
{
int i ;
@ -321,11 +447,17 @@ const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid)
return NULL ;
}
/*
* Return entry to the list of partition table entries .
*/
const partition_entry_list_t * get_partition_entry_list ( void )
{
return & list ;
}
/*
* Try loading partition table info for the given image ID .
*/
void partition_init ( unsigned int image_id )
{
load_partition_table ( image_id ) ;