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 \