GPT: Enable partition table to be flashed using fastboot command.
The partition table can be flashed using the command "fastboot flash partition
<name of the file>". Code detects the GPT partition table and flashes it
to the eMMC card.
Change-Id: I93c9a204ba0a7c0328a9cfd30331ea6cbe7d5df4
diff --git a/platform/msm_shared/include/mmc.h b/platform/msm_shared/include/mmc.h
index bba854a..33dc336 100644
--- a/platform/msm_shared/include/mmc.h
+++ b/platform/msm_shared/include/mmc.h
@@ -535,15 +535,6 @@
#define GET_PAR_NUM_FROM_POS(x) (((x & 0x0000FF00) >> 8) + (x & 0x000000FF))
-/* Some useful define used to access the MBR/EBR table */
-#define BLOCK_SIZE 0x200
-#define TABLE_ENTRY_0 0x1BE
-#define TABLE_ENTRY_1 0x1CE
-#define TABLE_ENTRY_2 0x1DE
-#define TABLE_ENTRY_3 0x1EE
-#define TABLE_SIGNATURE 0x1FE
-#define TABLE_ENTRY_SIZE 0x010
-
#define OFFSET_STATUS 0x00
#define OFFSET_TYPE 0x04
#define OFFSET_FIRST_SEC 0x08
@@ -554,8 +545,6 @@
#define MMC_RCA 2
-extern unsigned gpt_partitions_exist;
-
/* Can be used to unpack array of upto 32 bits data */
#define UNPACK_BITS(array, start, len, size_of) \
({ \
@@ -612,11 +601,11 @@
unsigned int data_len,
unsigned int *in );
-unsigned int mmc_write_partition (unsigned size, unsigned char *partition);
-unsigned int mmc_write_mbr_in_blocks(unsigned size, unsigned char *mbrImage);
-unsigned int mmc_write_mbr(unsigned size, unsigned char *mbrImage);
-unsigned int mmc_erase_card(unsigned long long data_addr,
- unsigned long long data_len);
-
+
+unsigned int mmc_erase_card(unsigned long long data_addr,
+ unsigned long long data_len);
+
+struct mmc_boot_host* get_mmc_host( void );
+struct mmc_boot_card* get_mmc_card( void );
#endif
diff --git a/platform/msm_shared/include/partition_parser.h b/platform/msm_shared/include/partition_parser.h
index 057f4ce..6df3902 100644
--- a/platform/msm_shared/include/partition_parser.h
+++ b/platform/msm_shared/include/partition_parser.h
@@ -43,6 +43,7 @@
#define PROTECTIVE_MBR_SIZE BLOCK_SIZE
#define HEADER_SIZE_OFFSET 12
#define HEADER_CRC_OFFSET 16
+#define PRIMARY_HEADER_OFFSET 24
#define BACKUP_HEADER_OFFSET 32
#define FIRST_USABLE_LBA_OFFSET 40
#define LAST_USABLE_LBA_OFFSET 48
@@ -51,6 +52,8 @@
#define PENTRY_SIZE_OFFSET 84
#define PARTITION_CRC_OFFSET 88
+#define MIN_PARTITION_ARRAY_SIZE 0x4000
+
#define PARTITION_ENTRY_LAST_LBA 40
#define ENTRY_SIZE 0x080
@@ -112,6 +115,25 @@
((unsigned long long)*(x+6) << 48) | \
((unsigned long long)*(x+7) << 56))
+#define GET_LONG(x) ((uint32_t)*(x) | \
+ ((uint32_t)*(x+1) << 8) | \
+ ((uint32_t)*(x+2) << 16) | \
+ ((uint32_t)*(x+3) << 24))
+
+#define PUT_LONG(x, y) *(x) = y & 0xff; \
+ *(x+1) = (y >> 8) & 0xff; \
+ *(x+2) = (y >> 16) & 0xff; \
+ *(x+3) = (y >> 24) & 0xff;
+
+#define PUT_LONG_LONG(x,y) *(x) =(y) & 0xff; \
+ *((x)+1) = (((y) >> 8) & 0xff); \
+ *((x)+2) = (((y) >> 16) & 0xff); \
+ *((x)+3) = (((y) >> 24) & 0xff); \
+ *((x)+4) = (((y) >> 32) & 0xff); \
+ *((x)+5) = (((y) >> 40) & 0xff); \
+ *((x)+6) = (((y) >> 48) & 0xff); \
+ *((x)+7) = (((y) >> 56) & 0xff);
+
/* Unified mbr and gpt entry types */
struct partition_entry
{
@@ -145,5 +167,15 @@
unsigned int * partition_entry_size,
unsigned int * header_size,
unsigned int * max_partition_count);
+
+unsigned int write_mbr(unsigned size, unsigned char *mbrImage,
+ struct mmc_boot_host *mmc_host,
+ struct mmc_boot_card *mmc_card);
+unsigned int write_gpt(unsigned size, unsigned char *gptImage,
+ struct mmc_boot_host *mmc_host,
+ struct mmc_boot_card *mmc_card);
+unsigned int write_partition(unsigned size, unsigned char* partition);
+
+
/* For Debugging */
void partition_dump(void);
diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index 6ca37d2..8836933 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -33,7 +33,7 @@
#include "mmc.h"
#include <partition_parser.h>
#include <platform/iomap.h>
-#include <platform/timer.h>
+#include <platform/timer.h>
#if MMC_BOOT_ADM
#include "adm.h"
@@ -2266,146 +2266,10 @@
return val;
}
-
-
-
-unsigned int mmc_write_mbr_in_blocks(unsigned size, unsigned char *mbrImage)
-{
- unsigned int dtype;
- unsigned int dfirstsec;
- unsigned int ebrSectorOffset;
- unsigned char *ebrImage;
- unsigned char *lastAddress;
- int idx, i;
- unsigned int ret;
-
- /* Write the first block */
- ret = mmc_write(0, MMC_BOOT_RD_BLOCK_LEN, (unsigned int *) mbrImage);
- if (ret)
- {
- dprintf(CRITICAL, "Failed to write mbr partition\n");
- goto end;
- }
- dprintf(SPEW, "write of first MBR block ok\n");
- /*
- Loop through the MBR table to see if there is an EBR.
- If found, then figure out where to write the first EBR
- */
- idx = TABLE_ENTRY_0;
- for (i = 0; i < 4; i++)
- {
- dtype = mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
- if (MBR_EBR_TYPE == dtype)
- {
- dprintf(SPEW, "EBR found.\n");
- break;
- }
- }
- if (MBR_EBR_TYPE != dtype)
- {
- dprintf(SPEW, "No EBR in this image\n");
- goto end;
- }
- /* EBR exists. Write each EBR block to mmc */
- ebrImage = mbrImage + MMC_BOOT_RD_BLOCK_LEN;
- ebrSectorOffset= GET_LWORD_FROM_BYTE(&mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_FIRST_SEC]);
- dfirstsec = 0;
- dprintf(SPEW, "first EBR to be written at sector 0x%X\n", dfirstsec);
- lastAddress = mbrImage + size;
- while (ebrImage < lastAddress)
- {
- dprintf(SPEW, "writing to 0x%X\n", (ebrSectorOffset + dfirstsec) * MMC_BOOT_RD_BLOCK_LEN);
- ret = mmc_write((ebrSectorOffset + dfirstsec) * MMC_BOOT_RD_BLOCK_LEN,
- MMC_BOOT_RD_BLOCK_LEN, (unsigned int *) ebrImage);
- if (ret)
- {
- dprintf(CRITICAL, "Failed to write EBR block to sector 0x%X", dfirstsec);
- goto end;
- }
- dfirstsec = GET_LWORD_FROM_BYTE(&ebrImage[TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
- ebrImage += MMC_BOOT_RD_BLOCK_LEN;
- }
- dprintf(INFO, "MBR written to mmc successfully");
-end:
- return ret;
-}
-
-
-
-/* Write the MBR/EBR to the MMC. */
-unsigned int mmc_write_mbr(unsigned size, unsigned char *mbrImage)
-{
- unsigned int ret;
-
- /* Verify that passed in block is a valid MBR */
- ret = partition_verify_mbr_signature(size, mbrImage);
- if (ret)
- {
- goto end;
- }
-
- /* Write the MBR/EBR to mmc */
- ret = mmc_write_mbr_in_blocks(size, mbrImage);
- if (ret)
- {
- dprintf(CRITICAL, "Failed to write MBR block to mmc.\n" );
- goto end;
- }
- /* Re-read the MBR partition into mbr table */
- ret = mmc_boot_read_mbr( &mmc_host, &mmc_card );
- if (ret)
- {
- dprintf(CRITICAL, "Failed to re-read mbr partition.\n");
- goto end;
- }
- partition_dump();
-end:
- return ret;
-}
-
-unsigned int mmc_write_partition(unsigned size, unsigned char* partition)
-{
- unsigned int ret = MMC_BOOT_E_INVAL;
- unsigned int partition_type;
-
- if (partition == 0)
- {
- dprintf(CRITICAL, "NULL partition\n");
- goto end;
- }
- ret = partition_get_type(size, partition, &partition_type);
- if (ret != MMC_BOOT_E_SUCCESS)
- {
- goto end;
- }
- switch (partition_type)
- {
- case PARTITION_TYPE_MBR:
- dprintf(INFO, "Writing MBR partition\n");
- ret = mmc_write_mbr(size, partition);
- break;
- case PARTITION_TYPE_GPT:
- dprintf(INFO, "Writing GPT partition\n");
- dprintf(CRITICAL, "Flash of GPT not implemented\n");
- ret = MMC_BOOT_E_INVAL;
- break;
- case PARTITION_TYPE_GPT_BACKUP:
- dprintf(INFO, "Writing GPT backup partition\n");
- dprintf(CRITICAL, "Flash of GPT backup not implemented\n");
- ret = MMC_BOOT_E_INVAL;
- break;
- default:
- dprintf(CRITICAL, "Invalid partition\n");
- ret = MMC_BOOT_E_INVAL;
- goto end;
- }
-end:
- return ret;
-}
-
/*
* MMC read function
*/
+
unsigned int mmc_read (unsigned long long data_addr, unsigned int* out, unsigned int data_len)
{
int val = 0;
@@ -2649,8 +2513,7 @@
memset(wp_status_buf, 0, 8);
rc = mmc_boot_read_reg(card, 8, CMD31_SEND_WRITE_PROT_TYPE, sector,
- (unsigned int *) wp_status_buf);
-
+ (unsigned int *) wp_status_buf);
return rc;
}
@@ -2852,6 +2715,7 @@
} while(1);
return mmc_ret;
}
+
/*
* CMD35_ERASE_GROUP_START
@@ -3024,7 +2888,7 @@
if(size % erase_grp_size)
{
- dprintf(CRITICAL, "Overflow beyond ERASE_GROUP_SIZE:%llu \n",
+ dprintf(CRITICAL, "Overflow beyond ERASE_GROUP_SIZE:%llu\n",
(size % erase_grp_size));
}
@@ -3063,5 +2927,15 @@
}
dprintf(SPEW, "ERASE SUCCESSFULLY COMPLETED\n");
return MMC_BOOT_E_SUCCESS;
+}
+
+struct mmc_boot_host* get_mmc_host ( void )
+{
+ return &mmc_host;
+}
+
+struct mmc_boot_card* get_mmc_card( void )
+{
+ return &mmc_card;
}
diff --git a/platform/msm_shared/partition_parser.c b/platform/msm_shared/partition_parser.c
index e99d2ee..e131185 100644
--- a/platform/msm_shared/partition_parser.c
+++ b/platform/msm_shared/partition_parser.c
@@ -72,7 +72,7 @@
unsigned int mmc_boot_read_mbr( struct mmc_boot_host * mmc_host,
struct mmc_boot_card * mmc_card)
{
- unsigned char buffer[MMC_BOOT_RD_BLOCK_LEN];
+ unsigned char buffer[BLOCK_SIZE];
unsigned int dtype;
unsigned int dfirstsec;
unsigned int EBR_first_sec;
@@ -81,17 +81,17 @@
int idx, i;
/* Print out the MBR first */
- ret = mmc_boot_read_from_card( mmc_host, mmc_card, 0, \
- MMC_BOOT_RD_BLOCK_LEN, \
+ ret = mmc_boot_read_from_card( mmc_host, mmc_card, 0,
+ BLOCK_SIZE,
(unsigned int *)buffer);
if (ret)
{
- dprintf(CRITICAL, "Could not read partition from mmc");
+ dprintf(CRITICAL, "Could not read partition from mmc\n");
return ret;
}
/* Check to see if signature exists */
- ret = partition_verify_mbr_signature(MMC_BOOT_RD_BLOCK_LEN, buffer);
+ ret = partition_verify_mbr_signature(BLOCK_SIZE, buffer);
if (ret)
{
return ret;
@@ -112,18 +112,18 @@
return ret;
}
partition_entries[partition_count].dtype = dtype;
- partition_entries[partition_count].attribute_flag = \
+ partition_entries[partition_count].attribute_flag =
buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
- partition_entries[partition_count].first_lba = \
- GET_LWORD_FROM_BYTE(&buffer[idx + \
- i * TABLE_ENTRY_SIZE + \
+ partition_entries[partition_count].first_lba =
+ GET_LWORD_FROM_BYTE(&buffer[idx +
+ i * TABLE_ENTRY_SIZE +
OFFSET_FIRST_SEC]);
- partition_entries[partition_count].size = \
- GET_LWORD_FROM_BYTE(&buffer[idx + \
- i * TABLE_ENTRY_SIZE + \
+ partition_entries[partition_count].size =
+ GET_LWORD_FROM_BYTE(&buffer[idx +
+ i * TABLE_ENTRY_SIZE +
OFFSET_SIZE]);
dfirstsec = partition_entries[partition_count].first_lba;
- mbr_fill_name(&partition_entries[partition_count], \
+ mbr_fill_name(&partition_entries[partition_count],
partition_entries[partition_count].dtype);
partition_count++;
if (partition_count == NUM_PARTITIONS)
@@ -139,9 +139,9 @@
EBR_first_sec = dfirstsec;
EBR_current_sec = dfirstsec;
- ret = mmc_boot_read_from_card( mmc_host, mmc_card, \
- (EBR_first_sec * 512), \
- MMC_BOOT_RD_BLOCK_LEN, \
+ ret = mmc_boot_read_from_card( mmc_host, mmc_card,
+ (EBR_first_sec * 512),
+ BLOCK_SIZE,
(unsigned int *)buffer);
if (ret)
{
@@ -150,24 +150,24 @@
/* Loop to parse the EBR */
for (i = 0;; i++)
{
- ret = partition_verify_mbr_signature(MMC_BOOT_RD_BLOCK_LEN, buffer);
+ ret = partition_verify_mbr_signature(BLOCK_SIZE, buffer);
if (ret)
{
ret = MMC_BOOT_E_SUCCESS;
break;
}
- partition_entries[partition_count].attribute_flag = \
+ partition_entries[partition_count].attribute_flag =
buffer[TABLE_ENTRY_0 + OFFSET_STATUS];
- partition_entries[partition_count].dtype = \
+ partition_entries[partition_count].dtype =
buffer[TABLE_ENTRY_0 + OFFSET_TYPE];
- partition_entries[partition_count].first_lba = \
- GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + \
- OFFSET_FIRST_SEC]) + \
+ partition_entries[partition_count].first_lba =
+ GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 +
+ OFFSET_FIRST_SEC]) +
EBR_current_sec;
- partition_entries[partition_count].size = \
- GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + \
+ partition_entries[partition_count].size =
+ GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 +
OFFSET_SIZE]);
- mbr_fill_name(&(partition_entries[partition_count]), \
+ mbr_fill_name(&(partition_entries[partition_count]),
partition_entries[partition_count].dtype);
partition_count++;
if (partition_count == NUM_PARTITIONS)
@@ -183,9 +183,9 @@
/* More EBR to follow - read in the next EBR sector */
dprintf(SPEW, "Reading EBR block from 0x%X\n", EBR_first_sec
+ dfirstsec);
- ret = mmc_boot_read_from_card( mmc_host, mmc_card, \
- ((EBR_first_sec + dfirstsec) * 512), \
- MMC_BOOT_RD_BLOCK_LEN, \
+ ret = mmc_boot_read_from_card( mmc_host, mmc_card,
+ ((EBR_first_sec + dfirstsec) * 512),
+ BLOCK_SIZE,
(unsigned int *)buffer);
if (ret)
{
@@ -209,36 +209,35 @@
unsigned long long backup_header_lba;
unsigned int max_partition_count = 0;
unsigned int partition_entry_size;
- unsigned char data[MMC_BOOT_RD_BLOCK_LEN];
+ unsigned char data[BLOCK_SIZE];
unsigned int i = 0; /* Counter for each 512 block */
unsigned int j = 0; /* Counter for each 128 entry in the 512 block */
unsigned int n = 0; /* Counter for UTF-16 -> 8 conversion */
unsigned char UTF16_name[MAX_GPT_NAME_SIZE];
/* LBA of first partition -- 1 Block after Protected MBR + 1 for PT */
unsigned long long partition_0 = 2;
+ partition_count = 0;
/* Print out the GPT first */
- ret = mmc_boot_read_from_card( mmc_host, mmc_card, \
- PROTECTIVE_MBR_SIZE, \
- MMC_BOOT_RD_BLOCK_LEN, \
+ ret = mmc_boot_read_from_card( mmc_host, mmc_card,
+ PROTECTIVE_MBR_SIZE,
+ BLOCK_SIZE,
(unsigned int *)data);
-
if (ret)
dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
ret = partition_parse_gpt_header(data, &first_usable_lba,
&partition_entry_size, &header_size,
&max_partition_count);
-
if (ret)
{
dprintf(INFO, "GPT: (WARNING) Primary signature invalid\n" );
/* Check the backup gpt */
backup_header_lba = GET_LLWORD_FROM_BYTE(&data[BACKUP_HEADER_OFFSET]);
- ret = mmc_boot_read_from_card( mmc_host, mmc_card, \
- (backup_header_lba * BLOCK_SIZE), \
- MMC_BOOT_RD_BLOCK_LEN, \
+ ret = mmc_boot_read_from_card( mmc_host, mmc_card,
+ (backup_header_lba * BLOCK_SIZE),
+ BLOCK_SIZE,
(unsigned int *)data);
if (ret)
@@ -263,8 +262,8 @@
{
ret = mmc_boot_read_from_card( mmc_host, mmc_card,
(partition_0 * BLOCK_SIZE) +
- (i * MMC_BOOT_RD_BLOCK_LEN),
- MMC_BOOT_RD_BLOCK_LEN,
+ (i * BLOCK_SIZE),
+ BLOCK_SIZE,
(uint32_t *)data);
if (ret)
@@ -315,10 +314,432 @@
partition_count++;
}
}
-
return ret;
}
+static unsigned int write_mbr_in_blocks(unsigned size, unsigned char *mbrImage)
+{
+ unsigned int dtype;
+ unsigned int dfirstsec;
+ unsigned int ebrSectorOffset;
+ unsigned char *ebrImage;
+ unsigned char *lastAddress;
+ int idx, i;
+ unsigned int ret;
+
+ /* Write the first block */
+ ret = mmc_write(0, BLOCK_SIZE, (unsigned int *) mbrImage);
+ if (ret)
+ {
+ dprintf(CRITICAL, "Failed to write mbr partition\n");
+ goto end;
+ }
+ dprintf(SPEW, "write of first MBR block ok\n");
+ /*
+ Loop through the MBR table to see if there is an EBR.
+ If found, then figure out where to write the first EBR
+ */
+ idx = TABLE_ENTRY_0;
+ for (i = 0; i < 4; i++)
+ {
+ dtype = mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
+ if (MBR_EBR_TYPE == dtype)
+ {
+ dprintf(SPEW, "EBR found.\n");
+ break;
+ }
+ }
+ if (MBR_EBR_TYPE != dtype)
+ {
+ dprintf(SPEW, "No EBR in this image\n");
+ goto end;
+ }
+ /* EBR exists. Write each EBR block to mmc */
+ ebrImage = mbrImage + BLOCK_SIZE;
+ ebrSectorOffset= GET_LWORD_FROM_BYTE(&mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_FIRST_SEC]);
+ dfirstsec = 0;
+ dprintf(SPEW, "first EBR to be written at sector 0x%X\n", dfirstsec);
+ lastAddress = mbrImage + size;
+ while (ebrImage < lastAddress)
+ {
+ dprintf(SPEW, "writing to 0x%X\n", (ebrSectorOffset + dfirstsec) * BLOCK_SIZE);
+ ret = mmc_write((ebrSectorOffset + dfirstsec) * BLOCK_SIZE,
+ BLOCK_SIZE, (unsigned int *) ebrImage);
+ if (ret)
+ {
+ dprintf(CRITICAL, "Failed to write EBR block to sector 0x%X\n", dfirstsec);
+ goto end;
+ }
+ dfirstsec = GET_LWORD_FROM_BYTE(&ebrImage[TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
+ ebrImage += BLOCK_SIZE;
+ }
+ dprintf(INFO, "MBR written to mmc successfully\n");
+end:
+ return ret;
+}
+
+/* Write the MBR/EBR to the MMC. */
+unsigned int write_mbr(unsigned size, unsigned char *mbrImage,
+ struct mmc_boot_host * mmc_host,
+ struct mmc_boot_card * mmc_card)
+{
+ unsigned int ret;
+
+ /* Verify that passed in block is a valid MBR */
+ ret = partition_verify_mbr_signature(size, mbrImage);
+ if (ret)
+ {
+ goto end;
+ }
+
+ /* Write the MBR/EBR to mmc */
+ ret = write_mbr_in_blocks(size, mbrImage);
+ if (ret)
+ {
+ dprintf(CRITICAL, "Failed to write MBR block to mmc.\n" );
+ goto end;
+ }
+ /* Re-read the MBR partition into mbr table */
+ ret = mmc_boot_read_mbr( mmc_host, mmc_card );
+ if (ret)
+ {
+ dprintf(CRITICAL, "Failed to re-read mbr partition.\n");
+ goto end;
+ }
+ partition_dump();
+end:
+ return ret;
+}
+
+/*
+ * A8h reflected is 15h, i.e. 10101000 <--> 00010101
+*/
+int reflect(int data, int len)
+{
+ int ref = 0;
+
+ for(int i=0; i < len; i++) {
+ if(data & 0x1) {
+ ref |= (1 << ((len - 1) - i));
+ }
+ data = (data >> 1);
+ }
+
+ return ref;
+}
+
+/*
+* Function to calculate the CRC32
+*/
+unsigned int calculate_crc32(unsigned char *buffer, int len)
+{
+ int byte_length = 8; /*length of unit (i.e. byte)*/
+ int msb = 0;
+ int polynomial = 0x104C11DB7; /* IEEE 32bit polynomial*/
+ unsigned int regs = 0xFFFFFFFF; /* init to all ones */
+ int regs_mask = 0xFFFFFFFF; /* ensure only 32 bit answer */
+ int regs_msb = 0;
+ unsigned int reflected_regs;
+
+ for( int i=0; i < len; i++)
+ {
+ int data_byte = buffer[i];
+ data_byte = reflect(data_byte,8);
+ for(int j=0; j < byte_length; j++)
+ {
+ msb = data_byte >> (byte_length-1); /* get MSB */
+ msb &= 1; /* ensure just 1 bit */
+ regs_msb = (regs>>31) & 1; /* MSB of regs */
+ regs = regs<<1; /* shift regs for CRC-CCITT */
+ if(regs_msb ^ msb) /* MSB is a 1 */
+ {
+ regs = regs ^ polynomial; /* XOR with generator poly */
+ }
+ regs = regs & regs_mask; /* Mask off excess upper bits */
+ data_byte <<= 1; /* get to next bit */
+ }
+ }
+ regs = regs & regs_mask;
+ reflected_regs = reflect(regs, 32) ^ 0xFFFFFFFF;
+
+ return reflected_regs;
+}
+
+/*
+ * Write the GPT Partition Entry Array to the MMC.
+ */
+static unsigned int write_gpt_partition_array(unsigned char * header,
+ unsigned int partition_array_start,
+ unsigned int array_size)
+{
+ unsigned int ret = MMC_BOOT_E_INVAL;
+ unsigned long long partition_entry_lba;
+ unsigned long long partition_entry_array_start_location;
+
+ partition_entry_lba = GET_LLWORD_FROM_BYTE(&header[PARTITION_ENTRIES_OFFSET]);
+ partition_entry_array_start_location = partition_entry_lba * BLOCK_SIZE;
+
+ ret = mmc_write( partition_entry_array_start_location, array_size,
+ (unsigned int *) partition_array_start);
+ if( ret )
+ {
+ dprintf(CRITICAL, "GPT: FAILED to write the partition entry array\n");
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static void patch_gpt(unsigned char *gptImage,
+ struct mmc_boot_card * mmc_card,
+ unsigned int array_size,
+ unsigned int max_part_count,
+ unsigned int part_entry_size)
+{
+ unsigned int partition_entry_array_start;
+ unsigned char * primary_gpt_header;
+ unsigned char * secondary_gpt_header;
+ unsigned int offset;
+ unsigned long long card_size_sec;
+ int total_part=0;
+ unsigned int last_part_offset;
+ unsigned int crc_value;
+
+ /* Get size of MMC */
+ card_size_sec = (mmc_card->capacity)/512;
+ /* Working around cap at 4GB */
+ if( card_size_sec == 0 )
+ {
+ card_size_sec = 4*1024*1024*2 - 1;
+ }
+
+ /* Patching primary header */
+ primary_gpt_header = (gptImage + PROTECTIVE_MBR_SIZE);
+ PUT_LONG_LONG( primary_gpt_header + BACKUP_HEADER_OFFSET,
+ ((long long)(card_size_sec - 1)) );
+ PUT_LONG_LONG( primary_gpt_header + LAST_USABLE_LBA_OFFSET,
+ ((long long)(card_size_sec - 34)) );
+
+ /* Patching backup GPT */
+ offset = (2 * array_size );
+ secondary_gpt_header = offset + BLOCK_SIZE + primary_gpt_header;
+ PUT_LONG_LONG( secondary_gpt_header + PRIMARY_HEADER_OFFSET,
+ ((long long)(card_size_sec - 1)) );
+ PUT_LONG_LONG( secondary_gpt_header + LAST_USABLE_LBA_OFFSET,
+ ((long long)(card_size_sec - 34)) );
+ PUT_LONG_LONG( secondary_gpt_header + PARTITION_ENTRIES_OFFSET,
+ ((long long)(card_size_sec - 33)) );
+
+ /* Find last partition */
+ while(*(primary_gpt_header +BLOCK_SIZE+ total_part* ENTRY_SIZE)!= 0)
+ {
+ total_part++;
+ }
+
+ /* Patching last partition */
+ last_part_offset = (total_part-1)*ENTRY_SIZE +
+ PARTITION_ENTRY_LAST_LBA;
+ PUT_LONG_LONG( primary_gpt_header + BLOCK_SIZE + last_part_offset,
+ (long long)(card_size_sec - 34) );
+ PUT_LONG_LONG( primary_gpt_header + BLOCK_SIZE + last_part_offset+
+ array_size,
+ (long long)(card_size_sec - 34) );
+
+ /* Updating CRC of the Partition entry array in both headers */
+ partition_entry_array_start = primary_gpt_header + BLOCK_SIZE;
+ crc_value = calculate_crc32( partition_entry_array_start,
+ max_part_count * part_entry_size);
+ PUT_LONG ( primary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
+
+ crc_value = calculate_crc32( partition_entry_array_start + array_size,
+ max_part_count * part_entry_size);
+ PUT_LONG ( secondary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
+
+ /* Clearing CRC fields to calculate */
+ PUT_LONG ( primary_gpt_header + HEADER_CRC_OFFSET,0 );
+ crc_value = calculate_crc32( primary_gpt_header, 92);
+ PUT_LONG ( primary_gpt_header + HEADER_CRC_OFFSET, crc_value);
+
+ PUT_LONG ( secondary_gpt_header + HEADER_CRC_OFFSET, 0);
+ crc_value = (calculate_crc32( secondary_gpt_header, 92));
+ PUT_LONG ( secondary_gpt_header + HEADER_CRC_OFFSET, crc_value);
+
+}
+
+/*
+ * Write the GPT to the MMC.
+ */
+unsigned int write_gpt(unsigned size, unsigned char *gptImage,
+ struct mmc_boot_host * mmc_host,
+ struct mmc_boot_card * mmc_card)
+{
+ unsigned int ret = MMC_BOOT_E_INVAL;
+ unsigned int header_size;
+ unsigned long long first_usable_lba;
+ unsigned long long backup_header_lba;
+ unsigned int max_partition_count = 0;
+ unsigned int partition_entry_size;
+ unsigned int partition_entry_array_start;
+ unsigned char * primary_gpt_header;
+ unsigned char * secondary_gpt_header;
+ unsigned int offset;
+ unsigned int partition_entry_array_size;
+ unsigned long long primary_header_location; /* address on the emmc card */
+ unsigned long long secondary_header_location; /* address on the emmc card */
+
+ /* Verify that passed block has a valid GPT primary header */
+ primary_gpt_header = (gptImage + PROTECTIVE_MBR_SIZE);
+ ret = partition_parse_gpt_header(primary_gpt_header, &first_usable_lba,
+ &partition_entry_size, &header_size,
+ &max_partition_count);
+ if( ret )
+ {
+ dprintf(CRITICAL, "GPT: Primary signature invalid cannot write GPT\n");
+ goto end;
+ }
+
+ /* Verify that passed block has a valid backup GPT HEADER */
+ partition_entry_array_size = partition_entry_size * max_partition_count;
+ if(partition_entry_array_size < MIN_PARTITION_ARRAY_SIZE)
+ {
+ partition_entry_array_size = MIN_PARTITION_ARRAY_SIZE;
+ }
+ offset = (2 * partition_entry_array_size );
+ secondary_gpt_header = offset + BLOCK_SIZE + primary_gpt_header;
+ ret = partition_parse_gpt_header ( secondary_gpt_header , &first_usable_lba,
+ &partition_entry_size, &header_size,
+ &max_partition_count);
+ if( ret )
+ {
+ dprintf(CRITICAL, "GPT: Backup signature invalid cannot write GPT\n");
+ goto end;
+ }
+
+ /* Patching the primary and the backup header of the GPT table */
+ patch_gpt(gptImage ,mmc_card ,partition_entry_array_size ,
+ max_partition_count, partition_entry_size);
+
+ /* Erasing the eMMC card before writing */
+ ret = mmc_erase_card (0x00000000 , mmc_card->capacity);
+ if(ret)
+ {
+ dprintf(CRITICAL , "Failed to erase the eMMC card\n");
+ goto end;
+ }
+
+ /* Writing protective MBR*/
+ ret = mmc_write(0 ,PROTECTIVE_MBR_SIZE ,(unsigned int *) gptImage);
+ if(ret)
+ {
+ dprintf(CRITICAL, "Failed to write Protective MBR\n");
+ goto end;
+ }
+ /* Writing the primary GPT header */
+ primary_header_location = PROTECTIVE_MBR_SIZE;
+ ret = mmc_write(primary_header_location , BLOCK_SIZE ,
+ (unsigned int *)primary_gpt_header);
+ if (ret)
+ {
+ dprintf(CRITICAL, "Failed to write GPT header\n");
+ goto end;
+ }
+
+ /* Writing the backup GPT header */
+ backup_header_lba = GET_LLWORD_FROM_BYTE
+ (&primary_gpt_header[BACKUP_HEADER_OFFSET]);
+ secondary_header_location = backup_header_lba * BLOCK_SIZE;
+ ret = mmc_write(secondary_header_location, BLOCK_SIZE ,
+ (unsigned int *)secondary_gpt_header);
+ if (ret)
+ {
+ dprintf(CRITICAL, "Failed to write GPT backup header\n");
+ goto end;
+ }
+
+ /* Writing the partition entries array for the primary header */
+ partition_entry_array_start = primary_gpt_header + BLOCK_SIZE;
+ ret =write_gpt_partition_array( primary_gpt_header ,
+ partition_entry_array_start,
+ partition_entry_array_size);
+ if( ret )
+ {
+ dprintf(CRITICAL, "GPT: Could not write GPT Partition entries array\n");
+ goto end;
+ }
+
+ /*Writing the partition entries array for the backup header */
+ partition_entry_array_start =primary_gpt_header + BLOCK_SIZE+
+ partition_entry_array_size;
+ ret = write_gpt_partition_array( secondary_gpt_header ,
+ partition_entry_array_start,
+ partition_entry_array_size);
+ if( ret )
+ {
+ dprintf(CRITICAL, "GPT: Could not write GPT Partition entries array\n");
+ goto end;
+ }
+
+ /* Re-read the GPT partition table */
+ dprintf(INFO, "Re-reading the GPT Partition Table\n");
+ ret = mmc_boot_read_gpt( mmc_host, mmc_card);
+ if( ret )
+ {
+ dprintf( CRITICAL , "GPT: Failure to re- read the GPT Partition table\n");
+ goto end;
+ }
+ partition_dump();
+ dprintf( CRITICAL, "GPT: Partition Table written\n");
+ memset(primary_gpt_header , 0x00 , size);
+
+end:
+ return ret;
+}
+
+unsigned int write_partition(unsigned size, unsigned char* partition)
+{
+ unsigned int ret = MMC_BOOT_E_INVAL;
+ unsigned int partition_type;
+ struct mmc_boot_host* mmc_host;
+ struct mmc_boot_card* mmc_card;
+
+ if (partition == 0)
+ {
+ dprintf(CRITICAL, "NULL partition\n");
+ goto end;
+ }
+
+ ret = partition_get_type(size, partition, &partition_type);
+ if (ret != MMC_BOOT_E_SUCCESS)
+ {
+ goto end;
+ }
+
+ mmc_host = get_mmc_host();
+ mmc_card = get_mmc_card();
+
+ switch (partition_type)
+ {
+ case PARTITION_TYPE_MBR:
+ dprintf(INFO, "Writing MBR partition\n");
+ ret = write_mbr(size, partition, mmc_host, mmc_card);
+ break;
+
+ case PARTITION_TYPE_GPT:
+ dprintf(INFO, "Writing GPT partition\n");
+ ret = write_gpt(size, partition, mmc_host, mmc_card);
+ dprintf( CRITICAL, "Re-Flash all the partitions\n");
+ break;
+
+ default:
+ dprintf(CRITICAL, "Invalid partition\n");
+ ret = MMC_BOOT_E_INVAL;
+ goto end;
+ }
+
+end:
+ return ret;
+}
/*
* Fill name for android partition found.
*/
@@ -409,7 +830,7 @@
if (index == INVALID_PTN)
return 0;
else{
- return partition_entries[index].size * MMC_BOOT_RD_BLOCK_LEN;
+ return partition_entries[index].size * BLOCK_SIZE;
}
}
@@ -419,7 +840,7 @@
if (index == INVALID_PTN)
return 0;
else{
- return partition_entries[index].first_lba * MMC_BOOT_RD_BLOCK_LEN;
+ return partition_entries[index].first_lba * BLOCK_SIZE;
}
}
@@ -445,10 +866,10 @@
return MMC_BOOT_E_FAILURE;
}
/* Check to see if signature exists */
- if ((buffer[TABLE_SIGNATURE] != MMC_MBR_SIGNATURE_BYTE_0) || \
+ if ((buffer[TABLE_SIGNATURE] != MMC_MBR_SIGNATURE_BYTE_0) ||
(buffer[TABLE_SIGNATURE + 1] != MMC_MBR_SIGNATURE_BYTE_1))
{
- dprintf(CRITICAL, "MBR signature does not match. \n" );
+ dprintf(CRITICAL, "MBR signature does not match.\n" );
return MMC_BOOT_E_FAILURE;
}
return MMC_BOOT_E_SUCCESS;
@@ -524,8 +945,8 @@
unsigned int * max_partition_count)
{
/* Check GPT Signature */
- if( ((uint32_t *)buffer)[0] != GPT_SIGNATURE_2 ||
- ((uint32_t *)buffer)[1] != GPT_SIGNATURE_1 )
+ if( ((uint32_t *) buffer)[0] != GPT_SIGNATURE_2 ||
+ ((uint32_t *) buffer)[1] != GPT_SIGNATURE_1 )
return 1;
*header_size = GET_LWORD_FROM_BYTE(&buffer[HEADER_SIZE_OFFSET]);