mmc/aboot: Adding GPT parser for appsboot
Initial commit for adding a GPT parser for Guid Partitions.
This only adds the functionality and enables
GPT to be parsed and as well as MBR format.
Change-Id: I9a85926cc0f4503cd169f8eaed867f1f2df97598
diff --git a/platform/msm_shared/include/mmc.h b/platform/msm_shared/include/mmc.h
index 5564101..1f94ec3 100755
--- a/platform/msm_shared/include/mmc.h
+++ b/platform/msm_shared/include/mmc.h
@@ -624,5 +624,10 @@
#define MMC_CLK_ENABLE 1
#define MMC_CLK_DISABLE 0
+unsigned int mmc_boot_read_from_card( struct mmc_boot_host* host,
+ struct mmc_boot_card* card,
+ unsigned long long data_addr,
+ unsigned int data_len,
+ unsigned int* out );
#endif
diff --git a/platform/msm_shared/include/partition_parser.h b/platform/msm_shared/include/partition_parser.h
new file mode 100644
index 0000000..56855e2
--- /dev/null
+++ b/platform/msm_shared/include/partition_parser.h
@@ -0,0 +1,83 @@
+/* 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.
+ */
+
+/* Lookup Type */
+//TODO: Remove when merging MBR code to mmc_parser
+#define PTN_OFFSET 0x01
+#define PTN_SIZE 0x02
+
+/* GPT Signature should be 0x5452415020494645 */
+#define GPT_SIGNATURE_1 0x54524150
+#define GPT_SIGNATURE_2 0x20494645
+
+/* GPT Offsets */
+#define PROTECTIVE_MBR_SIZE 512
+#define PARTITION_TABLE_SIZE 512
+#define PARTITION_ENTRY_SIZE 512
+#define HEADER_SIZE_OFFSET 12
+#define HEADER_CRC_OFFSET 16
+#define FIRST_USABLE_LBA_OFFSET 40
+#define LAST_USABLE_LBA_OFFSET 48
+#define PARTITION_ENTRIES_OFFSET 72
+#define PARTITION_COUNT_OFFSET 80
+#define PENTRY_SIZE_OFFSET 84
+#define PARTITION_CRC_OFFSET 88
+
+#define UNIQUE_GUID_OFFSET 16
+#define FIRST_LBA_OFFSET 32
+#define LAST_LBA_OFFSET 40
+#define ATTRIBUTE_FLAG_OFFSET 48
+#define PARTITION_NAME_OFFSET 56
+
+#define MAX_GPT_NAME_SIZE 72
+#define PARTITION_TYPE_GUID_SIZE 16
+#define UNIQUE_PARTITION_GUID_SIZE 16
+#define NUM_GPT_PARTITIONS 32
+
+#define GET_LLWORD_FROM_BYTE(x) ((unsigned long long)*(x) | \
+ ((unsigned long long)*(x+1) << 8) | \
+ ((unsigned long long)*(x+2) << 16) | \
+ ((unsigned long long)*(x+3) << 24) | \
+ ((unsigned long long)*(x+4) << 32) | \
+ ((unsigned long long)*(x+5) << 40) | \
+ ((unsigned long long)*(x+6) << 48) | \
+ ((unsigned long long)*(x+7) << 56))
+
+struct gpt_entry
+{
+ unsigned char partition_type_guid[PARTITION_TYPE_GUID_SIZE];
+ unsigned char unique_partition_guid[UNIQUE_PARTITION_GUID_SIZE];
+ unsigned long long first_lba;
+ unsigned long long last_lba;
+ unsigned long long attribute_flag;
+ unsigned char partition_name[MAX_GPT_NAME_SIZE];
+};
+
+unsigned int mmc_boot_read_gpt(struct mmc_boot_host * mmc_host,
+ struct mmc_boot_card * mmc_card);
+unsigned long long gpt_lookup(unsigned char * name, unsigned type);
diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index 3984bf6..d6dc3ec 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -31,6 +31,7 @@
#include <debug.h>
#include <reg.h>
#include "mmc.h"
+#include "partition_parser.h"
#include <platform/iomap.h>
#if MMC_BOOT_ADM
@@ -94,6 +95,7 @@
struct mmc_boot_card mmc_card;
struct mbr_entry mbr[MAX_PARTITIONS];
unsigned mmc_partition_count = 0;
+static unsigned gpt_partitions_exist = 0;
unsigned int mmc_read (unsigned long long data_addr, unsigned int* out,
unsigned int data_len);
@@ -1671,7 +1673,7 @@
* Reads a data of data_len from the address specified. data_len
* should be multiple of block size for block data transfer.
*/
-static unsigned int mmc_boot_read_from_card( struct mmc_boot_host* host,
+unsigned int mmc_boot_read_from_card( struct mmc_boot_host* host,
struct mmc_boot_card* card,
unsigned long long data_addr,
unsigned int data_len,
@@ -2291,7 +2293,7 @@
unsigned int dfirstsec;
unsigned int EBR_first_sec;
unsigned int EBR_current_sec;
- int ret = 0;
+ int ret = MMC_BOOT_E_SUCCESS;
int idx, i;
/* Print out the MBR first */
@@ -2315,10 +2317,15 @@
idx = TABLE_ENTRY_0;
for (i = 0; i < 4; i++)
{
+ dtype = buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
+ /* Type 0xEE indicates end of MBR and GPT partitions exist */
+ if (dtype == 0xEE){
+ gpt_partitions_exist = 1;
+ return ret;
+ }
+ mbr[mmc_partition_count].dtype = dtype;
mbr[mmc_partition_count].dstatus = \
buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
- mbr[mmc_partition_count].dtype = \
- buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
mbr[mmc_partition_count].dfirstsec = \
GET_LWORD_FROM_BYTE(&buffer[idx + \
i * TABLE_ENTRY_SIZE + \
@@ -2327,7 +2334,6 @@
GET_LWORD_FROM_BYTE(&buffer[idx + \
i * TABLE_ENTRY_SIZE + \
OFFSET_SIZE]);
- dtype = mbr[mmc_partition_count].dtype;
dfirstsec = mbr[mmc_partition_count].dfirstsec;
mbr_fill_name(&mbr[mmc_partition_count], \
mbr[mmc_partition_count].dtype);
@@ -2443,6 +2449,16 @@
return MMC_BOOT_E_FAILURE;
}
+ /* Read GPT of the card if exist */
+ if(gpt_partitions_exist){
+ mmc_ret = mmc_boot_read_gpt(&mmc_host, &mmc_card);
+ if( mmc_ret != MMC_BOOT_E_SUCCESS )
+ {
+ dprintf(CRITICAL, "GPT Boot: GPT read failed!\n" );
+ return MMC_BOOT_E_FAILURE;
+ }
+ }
+
return MMC_BOOT_E_SUCCESS;
}
@@ -2561,9 +2577,15 @@
return ((uint64_t)mbr[n].dfirstsec * MMC_BOOT_RD_BLOCK_LEN);
}
}
- return 0;
+ if (gpt_partitions_exist)
+ return gpt_lookup(name, PTN_OFFSET);
+ else
+ return 0;
}
+/*
+ * Returns size of given partition
+ */
uint64_t mmc_ptn_size (unsigned char * name)
{
unsigned n;
@@ -2572,7 +2594,10 @@
return ((uint64_t)mbr[n].dsize * MMC_BOOT_RD_BLOCK_LEN);
}
}
- return 0;
+ if (gpt_partitions_exist)
+ return gpt_lookup(name, PTN_SIZE);
+ else
+ return 0;
}
/*
diff --git a/platform/msm_shared/partition_parser.c b/platform/msm_shared/partition_parser.c
new file mode 100644
index 0000000..1f68e4b
--- /dev/null
+++ b/platform/msm_shared/partition_parser.c
@@ -0,0 +1,141 @@
+/* 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;
+}
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 57827c5..bcb8bac 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -17,7 +17,8 @@
$(LOCAL_DIR)/nand.o \
$(LOCAL_DIR)/lcdc.o \
$(LOCAL_DIR)/mddi.o \
- $(LOCAL_DIR)/mmc.o
+ $(LOCAL_DIR)/mmc.o \
+ $(LOCAL_DIR)/partition_parser.o
ifeq ($(PLATFORM),msm8x60)
OBJS += $(LOCAL_DIR)/mipi_dsi.o \