blob: e131185b39327c1051512d89355ae8240670f464 [file] [log] [blame]
Kinson Chik66552a82011-03-29 15:59:06 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdlib.h>
30#include <string.h>
31#include "mmc.h"
32#include "partition_parser.h"
33
Kinson Chikf1a43512011-07-14 11:28:39 -070034char *ext3_partitions[] = {"system", "userdata", "persist", "cache", "tombstones"};
35char *vfat_partitions[] = {"modem", "mdm", "NONE"};
36unsigned int ext3_count = 0;
37unsigned int vfat_count = 0;
38
39struct partition_entry partition_entries[NUM_PARTITIONS];
40unsigned gpt_partitions_exist = 0;
41unsigned partition_count = 0;
42
43//TODO: Remove the dependency of mmc in these functions
44unsigned int partition_read_table( struct mmc_boot_host * mmc_host,
45 struct mmc_boot_card * mmc_card)
46{
47 unsigned int ret;
48
49 /* Read MBR of the card */
50 ret = mmc_boot_read_mbr( mmc_host, mmc_card );
51 if( ret != MMC_BOOT_E_SUCCESS )
52 {
53 dprintf(CRITICAL, "MMC Boot: MBR read failed!\n" );
54 return MMC_BOOT_E_FAILURE;
55 }
56
57 /* Read GPT of the card if exist */
58 if(gpt_partitions_exist){
59 ret = mmc_boot_read_gpt(mmc_host, mmc_card);
60 if( ret != MMC_BOOT_E_SUCCESS )
61 {
62 dprintf(CRITICAL, "MMC Boot: GPT read failed!\n" );
63 return MMC_BOOT_E_FAILURE;
64 }
65 }
66 return MMC_BOOT_E_SUCCESS;
67}
68
69/*
70 * Read MBR from MMC card and fill partition table.
71 */
72unsigned int mmc_boot_read_mbr( struct mmc_boot_host * mmc_host,
73 struct mmc_boot_card * mmc_card)
74{
Neeti Desai5f26aff2011-09-30 10:27:40 -070075 unsigned char buffer[BLOCK_SIZE];
Kinson Chikf1a43512011-07-14 11:28:39 -070076 unsigned int dtype;
77 unsigned int dfirstsec;
78 unsigned int EBR_first_sec;
79 unsigned int EBR_current_sec;
80 int ret = MMC_BOOT_E_SUCCESS;
81 int idx, i;
82
83 /* Print out the MBR first */
Neeti Desai5f26aff2011-09-30 10:27:40 -070084 ret = mmc_boot_read_from_card( mmc_host, mmc_card, 0,
85 BLOCK_SIZE,
Kinson Chikf1a43512011-07-14 11:28:39 -070086 (unsigned int *)buffer);
87 if (ret)
88 {
Neeti Desai5f26aff2011-09-30 10:27:40 -070089 dprintf(CRITICAL, "Could not read partition from mmc\n");
Kinson Chikf1a43512011-07-14 11:28:39 -070090 return ret;
91 }
92
93 /* Check to see if signature exists */
Neeti Desai5f26aff2011-09-30 10:27:40 -070094 ret = partition_verify_mbr_signature(BLOCK_SIZE, buffer);
Kinson Chikf1a43512011-07-14 11:28:39 -070095 if (ret)
96 {
97 return ret;
98 }
99
100 /*
101 * Process each of the four partitions in the MBR by reading the table
102 * information into our mbr table.
103 */
104 partition_count = 0;
105 idx = TABLE_ENTRY_0;
106 for (i = 0; i < 4; i++)
107 {
108 /* Type 0xEE indicates end of MBR and GPT partitions exist */
109 dtype = buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
110 if (dtype == MBR_PROTECTED_TYPE){
111 gpt_partitions_exist = 1;
112 return ret;
113 }
114 partition_entries[partition_count].dtype = dtype;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700115 partition_entries[partition_count].attribute_flag =
Kinson Chikf1a43512011-07-14 11:28:39 -0700116 buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
Neeti Desai5f26aff2011-09-30 10:27:40 -0700117 partition_entries[partition_count].first_lba =
118 GET_LWORD_FROM_BYTE(&buffer[idx +
119 i * TABLE_ENTRY_SIZE +
Kinson Chikf1a43512011-07-14 11:28:39 -0700120 OFFSET_FIRST_SEC]);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700121 partition_entries[partition_count].size =
122 GET_LWORD_FROM_BYTE(&buffer[idx +
123 i * TABLE_ENTRY_SIZE +
Kinson Chikf1a43512011-07-14 11:28:39 -0700124 OFFSET_SIZE]);
125 dfirstsec = partition_entries[partition_count].first_lba;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700126 mbr_fill_name(&partition_entries[partition_count],
Kinson Chikf1a43512011-07-14 11:28:39 -0700127 partition_entries[partition_count].dtype);
128 partition_count++;
129 if (partition_count == NUM_PARTITIONS)
130 return ret;
131 }
132
133 /* See if the last partition is EBR, if not, parsing is done */
134 if (dtype != MBR_EBR_TYPE)
135 {
136 return ret;
137 }
138
139 EBR_first_sec = dfirstsec;
140 EBR_current_sec = dfirstsec;
141
Neeti Desai5f26aff2011-09-30 10:27:40 -0700142 ret = mmc_boot_read_from_card( mmc_host, mmc_card,
143 (EBR_first_sec * 512),
144 BLOCK_SIZE,
Kinson Chikf1a43512011-07-14 11:28:39 -0700145 (unsigned int *)buffer);
146 if (ret)
147 {
148 return ret;
149 }
150 /* Loop to parse the EBR */
151 for (i = 0;; i++)
152 {
Neeti Desai5f26aff2011-09-30 10:27:40 -0700153 ret = partition_verify_mbr_signature(BLOCK_SIZE, buffer);
Kinson Chikf1a43512011-07-14 11:28:39 -0700154 if (ret)
155 {
156 ret = MMC_BOOT_E_SUCCESS;
157 break;
158 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700159 partition_entries[partition_count].attribute_flag =
Kinson Chikf1a43512011-07-14 11:28:39 -0700160 buffer[TABLE_ENTRY_0 + OFFSET_STATUS];
Neeti Desai5f26aff2011-09-30 10:27:40 -0700161 partition_entries[partition_count].dtype =
Kinson Chikf1a43512011-07-14 11:28:39 -0700162 buffer[TABLE_ENTRY_0 + OFFSET_TYPE];
Neeti Desai5f26aff2011-09-30 10:27:40 -0700163 partition_entries[partition_count].first_lba =
164 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 +
165 OFFSET_FIRST_SEC]) +
Kinson Chikf1a43512011-07-14 11:28:39 -0700166 EBR_current_sec;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700167 partition_entries[partition_count].size =
168 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 +
Kinson Chikf1a43512011-07-14 11:28:39 -0700169 OFFSET_SIZE]);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700170 mbr_fill_name(&(partition_entries[partition_count]),
Kinson Chikf1a43512011-07-14 11:28:39 -0700171 partition_entries[partition_count].dtype);
172 partition_count++;
173 if (partition_count == NUM_PARTITIONS)
174 return ret;
175
176 dfirstsec =
177 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
178 if(dfirstsec == 0)
179 {
180 /* Getting to the end of the EBR tables */
181 break;
182 }
183 /* More EBR to follow - read in the next EBR sector */
184 dprintf(SPEW, "Reading EBR block from 0x%X\n", EBR_first_sec
185 + dfirstsec);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700186 ret = mmc_boot_read_from_card( mmc_host, mmc_card,
187 ((EBR_first_sec + dfirstsec) * 512),
188 BLOCK_SIZE,
Kinson Chikf1a43512011-07-14 11:28:39 -0700189 (unsigned int *)buffer);
190 if (ret)
191 {
192 return ret;
193 }
194 EBR_current_sec = EBR_first_sec + dfirstsec;
195 }
196 return ret;
197}
Kinson Chik66552a82011-03-29 15:59:06 -0700198
199/*
200 * Read GPT from MMC and fill partition table
201 */
Kinson Chikf1a43512011-07-14 11:28:39 -0700202unsigned int mmc_boot_read_gpt( struct mmc_boot_host * mmc_host,
203 struct mmc_boot_card * mmc_card)
204{
Kinson Chik66552a82011-03-29 15:59:06 -0700205
Kinson Chikf1a43512011-07-14 11:28:39 -0700206 int ret = MMC_BOOT_E_SUCCESS;
207 unsigned int header_size;
208 unsigned long long first_usable_lba;
Kinson Chik4d7444f2011-09-13 15:48:51 -0700209 unsigned long long backup_header_lba;
210 unsigned int max_partition_count = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700211 unsigned int partition_entry_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700212 unsigned char data[BLOCK_SIZE];
Kinson Chikf1a43512011-07-14 11:28:39 -0700213 unsigned int i = 0; /* Counter for each 512 block */
214 unsigned int j = 0; /* Counter for each 128 entry in the 512 block */
215 unsigned int n = 0; /* Counter for UTF-16 -> 8 conversion */
216 unsigned char UTF16_name[MAX_GPT_NAME_SIZE];
Kinson Chik4d7444f2011-09-13 15:48:51 -0700217 /* LBA of first partition -- 1 Block after Protected MBR + 1 for PT */
218 unsigned long long partition_0 = 2;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700219 partition_count = 0;
Kinson Chik66552a82011-03-29 15:59:06 -0700220
221 /* Print out the GPT first */
Neeti Desai5f26aff2011-09-30 10:27:40 -0700222 ret = mmc_boot_read_from_card( mmc_host, mmc_card,
223 PROTECTIVE_MBR_SIZE,
224 BLOCK_SIZE,
Kinson Chikf1a43512011-07-14 11:28:39 -0700225 (unsigned int *)data);
Kinson Chik4d7444f2011-09-13 15:48:51 -0700226 if (ret)
227 dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
Kinson Chik66552a82011-03-29 15:59:06 -0700228
Kinson Chik4d7444f2011-09-13 15:48:51 -0700229 ret = partition_parse_gpt_header(data, &first_usable_lba,
230 &partition_entry_size, &header_size,
231 &max_partition_count);
Kinson Chik4d7444f2011-09-13 15:48:51 -0700232 if (ret)
233 {
234 dprintf(INFO, "GPT: (WARNING) Primary signature invalid\n" );
235
236 /* Check the backup gpt */
237 backup_header_lba = GET_LLWORD_FROM_BYTE(&data[BACKUP_HEADER_OFFSET]);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700238 ret = mmc_boot_read_from_card( mmc_host, mmc_card,
239 (backup_header_lba * BLOCK_SIZE),
240 BLOCK_SIZE,
Kinson Chik4d7444f2011-09-13 15:48:51 -0700241 (unsigned int *)data);
242
243 if (ret)
244 {
245 dprintf(CRITICAL, "GPT: Could not read backup gpt from mmc\n");
246 return ret;
247 }
248
249 ret = partition_parse_gpt_header(data, &first_usable_lba,
250 &partition_entry_size, &header_size,
251 &max_partition_count);
252 if (ret)
253 {
254 dprintf(CRITICAL, "GPT: Primary and backup signatures invalid\n");
255 return ret;
256 }
257 partition_0 = backup_header_lba - (max_partition_count / 4);
258 }
Kinson Chik66552a82011-03-29 15:59:06 -0700259
260 /* Read GPT Entries */
Kinson Chikf1a43512011-07-14 11:28:39 -0700261 for(i = 0; i < (max_partition_count/4); i++)
Kinson Chik66552a82011-03-29 15:59:06 -0700262 {
263 ret = mmc_boot_read_from_card( mmc_host, mmc_card,
Kinson Chik4d7444f2011-09-13 15:48:51 -0700264 (partition_0 * BLOCK_SIZE) +
Neeti Desai5f26aff2011-09-30 10:27:40 -0700265 (i * BLOCK_SIZE),
266 BLOCK_SIZE,
Kinson Chik66552a82011-03-29 15:59:06 -0700267 (uint32_t *)data);
268
269 if (ret)
270 {
Kinson Chikf1a43512011-07-14 11:28:39 -0700271 dprintf(CRITICAL,
272 "GPT: mmc read card failed reading partition entries.\n" );
Kinson Chik66552a82011-03-29 15:59:06 -0700273 return ret;
274 }
275
276 for(j=0; j < 4; j++)
277 {
Kinson Chikf1a43512011-07-14 11:28:39 -0700278 memcpy(&(partition_entries[partition_count].type_guid),
279 &data[(j * partition_entry_size)],
280 PARTITION_TYPE_GUID_SIZE);
281 if (partition_entries[partition_count].type_guid[0] == 0x00 &&
282 partition_entries[partition_count].type_guid[1] == 0x00)
Kinson Chik66552a82011-03-29 15:59:06 -0700283 {
Kinson Chikf1a43512011-07-14 11:28:39 -0700284 i = max_partition_count;
Kinson Chik66552a82011-03-29 15:59:06 -0700285 break;
286 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700287 memcpy(&(partition_entries[partition_count].unique_partition_guid),
288 &data[(j * partition_entry_size) +
289 UNIQUE_GUID_OFFSET], UNIQUE_PARTITION_GUID_SIZE);
290 partition_entries[partition_count].first_lba =
291 GET_LLWORD_FROM_BYTE(&data[(j * partition_entry_size) +
292 FIRST_LBA_OFFSET]);
293 partition_entries[partition_count].last_lba =
294 GET_LLWORD_FROM_BYTE(&data[(j * partition_entry_size) +
295 LAST_LBA_OFFSET]);
296 partition_entries[partition_count].size =
297 partition_entries[partition_count].last_lba -
298 partition_entries[partition_count].first_lba;
299 partition_entries[partition_count].attribute_flag =
300 GET_LLWORD_FROM_BYTE(&data[(j * partition_entry_size) +
301 ATTRIBUTE_FLAG_OFFSET]);
Kinson Chik66552a82011-03-29 15:59:06 -0700302
Kinson Chikf1a43512011-07-14 11:28:39 -0700303 memset(&UTF16_name, 0x00, MAX_GPT_NAME_SIZE);
304 memcpy(UTF16_name, &data[(j * partition_entry_size) +
305 PARTITION_NAME_OFFSET],
306 MAX_GPT_NAME_SIZE);
307 /*
308 * Currently partition names in *.xml are UTF-8 and lowercase
309 * Only supporting english for now so removing 2nd byte of UTF-16
310 */
311 for(n = 0; n < MAX_GPT_NAME_SIZE/2; n++){
312 partition_entries[partition_count].name[n] = UTF16_name[n*2];
313 }
314 partition_count++;
Kinson Chik66552a82011-03-29 15:59:06 -0700315 }
316 }
317 return ret;
318}
319
Neeti Desai5f26aff2011-09-30 10:27:40 -0700320static unsigned int write_mbr_in_blocks(unsigned size, unsigned char *mbrImage)
321{
322 unsigned int dtype;
323 unsigned int dfirstsec;
324 unsigned int ebrSectorOffset;
325 unsigned char *ebrImage;
326 unsigned char *lastAddress;
327 int idx, i;
328 unsigned int ret;
329
330 /* Write the first block */
331 ret = mmc_write(0, BLOCK_SIZE, (unsigned int *) mbrImage);
332 if (ret)
333 {
334 dprintf(CRITICAL, "Failed to write mbr partition\n");
335 goto end;
336 }
337 dprintf(SPEW, "write of first MBR block ok\n");
338 /*
339 Loop through the MBR table to see if there is an EBR.
340 If found, then figure out where to write the first EBR
341 */
342 idx = TABLE_ENTRY_0;
343 for (i = 0; i < 4; i++)
344 {
345 dtype = mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
346 if (MBR_EBR_TYPE == dtype)
347 {
348 dprintf(SPEW, "EBR found.\n");
349 break;
350 }
351 }
352 if (MBR_EBR_TYPE != dtype)
353 {
354 dprintf(SPEW, "No EBR in this image\n");
355 goto end;
356 }
357 /* EBR exists. Write each EBR block to mmc */
358 ebrImage = mbrImage + BLOCK_SIZE;
359 ebrSectorOffset= GET_LWORD_FROM_BYTE(&mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_FIRST_SEC]);
360 dfirstsec = 0;
361 dprintf(SPEW, "first EBR to be written at sector 0x%X\n", dfirstsec);
362 lastAddress = mbrImage + size;
363 while (ebrImage < lastAddress)
364 {
365 dprintf(SPEW, "writing to 0x%X\n", (ebrSectorOffset + dfirstsec) * BLOCK_SIZE);
366 ret = mmc_write((ebrSectorOffset + dfirstsec) * BLOCK_SIZE,
367 BLOCK_SIZE, (unsigned int *) ebrImage);
368 if (ret)
369 {
370 dprintf(CRITICAL, "Failed to write EBR block to sector 0x%X\n", dfirstsec);
371 goto end;
372 }
373 dfirstsec = GET_LWORD_FROM_BYTE(&ebrImage[TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
374 ebrImage += BLOCK_SIZE;
375 }
376 dprintf(INFO, "MBR written to mmc successfully\n");
377end:
378 return ret;
379}
380
381/* Write the MBR/EBR to the MMC. */
382unsigned int write_mbr(unsigned size, unsigned char *mbrImage,
383 struct mmc_boot_host * mmc_host,
384 struct mmc_boot_card * mmc_card)
385{
386 unsigned int ret;
387
388 /* Verify that passed in block is a valid MBR */
389 ret = partition_verify_mbr_signature(size, mbrImage);
390 if (ret)
391 {
392 goto end;
393 }
394
395 /* Write the MBR/EBR to mmc */
396 ret = write_mbr_in_blocks(size, mbrImage);
397 if (ret)
398 {
399 dprintf(CRITICAL, "Failed to write MBR block to mmc.\n" );
400 goto end;
401 }
402 /* Re-read the MBR partition into mbr table */
403 ret = mmc_boot_read_mbr( mmc_host, mmc_card );
404 if (ret)
405 {
406 dprintf(CRITICAL, "Failed to re-read mbr partition.\n");
407 goto end;
408 }
409 partition_dump();
410end:
411 return ret;
412}
413
414/*
415 * A8h reflected is 15h, i.e. 10101000 <--> 00010101
416*/
417int reflect(int data, int len)
418{
419 int ref = 0;
420
421 for(int i=0; i < len; i++) {
422 if(data & 0x1) {
423 ref |= (1 << ((len - 1) - i));
424 }
425 data = (data >> 1);
426 }
427
428 return ref;
429}
430
431/*
432* Function to calculate the CRC32
433*/
434unsigned int calculate_crc32(unsigned char *buffer, int len)
435{
436 int byte_length = 8; /*length of unit (i.e. byte)*/
437 int msb = 0;
438 int polynomial = 0x104C11DB7; /* IEEE 32bit polynomial*/
439 unsigned int regs = 0xFFFFFFFF; /* init to all ones */
440 int regs_mask = 0xFFFFFFFF; /* ensure only 32 bit answer */
441 int regs_msb = 0;
442 unsigned int reflected_regs;
443
444 for( int i=0; i < len; i++)
445 {
446 int data_byte = buffer[i];
447 data_byte = reflect(data_byte,8);
448 for(int j=0; j < byte_length; j++)
449 {
450 msb = data_byte >> (byte_length-1); /* get MSB */
451 msb &= 1; /* ensure just 1 bit */
452 regs_msb = (regs>>31) & 1; /* MSB of regs */
453 regs = regs<<1; /* shift regs for CRC-CCITT */
454 if(regs_msb ^ msb) /* MSB is a 1 */
455 {
456 regs = regs ^ polynomial; /* XOR with generator poly */
457 }
458 regs = regs & regs_mask; /* Mask off excess upper bits */
459 data_byte <<= 1; /* get to next bit */
460 }
461 }
462 regs = regs & regs_mask;
463 reflected_regs = reflect(regs, 32) ^ 0xFFFFFFFF;
464
465 return reflected_regs;
466}
467
468/*
469 * Write the GPT Partition Entry Array to the MMC.
470 */
471static unsigned int write_gpt_partition_array(unsigned char * header,
472 unsigned int partition_array_start,
473 unsigned int array_size)
474{
475 unsigned int ret = MMC_BOOT_E_INVAL;
476 unsigned long long partition_entry_lba;
477 unsigned long long partition_entry_array_start_location;
478
479 partition_entry_lba = GET_LLWORD_FROM_BYTE(&header[PARTITION_ENTRIES_OFFSET]);
480 partition_entry_array_start_location = partition_entry_lba * BLOCK_SIZE;
481
482 ret = mmc_write( partition_entry_array_start_location, array_size,
483 (unsigned int *) partition_array_start);
484 if( ret )
485 {
486 dprintf(CRITICAL, "GPT: FAILED to write the partition entry array\n");
487 goto end;
488 }
489
490end:
491 return ret;
492}
493
494static void patch_gpt(unsigned char *gptImage,
495 struct mmc_boot_card * mmc_card,
496 unsigned int array_size,
497 unsigned int max_part_count,
498 unsigned int part_entry_size)
499{
500 unsigned int partition_entry_array_start;
501 unsigned char * primary_gpt_header;
502 unsigned char * secondary_gpt_header;
503 unsigned int offset;
504 unsigned long long card_size_sec;
505 int total_part=0;
506 unsigned int last_part_offset;
507 unsigned int crc_value;
508
509 /* Get size of MMC */
510 card_size_sec = (mmc_card->capacity)/512;
511 /* Working around cap at 4GB */
512 if( card_size_sec == 0 )
513 {
514 card_size_sec = 4*1024*1024*2 - 1;
515 }
516
517 /* Patching primary header */
518 primary_gpt_header = (gptImage + PROTECTIVE_MBR_SIZE);
519 PUT_LONG_LONG( primary_gpt_header + BACKUP_HEADER_OFFSET,
520 ((long long)(card_size_sec - 1)) );
521 PUT_LONG_LONG( primary_gpt_header + LAST_USABLE_LBA_OFFSET,
522 ((long long)(card_size_sec - 34)) );
523
524 /* Patching backup GPT */
525 offset = (2 * array_size );
526 secondary_gpt_header = offset + BLOCK_SIZE + primary_gpt_header;
527 PUT_LONG_LONG( secondary_gpt_header + PRIMARY_HEADER_OFFSET,
528 ((long long)(card_size_sec - 1)) );
529 PUT_LONG_LONG( secondary_gpt_header + LAST_USABLE_LBA_OFFSET,
530 ((long long)(card_size_sec - 34)) );
531 PUT_LONG_LONG( secondary_gpt_header + PARTITION_ENTRIES_OFFSET,
532 ((long long)(card_size_sec - 33)) );
533
534 /* Find last partition */
535 while(*(primary_gpt_header +BLOCK_SIZE+ total_part* ENTRY_SIZE)!= 0)
536 {
537 total_part++;
538 }
539
540 /* Patching last partition */
541 last_part_offset = (total_part-1)*ENTRY_SIZE +
542 PARTITION_ENTRY_LAST_LBA;
543 PUT_LONG_LONG( primary_gpt_header + BLOCK_SIZE + last_part_offset,
544 (long long)(card_size_sec - 34) );
545 PUT_LONG_LONG( primary_gpt_header + BLOCK_SIZE + last_part_offset+
546 array_size,
547 (long long)(card_size_sec - 34) );
548
549 /* Updating CRC of the Partition entry array in both headers */
550 partition_entry_array_start = primary_gpt_header + BLOCK_SIZE;
551 crc_value = calculate_crc32( partition_entry_array_start,
552 max_part_count * part_entry_size);
553 PUT_LONG ( primary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
554
555 crc_value = calculate_crc32( partition_entry_array_start + array_size,
556 max_part_count * part_entry_size);
557 PUT_LONG ( secondary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
558
559 /* Clearing CRC fields to calculate */
560 PUT_LONG ( primary_gpt_header + HEADER_CRC_OFFSET,0 );
561 crc_value = calculate_crc32( primary_gpt_header, 92);
562 PUT_LONG ( primary_gpt_header + HEADER_CRC_OFFSET, crc_value);
563
564 PUT_LONG ( secondary_gpt_header + HEADER_CRC_OFFSET, 0);
565 crc_value = (calculate_crc32( secondary_gpt_header, 92));
566 PUT_LONG ( secondary_gpt_header + HEADER_CRC_OFFSET, crc_value);
567
568}
569
570/*
571 * Write the GPT to the MMC.
572 */
573unsigned int write_gpt(unsigned size, unsigned char *gptImage,
574 struct mmc_boot_host * mmc_host,
575 struct mmc_boot_card * mmc_card)
576{
577 unsigned int ret = MMC_BOOT_E_INVAL;
578 unsigned int header_size;
579 unsigned long long first_usable_lba;
580 unsigned long long backup_header_lba;
581 unsigned int max_partition_count = 0;
582 unsigned int partition_entry_size;
583 unsigned int partition_entry_array_start;
584 unsigned char * primary_gpt_header;
585 unsigned char * secondary_gpt_header;
586 unsigned int offset;
587 unsigned int partition_entry_array_size;
588 unsigned long long primary_header_location; /* address on the emmc card */
589 unsigned long long secondary_header_location; /* address on the emmc card */
590
591 /* Verify that passed block has a valid GPT primary header */
592 primary_gpt_header = (gptImage + PROTECTIVE_MBR_SIZE);
593 ret = partition_parse_gpt_header(primary_gpt_header, &first_usable_lba,
594 &partition_entry_size, &header_size,
595 &max_partition_count);
596 if( ret )
597 {
598 dprintf(CRITICAL, "GPT: Primary signature invalid cannot write GPT\n");
599 goto end;
600 }
601
602 /* Verify that passed block has a valid backup GPT HEADER */
603 partition_entry_array_size = partition_entry_size * max_partition_count;
604 if(partition_entry_array_size < MIN_PARTITION_ARRAY_SIZE)
605 {
606 partition_entry_array_size = MIN_PARTITION_ARRAY_SIZE;
607 }
608 offset = (2 * partition_entry_array_size );
609 secondary_gpt_header = offset + BLOCK_SIZE + primary_gpt_header;
610 ret = partition_parse_gpt_header ( secondary_gpt_header , &first_usable_lba,
611 &partition_entry_size, &header_size,
612 &max_partition_count);
613 if( ret )
614 {
615 dprintf(CRITICAL, "GPT: Backup signature invalid cannot write GPT\n");
616 goto end;
617 }
618
619 /* Patching the primary and the backup header of the GPT table */
620 patch_gpt(gptImage ,mmc_card ,partition_entry_array_size ,
621 max_partition_count, partition_entry_size);
622
623 /* Erasing the eMMC card before writing */
624 ret = mmc_erase_card (0x00000000 , mmc_card->capacity);
625 if(ret)
626 {
627 dprintf(CRITICAL , "Failed to erase the eMMC card\n");
628 goto end;
629 }
630
631 /* Writing protective MBR*/
632 ret = mmc_write(0 ,PROTECTIVE_MBR_SIZE ,(unsigned int *) gptImage);
633 if(ret)
634 {
635 dprintf(CRITICAL, "Failed to write Protective MBR\n");
636 goto end;
637 }
638 /* Writing the primary GPT header */
639 primary_header_location = PROTECTIVE_MBR_SIZE;
640 ret = mmc_write(primary_header_location , BLOCK_SIZE ,
641 (unsigned int *)primary_gpt_header);
642 if (ret)
643 {
644 dprintf(CRITICAL, "Failed to write GPT header\n");
645 goto end;
646 }
647
648 /* Writing the backup GPT header */
649 backup_header_lba = GET_LLWORD_FROM_BYTE
650 (&primary_gpt_header[BACKUP_HEADER_OFFSET]);
651 secondary_header_location = backup_header_lba * BLOCK_SIZE;
652 ret = mmc_write(secondary_header_location, BLOCK_SIZE ,
653 (unsigned int *)secondary_gpt_header);
654 if (ret)
655 {
656 dprintf(CRITICAL, "Failed to write GPT backup header\n");
657 goto end;
658 }
659
660 /* Writing the partition entries array for the primary header */
661 partition_entry_array_start = primary_gpt_header + BLOCK_SIZE;
662 ret =write_gpt_partition_array( primary_gpt_header ,
663 partition_entry_array_start,
664 partition_entry_array_size);
665 if( ret )
666 {
667 dprintf(CRITICAL, "GPT: Could not write GPT Partition entries array\n");
668 goto end;
669 }
670
671 /*Writing the partition entries array for the backup header */
672 partition_entry_array_start =primary_gpt_header + BLOCK_SIZE+
673 partition_entry_array_size;
674 ret = write_gpt_partition_array( secondary_gpt_header ,
675 partition_entry_array_start,
676 partition_entry_array_size);
677 if( ret )
678 {
679 dprintf(CRITICAL, "GPT: Could not write GPT Partition entries array\n");
680 goto end;
681 }
682
683 /* Re-read the GPT partition table */
684 dprintf(INFO, "Re-reading the GPT Partition Table\n");
685 ret = mmc_boot_read_gpt( mmc_host, mmc_card);
686 if( ret )
687 {
688 dprintf( CRITICAL , "GPT: Failure to re- read the GPT Partition table\n");
689 goto end;
690 }
691 partition_dump();
692 dprintf( CRITICAL, "GPT: Partition Table written\n");
693 memset(primary_gpt_header , 0x00 , size);
694
695end:
696 return ret;
697}
698
699unsigned int write_partition(unsigned size, unsigned char* partition)
700{
701 unsigned int ret = MMC_BOOT_E_INVAL;
702 unsigned int partition_type;
703 struct mmc_boot_host* mmc_host;
704 struct mmc_boot_card* mmc_card;
705
706 if (partition == 0)
707 {
708 dprintf(CRITICAL, "NULL partition\n");
709 goto end;
710 }
711
712 ret = partition_get_type(size, partition, &partition_type);
713 if (ret != MMC_BOOT_E_SUCCESS)
714 {
715 goto end;
716 }
717
718 mmc_host = get_mmc_host();
719 mmc_card = get_mmc_card();
720
721 switch (partition_type)
722 {
723 case PARTITION_TYPE_MBR:
724 dprintf(INFO, "Writing MBR partition\n");
725 ret = write_mbr(size, partition, mmc_host, mmc_card);
726 break;
727
728 case PARTITION_TYPE_GPT:
729 dprintf(INFO, "Writing GPT partition\n");
730 ret = write_gpt(size, partition, mmc_host, mmc_card);
731 dprintf( CRITICAL, "Re-Flash all the partitions\n");
732 break;
733
734 default:
735 dprintf(CRITICAL, "Invalid partition\n");
736 ret = MMC_BOOT_E_INVAL;
737 goto end;
738 }
739
740end:
741 return ret;
742}
Kinson Chikf1a43512011-07-14 11:28:39 -0700743/*
744 * Fill name for android partition found.
745 */
746static void mbr_fill_name (struct partition_entry *partition_ent,
747 unsigned int type)
748{
749 switch(type)
750 {
751 memset(partition_ent->name, 0, MAX_GPT_NAME_SIZE);
752 case MBR_MODEM_TYPE:
753 case MBR_MODEM_TYPE2:
754 /* if already assigned last name available then return */
755 if(!strcmp((const char *)vfat_partitions[vfat_count], "NONE"))
756 return;
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700757 strlcpy((char *)partition_ent->name,
758 (const char *)vfat_partitions[vfat_count],
759 sizeof(partition_ent->name));
Kinson Chikf1a43512011-07-14 11:28:39 -0700760 vfat_count++;
761 break;
762 case MBR_SBL1_TYPE:
763 memcpy(partition_ent->name,"sbl1",4);
764 break;
765 case MBR_SBL2_TYPE:
766 memcpy(partition_ent->name,"sbl2",4);
767 break;
768 case MBR_SBL3_TYPE:
769 memcpy(partition_ent->name,"sbl3",4);
770 break;
771 case MBR_RPM_TYPE:
772 memcpy(partition_ent->name,"rpm",3);
773 break;
774 case MBR_TZ_TYPE:
775 memcpy(partition_ent->name,"tz",2);
776 break;
777 case MBR_ABOOT_TYPE:
778 memcpy(partition_ent->name,"aboot",5);
779 break;
780 case MBR_BOOT_TYPE:
781 memcpy(partition_ent->name,"boot",4);
782 break;
783 case MBR_MODEM_ST1_TYPE:
784 memcpy(partition_ent->name,"modem_st1",9);
785 break;
786 case MBR_MODEM_ST2_TYPE:
787 memcpy(partition_ent->name,"modem_st2",9);
788 break;
789 case MBR_EFS2_TYPE:
790 memcpy(partition_ent->name,"efs2",4);
791 break;
792 case MBR_USERDATA_TYPE:
793 if (ext3_count == sizeof(ext3_partitions) / sizeof(char*))
794 return;
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700795 strlcpy((char *)partition_ent->name,
796 (const char *)ext3_partitions[ext3_count],
797 sizeof(partition_ent->name));
Kinson Chikf1a43512011-07-14 11:28:39 -0700798 ext3_count++;
799 break;
800 case MBR_RECOVERY_TYPE:
801 memcpy(partition_ent->name,"recovery",8);
802 break;
803 case MBR_MISC_TYPE:
804 memcpy(partition_ent->name,"misc",4);
805 break;
806 };
807}
808
809/*
810 * Find index of parition in array of partition entries
811 */
812unsigned partition_get_index (const char * name)
813{
814 unsigned int input_string_length = strlen(name);
Kinson Chik66552a82011-03-29 15:59:06 -0700815 unsigned n;
816
Kinson Chikf1a43512011-07-14 11:28:39 -0700817 for(n = 0; n < partition_count; n++){
818 if(!memcmp(name, &partition_entries[n].name, input_string_length) &&
819 input_string_length == strlen((const char *)&partition_entries[n].name))
820 {
821 return n;
Kinson Chik66552a82011-03-29 15:59:06 -0700822 }
823 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700824 return INVALID_PTN;
825}
826
827/* Get size of the partition */
828unsigned long long partition_get_size (int index)
829{
830 if (index == INVALID_PTN)
831 return 0;
832 else{
Neeti Desai5f26aff2011-09-30 10:27:40 -0700833 return partition_entries[index].size * BLOCK_SIZE;
Kinson Chikf1a43512011-07-14 11:28:39 -0700834 }
835}
836
837/* Get offset of the partition */
838unsigned long long partition_get_offset (int index)
839{
840 if (index == INVALID_PTN)
841 return 0;
842 else{
Neeti Desai5f26aff2011-09-30 10:27:40 -0700843 return partition_entries[index].first_lba * BLOCK_SIZE;
Kinson Chikf1a43512011-07-14 11:28:39 -0700844 }
845}
846
847/* Debug: Print all parsed partitions */
848void partition_dump()
849{
850 unsigned i = 0;
851 for (i=0; i< partition_count; i++){
852 dprintf(SPEW,
853 "ptn[%d]:Name[%s] Size[%llu] Type[%u] First[%llu] Last[%llu]\n",
854 i, partition_entries[i].name, partition_entries[i].size,
855 partition_entries[i].dtype, partition_entries[i].first_lba,
856 partition_entries[i].last_lba);
857 }
858}
859
860unsigned int partition_verify_mbr_signature(unsigned size,
861 unsigned char* buffer)
862{
863 /* Avoid checking past end of buffer */
864 if ((TABLE_SIGNATURE + 1) > size)
865 {
866 return MMC_BOOT_E_FAILURE;
867 }
868 /* Check to see if signature exists */
Neeti Desai5f26aff2011-09-30 10:27:40 -0700869 if ((buffer[TABLE_SIGNATURE] != MMC_MBR_SIGNATURE_BYTE_0) ||
Kinson Chikf1a43512011-07-14 11:28:39 -0700870 (buffer[TABLE_SIGNATURE + 1] != MMC_MBR_SIGNATURE_BYTE_1))
871 {
Neeti Desai5f26aff2011-09-30 10:27:40 -0700872 dprintf(CRITICAL, "MBR signature does not match.\n" );
Kinson Chikf1a43512011-07-14 11:28:39 -0700873 return MMC_BOOT_E_FAILURE;
874 }
875 return MMC_BOOT_E_SUCCESS;
876}
877
878unsigned int mbr_partition_get_type(unsigned size, unsigned char* partition,
879 unsigned int *partition_type)
880{
881 unsigned int type_offset = TABLE_ENTRY_0 + OFFSET_TYPE;
882
883 if (size < type_offset)
884 {
885 goto end;
886 }
887
888 *partition_type = partition[type_offset];
889end:
890 return MMC_BOOT_E_SUCCESS;
891}
892
893unsigned int partition_get_type(unsigned size, unsigned char* partition,
894 unsigned int *partition_type)
895{
896 unsigned int ret = MMC_BOOT_E_SUCCESS;
897
898 /*
899 * If the block contains the MBR signature, then it's likely either
900 * MBR or MBR with protective type (GPT). If the MBR signature is
901 * not there, then it could be the GPT backup.
902 */
903
904 /* First check the MBR signature */
905 ret = partition_verify_mbr_signature(size, partition);
906 if (ret == MMC_BOOT_E_SUCCESS)
907 {
908 unsigned int mbr_partition_type = PARTITION_TYPE_MBR;
909
910 /* MBR signature verified. This could be MBR, MBR + EBR, or GPT */
911 ret = mbr_partition_get_type(size, partition, &mbr_partition_type);
912 if (ret != MMC_BOOT_E_SUCCESS)
913 {
914 dprintf(CRITICAL, "Cannot get TYPE of partition");
915 }
916 else if (MBR_PROTECTED_TYPE == mbr_partition_type)
917 {
918 *partition_type = PARTITION_TYPE_GPT;
919 }
920 else
921 {
922 *partition_type = PARTITION_TYPE_MBR;
923 }
924 }
925 else
926 {
927 /*
928 * This could be the GPT backup. Make that assumption for now.
929 * Anybody who treats the block as GPT backup should check the
930 * signature.
931 */
932 *partition_type = PARTITION_TYPE_GPT_BACKUP;
933 }
934 return ret;
Kinson Chik66552a82011-03-29 15:59:06 -0700935}
Kinson Chik4d7444f2011-09-13 15:48:51 -0700936
937/*
938 * Parse the gpt header and get the required header fields
939 * Return 0 on valid signature
940 */
941unsigned int partition_parse_gpt_header(unsigned char * buffer,
942 unsigned long long * first_usable_lba,
Kinson Chik0460f172011-09-19 11:33:16 -0700943 unsigned int * partition_entry_size,
944 unsigned int * header_size,
Kinson Chik4d7444f2011-09-13 15:48:51 -0700945 unsigned int * max_partition_count)
946{
947 /* Check GPT Signature */
Neeti Desai5f26aff2011-09-30 10:27:40 -0700948 if( ((uint32_t *) buffer)[0] != GPT_SIGNATURE_2 ||
949 ((uint32_t *) buffer)[1] != GPT_SIGNATURE_1 )
Kinson Chik4d7444f2011-09-13 15:48:51 -0700950 return 1;
951
952 *header_size = GET_LWORD_FROM_BYTE(&buffer[HEADER_SIZE_OFFSET]);
953 *first_usable_lba = GET_LLWORD_FROM_BYTE(&buffer[FIRST_USABLE_LBA_OFFSET]);
954 *max_partition_count = GET_LWORD_FROM_BYTE(&buffer[PARTITION_COUNT_OFFSET]);
955 *partition_entry_size = GET_LWORD_FROM_BYTE(&buffer[PENTRY_SIZE_OFFSET]);
956
957 return 0;
958}