blob: 1f68e4b2d59d8a4236dc484627de64550da0d7a9 [file] [log] [blame]
/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include "mmc.h"
#include "partition_parser.h"
static struct gpt_entry gpt[NUM_GPT_PARTITIONS];
static uint32_t gpt_partition_count = 0;
/*
* Read GPT from MMC and fill partition table
*/
uint32_t mmc_boot_read_gpt(struct mmc_boot_host * mmc_host,
struct mmc_boot_card * mmc_card){
int32_t ret = MMC_BOOT_E_SUCCESS;
uint32_t header_size = 0;
//uint32_t header_crc = 0;
uint64_t first_usable_lba = 0;
uint64_t last_usable_lba = 0;
uint32_t partition_count = 0;
uint32_t partition_entry_size = 0;
//uint32_t partition_array_crc;
uint8_t data[MMC_BOOT_RD_BLOCK_LEN];
uint32_t i = 0; /* Counter for each 512 block */
uint32_t j = 0; /* Counter for each 128 entry in the 512 block */
/* Print out the GPT first */
ret = mmc_boot_read_from_card( mmc_host, mmc_card,
PROTECTIVE_MBR_SIZE,
MMC_BOOT_RD_BLOCK_LEN,
(uint32_t *)data);
/* Check GPT Signature */
if( ((uint32_t *)data)[0] != GPT_SIGNATURE_2 ||
((uint32_t *)data)[1] != GPT_SIGNATURE_1 )
{
dprintf(CRITICAL, "GPT: signature does not match.\n" );
return MMC_BOOT_E_FAILURE;
}
header_size = GET_LWORD_FROM_BYTE(&data[HEADER_SIZE_OFFSET]);
//header_crc = GET_LWORD_FROM_BYTE(&data[HEADER_CRC_OFFSET]);
first_usable_lba = GET_LLWORD_FROM_BYTE(&data[FIRST_USABLE_LBA_OFFSET]);
last_usable_lba = GET_LLWORD_FROM_BYTE(&data[LAST_USABLE_LBA_OFFSET]);
partition_count = GET_LWORD_FROM_BYTE(&data[PARTITION_COUNT_OFFSET]);
partition_entry_size = GET_LWORD_FROM_BYTE(&data[PENTRY_SIZE_OFFSET]);
/* Read GPT Entries */
for(i = 0; i < (partition_count/4); i++)
{
ret = mmc_boot_read_from_card( mmc_host, mmc_card,
PROTECTIVE_MBR_SIZE + PARTITION_TABLE_SIZE +
(i * MMC_BOOT_RD_BLOCK_LEN),
MMC_BOOT_RD_BLOCK_LEN,
(uint32_t *)data);
if (ret)
{
dprintf(CRITICAL, "GPT: mmc read card failed reading partition entries.\n" );
return ret;
}
for(j=0; j < 4; j++)
{
memcpy(&(gpt[j+(i*4)].partition_type_guid),
&data[(j * partition_entry_size)], PARTITION_TYPE_GUID_SIZE);
if (gpt[j+(i*4)].partition_type_guid[0] == 0x00 &&
gpt[j+(i*4)].partition_type_guid[1] == 0x00)
{
i = partition_count;
break;
}
gpt_partition_count++;
memcpy(&(gpt[j+(i*4)].unique_partition_guid),
&data[(j * partition_entry_size) + UNIQUE_GUID_OFFSET], UNIQUE_PARTITION_GUID_SIZE);
gpt[j+(i*4)].first_lba = GET_LLWORD_FROM_BYTE(&data[(j * partition_entry_size) +
FIRST_LBA_OFFSET]);
gpt[j+(i*4)].last_lba = GET_LLWORD_FROM_BYTE(&data[(j * partition_entry_size) +
LAST_LBA_OFFSET]);
gpt[j+(i*4)].attribute_flag = GET_LLWORD_FROM_BYTE(&data[(j * partition_entry_size) +
ATTRIBUTE_FLAG_OFFSET]);
memcpy(&(gpt[j+(i*4)].partition_name),
&data[(j * partition_entry_size) + PARTITION_NAME_OFFSET], MAX_GPT_NAME_SIZE);
}
}
return ret;
}
uint64_t gpt_lookup(uint8_t * name, unsigned type){
uint32_t input_string_length = strlen(name);
uint8_t UTF16_name[MAX_GPT_NAME_SIZE];
unsigned n;
memset(&UTF16_name, 0x00, MAX_GPT_NAME_SIZE);
/* Currently partition names in partition.xml are UTF-8 and lowercase */
for(n = 0; n < input_string_length && n < MAX_GPT_NAME_SIZE/2; n++){
UTF16_name[n*2] = name[n];
UTF16_name[n*2+1] = 0x00;
}
for(n = 0; n < gpt_partition_count; n++){
if(!memcmp(&UTF16_name, &gpt[n].partition_name, MAX_GPT_NAME_SIZE)){
if(type == PTN_SIZE)
return ((uint64_t)(gpt[n].last_lba - gpt[n].first_lba) * MMC_BOOT_RD_BLOCK_LEN);
else if(type == PTN_OFFSET)
return ((uint64_t)gpt[n].first_lba * MMC_BOOT_RD_BLOCK_LEN);
else
return 0;
}
}
return 0;
}