blob: bd3cf39ebfe0556934293dec36cc1111434c7bb3 [file] [log] [blame]
Mayank Grover07f7ca62018-05-30 16:33:33 +05301/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
Kinson Chik66552a82011-03-29 15:59:06 -07002
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.
Channagoud Kadabif73aa292013-01-31 16:55:20 -080012 * * Neither the name of The Linux Foundation. nor the names of its
Kinson Chik66552a82011-03-29 15:59:06 -070013 * 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>
vijay kumar24c9ed12015-04-28 13:05:04 +053031#include <crc32.h>
Kinson Chik66552a82011-03-29 15:59:06 -070032#include "mmc.h"
33#include "partition_parser.h"
Mayank Grovere358f1f2017-05-30 20:05:14 +053034#include "ab_partition_parser.h"
35
vijay kumar24c9ed12015-04-28 13:05:04 +053036static bool flashing_gpt = 0;
37static bool parse_secondary_gpt = 0;
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -080038__WEAK void mmc_set_lun(uint8_t lun)
39{
40}
41
42__WEAK uint8_t mmc_get_lun(void)
43{
44 return 0;
45}
46
47__WEAK void mmc_read_partition_table(uint8_t arg)
48{
49 if(partition_read_table())
50 {
51 dprintf(CRITICAL, "Error reading the partition table info\n");
52 ASSERT(0);
53 }
54}
55
Channagoud Kadabi96c629e2013-09-10 14:21:30 -070056static uint32_t mmc_boot_read_gpt(uint32_t block_size);
57static uint32_t mmc_boot_read_mbr(uint32_t block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -070058static void mbr_fill_name(struct partition_entry *partition_ent,
59 uint32_t type);
60static uint32_t partition_verify_mbr_signature(uint32_t size,
61 uint8_t *buffer);
62static uint32_t mbr_partition_get_type(uint32_t size, uint8_t *partition,
63 uint32_t *partition_type);
64
65static uint32_t partition_get_type(uint32_t size, uint8_t *partition,
66 uint32_t *partition_type);
67static uint32_t partition_parse_gpt_header(uint8_t *buffer,
68 uint64_t *first_usable_lba,
69 uint32_t *partition_entry_size,
70 uint32_t *header_size,
71 uint32_t *max_partition_count);
72
Channagoud Kadabi96c629e2013-09-10 14:21:30 -070073static uint32_t write_mbr(uint32_t, uint8_t *mbrImage, uint32_t block_size);
74static uint32_t write_gpt(uint32_t size, uint8_t *gptImage, uint32_t block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -070075
Ajay Dudanib01e5062011-12-03 23:23:42 -080076char *ext3_partitions[] =
77 { "system", "userdata", "persist", "cache", "tombstones" };
78char *vfat_partitions[] = { "modem", "mdm", "NONE" };
79
Kinson Chikf1a43512011-07-14 11:28:39 -070080unsigned int ext3_count = 0;
81unsigned int vfat_count = 0;
82
Channagoud Kadabie9cb1c22013-11-12 13:49:41 -080083struct partition_entry *partition_entries;
Pavel Nedevb5ba62d2013-07-22 11:57:41 +030084static unsigned gpt_partitions_exist = 0;
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -080085static unsigned partition_count;
Mayank Grover07f7ca62018-05-30 16:33:33 +053086/* this is a pointer to ptn_entries_buffer */
87static unsigned char *new_buffer = NULL;
Kinson Chikf1a43512011-07-14 11:28:39 -070088
Mayank Grovere358f1f2017-05-30 20:05:14 +053089unsigned partition_get_partition_count()
90{
91 return partition_count;
92}
93
94struct partition_entry* partition_get_partition_entries()
95{
96 return partition_entries;
97}
98
Channagoud Kadabi0e332852013-04-19 12:55:53 -070099unsigned int partition_read_table()
Kinson Chikf1a43512011-07-14 11:28:39 -0700100{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800101 unsigned int ret;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700102 uint32_t block_size;
103
104 block_size = mmc_get_device_blocksize();
Kinson Chikf1a43512011-07-14 11:28:39 -0700105
Channagoud Kadabie9cb1c22013-11-12 13:49:41 -0800106 /* Allocate partition entries array */
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800107 if(!partition_entries)
108 {
109 partition_entries = (struct partition_entry *) calloc(NUM_PARTITIONS, sizeof(struct partition_entry));
110 ASSERT(partition_entries);
111 }
Channagoud Kadabie9cb1c22013-11-12 13:49:41 -0800112
Ajay Dudanib01e5062011-12-03 23:23:42 -0800113 /* Read MBR of the card */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700114 ret = mmc_boot_read_mbr(block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700115 if (ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800116 dprintf(CRITICAL, "MMC Boot: MBR read failed!\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700117 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800118 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700119
Ajay Dudanib01e5062011-12-03 23:23:42 -0800120 /* Read GPT of the card if exist */
121 if (gpt_partitions_exist) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700122 ret = mmc_boot_read_gpt(block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700123 if (ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 dprintf(CRITICAL, "MMC Boot: GPT read failed!\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700125 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800126 }
127 }
Mayank Grovere358f1f2017-05-30 20:05:14 +0530128
129 /* Scan of multislot support */
130 /* TODO: Move this to mmc_boot_read_gpt() */
131 partition_scan_for_multislot();
132
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700133 return 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700134}
135
136/*
137 * Read MBR from MMC card and fill partition table.
138 */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700139static unsigned int mmc_boot_read_mbr(uint32_t block_size)
Kinson Chikf1a43512011-07-14 11:28:39 -0700140{
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700141 uint8_t *buffer = NULL;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800142 unsigned int dtype;
143 unsigned int dfirstsec;
144 unsigned int EBR_first_sec;
145 unsigned int EBR_current_sec;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700146 int ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800147 int idx, i;
Kinson Chikf1a43512011-07-14 11:28:39 -0700148
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700149 buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(block_size, CACHE_LINE));
150
151 if (!buffer)
152 {
153 dprintf(CRITICAL, "Error allocating memory while reading partition table\n");
154 ret = -1;
155 goto end;
156 }
157
Ajay Dudanib01e5062011-12-03 23:23:42 -0800158 /* Print out the MBR first */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700159 ret = mmc_read(0, (unsigned int *)buffer, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800160 if (ret) {
161 dprintf(CRITICAL, "Could not read partition from mmc\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700162 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800163 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700164
Ajay Dudanib01e5062011-12-03 23:23:42 -0800165 /* Check to see if signature exists */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700166 ret = partition_verify_mbr_signature(block_size, buffer);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800167 if (ret) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700168 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800169 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700170
Ajay Dudanib01e5062011-12-03 23:23:42 -0800171 /*
172 * Process each of the four partitions in the MBR by reading the table
173 * information into our mbr table.
174 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800175 idx = TABLE_ENTRY_0;
176 for (i = 0; i < 4; i++) {
177 /* Type 0xEE indicates end of MBR and GPT partitions exist */
178 dtype = buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
179 if (dtype == MBR_PROTECTED_TYPE) {
180 gpt_partitions_exist = 1;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700181 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800182 }
183 partition_entries[partition_count].dtype = dtype;
184 partition_entries[partition_count].attribute_flag =
185 buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
186 partition_entries[partition_count].first_lba =
187 GET_LWORD_FROM_BYTE(&buffer[idx +
188 i * TABLE_ENTRY_SIZE +
189 OFFSET_FIRST_SEC]);
190 partition_entries[partition_count].size =
191 GET_LWORD_FROM_BYTE(&buffer[idx +
192 i * TABLE_ENTRY_SIZE +
193 OFFSET_SIZE]);
194 dfirstsec = partition_entries[partition_count].first_lba;
195 mbr_fill_name(&partition_entries[partition_count],
196 partition_entries[partition_count].dtype);
197 partition_count++;
198 if (partition_count == NUM_PARTITIONS)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700199 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800200 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700201
Ajay Dudanib01e5062011-12-03 23:23:42 -0800202 /* See if the last partition is EBR, if not, parsing is done */
203 if (dtype != MBR_EBR_TYPE) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700204 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800205 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700206
Ajay Dudanib01e5062011-12-03 23:23:42 -0800207 EBR_first_sec = dfirstsec;
208 EBR_current_sec = dfirstsec;
Kinson Chikf1a43512011-07-14 11:28:39 -0700209
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700210 ret = mmc_read((EBR_first_sec * block_size), (unsigned int *)buffer, block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700211 if (ret)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700212 goto end;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700213
Ajay Dudanib01e5062011-12-03 23:23:42 -0800214 /* Loop to parse the EBR */
215 for (i = 0;; i++) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700216 ret = partition_verify_mbr_signature(block_size, buffer);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800217 if (ret) {
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700218 ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800219 break;
220 }
221 partition_entries[partition_count].attribute_flag =
222 buffer[TABLE_ENTRY_0 + OFFSET_STATUS];
223 partition_entries[partition_count].dtype =
224 buffer[TABLE_ENTRY_0 + OFFSET_TYPE];
225 partition_entries[partition_count].first_lba =
226 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 +
227 OFFSET_FIRST_SEC]) +
228 EBR_current_sec;
229 partition_entries[partition_count].size =
230 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + OFFSET_SIZE]);
231 mbr_fill_name(&(partition_entries[partition_count]),
232 partition_entries[partition_count].dtype);
233 partition_count++;
234 if (partition_count == NUM_PARTITIONS)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700235 goto end;
Kinson Chikf1a43512011-07-14 11:28:39 -0700236
Ajay Dudanib01e5062011-12-03 23:23:42 -0800237 dfirstsec =
238 GET_LWORD_FROM_BYTE(&buffer
239 [TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
240 if (dfirstsec == 0) {
241 /* Getting to the end of the EBR tables */
242 break;
243 }
244 /* More EBR to follow - read in the next EBR sector */
245 dprintf(SPEW, "Reading EBR block from 0x%X\n", EBR_first_sec
246 + dfirstsec);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700247 ret = mmc_read(((EBR_first_sec + dfirstsec) * block_size),(unsigned int *)buffer,
248 block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700249 if (ret)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700250 goto end;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700251
Ajay Dudanib01e5062011-12-03 23:23:42 -0800252 EBR_current_sec = EBR_first_sec + dfirstsec;
253 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700254end:
255 if (buffer)
256 free(buffer);
257
Ajay Dudanib01e5062011-12-03 23:23:42 -0800258 return ret;
Kinson Chikf1a43512011-07-14 11:28:39 -0700259}
Kinson Chik66552a82011-03-29 15:59:06 -0700260
261/*
262 * Read GPT from MMC and fill partition table
263 */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700264static unsigned int mmc_boot_read_gpt(uint32_t block_size)
Kinson Chikf1a43512011-07-14 11:28:39 -0700265{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700266 int ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800267 unsigned int header_size;
268 unsigned long long first_usable_lba;
269 unsigned long long backup_header_lba;
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700270 unsigned long long card_size_sec;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800271 unsigned int max_partition_count = 0;
272 unsigned int partition_entry_size;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700273 unsigned int i = 0; /* Counter for each block */
274 unsigned int j = 0; /* Counter for each entry in a block */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800275 unsigned int n = 0; /* Counter for UTF-16 -> 8 conversion */
276 unsigned char UTF16_name[MAX_GPT_NAME_SIZE];
277 /* LBA of first partition -- 1 Block after Protected MBR + 1 for PT */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700278 uint64_t device_density;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700279 uint8_t *data = NULL;
Mayank Grover07f7ca62018-05-30 16:33:33 +0530280 uint8_t *data_org_ptr = NULL;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700281 uint32_t part_entry_cnt = block_size / ENTRY_SIZE;
Mayank Grover1f6c7ac2018-06-04 17:42:19 +0530282 uint32_t blocks_for_entries =
283 (NUM_PARTITIONS * PARTITION_ENTRY_SIZE)/block_size;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700284
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700285 /* Get the density of the mmc device */
286
287 device_density = mmc_get_device_capacity();
288
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700289 data = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(block_size, CACHE_LINE));
290 if (!data)
291 {
292 dprintf(CRITICAL, "Failed to Allocate memory to read partition table\n");
293 ret = -1;
294 goto end;
295 }
Mayank Grover07f7ca62018-05-30 16:33:33 +0530296 data_org_ptr = data;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700297
Ajay Dudanib01e5062011-12-03 23:23:42 -0800298 /* Print out the GPT first */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700299 ret = mmc_read(block_size, (unsigned int *)data, block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700300 if (ret)
Channagoud Kadabi39f13522013-07-31 14:46:22 -0700301 {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800302 dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700303 goto end;
Channagoud Kadabi39f13522013-07-31 14:46:22 -0700304 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800305 ret = partition_parse_gpt_header(data, &first_usable_lba,
306 &partition_entry_size, &header_size,
307 &max_partition_count);
308 if (ret) {
309 dprintf(INFO, "GPT: (WARNING) Primary signature invalid\n");
Kinson Chik4d7444f2011-09-13 15:48:51 -0700310
Ajay Dudanib01e5062011-12-03 23:23:42 -0800311 /* Check the backup gpt */
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700312
313 /* Get size of MMC */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700314 card_size_sec = (device_density) / block_size;
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700315 ASSERT (card_size_sec > 0);
316
317 backup_header_lba = card_size_sec - 1;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700318 ret = mmc_read((backup_header_lba * block_size), (unsigned int *)data,
319 block_size);
Kinson Chik4d7444f2011-09-13 15:48:51 -0700320
Ajay Dudanib01e5062011-12-03 23:23:42 -0800321 if (ret) {
322 dprintf(CRITICAL,
323 "GPT: Could not read backup gpt from mmc\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700324 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800325 }
vijay kumared75ae42015-07-22 12:42:06 +0530326 parse_secondary_gpt = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800327 ret = partition_parse_gpt_header(data, &first_usable_lba,
328 &partition_entry_size,
329 &header_size,
330 &max_partition_count);
331 if (ret) {
332 dprintf(CRITICAL,
333 "GPT: Primary and backup signatures invalid\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700334 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800335 }
vijay kumared75ae42015-07-22 12:42:06 +0530336 parse_secondary_gpt = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800337 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800338 /* Read GPT Entries */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700339 for (i = 0; i < (ROUNDUP(max_partition_count, part_entry_cnt)) / part_entry_cnt; i++) {
neetid6c38de12011-12-02 12:04:50 -0800340 ASSERT(partition_count < NUM_PARTITIONS);
Mayank Grover07f7ca62018-05-30 16:33:33 +0530341
342 data = (new_buffer + (i * block_size));
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700343 for (j = 0; j < part_entry_cnt; j++) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800344 memcpy(&(partition_entries[partition_count].type_guid),
345 &data[(j * partition_entry_size)],
346 PARTITION_TYPE_GUID_SIZE);
347 if (partition_entries[partition_count].type_guid[0] ==
348 0x00
349 && partition_entries[partition_count].
350 type_guid[1] == 0x00) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700351 i = ROUNDUP(max_partition_count, part_entry_cnt);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800352 break;
353 }
354 memcpy(&
355 (partition_entries[partition_count].
356 unique_partition_guid),
357 &data[(j * partition_entry_size) +
358 UNIQUE_GUID_OFFSET],
359 UNIQUE_PARTITION_GUID_SIZE);
360 partition_entries[partition_count].first_lba =
361 GET_LLWORD_FROM_BYTE(&data
362 [(j * partition_entry_size) +
363 FIRST_LBA_OFFSET]);
364 partition_entries[partition_count].last_lba =
365 GET_LLWORD_FROM_BYTE(&data
366 [(j * partition_entry_size) +
367 LAST_LBA_OFFSET]);
Mayank Grover1f6c7ac2018-06-04 17:42:19 +0530368
369 /* If partition entry LBA is not valid, skip this entry
370 and parse next entry */
371 if (partition_entries[partition_count].first_lba < first_usable_lba
372 || partition_entries[partition_count].last_lba >
373 (device_density/block_size -
374 (blocks_for_entries + GPT_HEADER_BLOCKS + 1))
375 || partition_entries[partition_count].first_lba >
376 partition_entries[partition_count].last_lba)
377 {
378 dprintf(CRITICAL, "Partition entry(%d), lba not valid\n", j);
379 partition_count++;
380 continue;
381 }
382
Ajay Dudanib01e5062011-12-03 23:23:42 -0800383 partition_entries[partition_count].size =
384 partition_entries[partition_count].last_lba -
Neeti Desai4b8c1df2012-03-21 13:15:14 -0700385 partition_entries[partition_count].first_lba + 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800386 partition_entries[partition_count].attribute_flag =
387 GET_LLWORD_FROM_BYTE(&data
388 [(j * partition_entry_size) +
Mayank Grover1f6c7ac2018-06-04 17:42:19 +0530389 ATTRIBUTE_FLAG_OFFSET]);
Kinson Chik66552a82011-03-29 15:59:06 -0700390
Ajay Dudanib01e5062011-12-03 23:23:42 -0800391 memset(&UTF16_name, 0x00, MAX_GPT_NAME_SIZE);
392 memcpy(UTF16_name, &data[(j * partition_entry_size) +
393 PARTITION_NAME_OFFSET],
394 MAX_GPT_NAME_SIZE);
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800395 partition_entries[partition_count].lun = mmc_get_lun();
396
Ajay Dudanib01e5062011-12-03 23:23:42 -0800397 /*
398 * Currently partition names in *.xml are UTF-8 and lowercase
399 * Only supporting english for now so removing 2nd byte of UTF-16
400 */
401 for (n = 0; n < MAX_GPT_NAME_SIZE / 2; n++) {
402 partition_entries[partition_count].name[n] =
403 UTF16_name[n * 2];
404 }
405 partition_count++;
406 }
407 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700408end:
Mayank Grover07f7ca62018-05-30 16:33:33 +0530409 if (data_org_ptr)
410 free(data_org_ptr);
411 if (new_buffer)
412 free(new_buffer);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700413
Ajay Dudanib01e5062011-12-03 23:23:42 -0800414 return ret;
Kinson Chik66552a82011-03-29 15:59:06 -0700415}
416
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700417static unsigned int write_mbr_in_blocks(uint32_t size, uint8_t *mbrImage, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700418{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800419 unsigned int dtype;
420 unsigned int dfirstsec;
421 unsigned int ebrSectorOffset;
422 unsigned char *ebrImage;
423 unsigned char *lastAddress;
424 int idx, i;
425 unsigned int ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700426
Ajay Dudanib01e5062011-12-03 23:23:42 -0800427 /* Write the first block */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700428 ret = mmc_write(0, block_size, (unsigned int *)mbrImage);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800429 if (ret) {
430 dprintf(CRITICAL, "Failed to write mbr partition\n");
431 goto end;
432 }
433 dprintf(SPEW, "write of first MBR block ok\n");
434 /*
435 Loop through the MBR table to see if there is an EBR.
436 If found, then figure out where to write the first EBR
437 */
438 idx = TABLE_ENTRY_0;
439 for (i = 0; i < 4; i++) {
440 dtype = mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
441 if (MBR_EBR_TYPE == dtype) {
442 dprintf(SPEW, "EBR found.\n");
443 break;
444 }
445 }
446 if (MBR_EBR_TYPE != dtype) {
447 dprintf(SPEW, "No EBR in this image\n");
448 goto end;
449 }
450 /* EBR exists. Write each EBR block to mmc */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700451 ebrImage = mbrImage + block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800452 ebrSectorOffset =
453 GET_LWORD_FROM_BYTE(&mbrImage
454 [idx + i * TABLE_ENTRY_SIZE +
455 OFFSET_FIRST_SEC]);
456 dfirstsec = 0;
457 dprintf(SPEW, "first EBR to be written at sector 0x%X\n", dfirstsec);
458 lastAddress = mbrImage + size;
459 while (ebrImage < lastAddress) {
460 dprintf(SPEW, "writing to 0x%X\n",
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700461 (ebrSectorOffset + dfirstsec) * block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800462 ret =
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700463 mmc_write((ebrSectorOffset + dfirstsec) * block_size,
464 block_size, (unsigned int *)ebrImage);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800465 if (ret) {
466 dprintf(CRITICAL,
467 "Failed to write EBR block to sector 0x%X\n",
468 dfirstsec);
469 goto end;
470 }
471 dfirstsec =
472 GET_LWORD_FROM_BYTE(&ebrImage
473 [TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700474 ebrImage += block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800475 }
476 dprintf(INFO, "MBR written to mmc successfully\n");
477 end:
478 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700479}
480
481/* Write the MBR/EBR to the MMC. */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700482static unsigned int write_mbr(uint32_t size, uint8_t *mbrImage, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700483{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800484 unsigned int ret;
Vijay Kumar Pendoti17c38532016-05-04 20:27:52 +0530485 uint64_t device_density;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700486
Ajay Dudanib01e5062011-12-03 23:23:42 -0800487 /* Verify that passed in block is a valid MBR */
488 ret = partition_verify_mbr_signature(size, mbrImage);
489 if (ret) {
490 goto end;
491 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700492
Vijay Kumar Pendoti17c38532016-05-04 20:27:52 +0530493 device_density = mmc_get_device_capacity();
494
495 /* Erasing the eMMC card before writing */
496 ret = mmc_erase_card(0x00000000, device_density);
497 if (ret) {
498 dprintf(CRITICAL, "Failed to erase the eMMC card\n");
499 goto end;
500 }
501
Ajay Dudanib01e5062011-12-03 23:23:42 -0800502 /* Write the MBR/EBR to mmc */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700503 ret = write_mbr_in_blocks(size, mbrImage, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800504 if (ret) {
505 dprintf(CRITICAL, "Failed to write MBR block to mmc.\n");
506 goto end;
507 }
508 /* Re-read the MBR partition into mbr table */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700509 ret = mmc_boot_read_mbr(block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800510 if (ret) {
511 dprintf(CRITICAL, "Failed to re-read mbr partition.\n");
512 goto end;
513 }
514 partition_dump();
515 end:
516 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700517}
518
519/*
520 * A8h reflected is 15h, i.e. 10101000 <--> 00010101
521*/
522int reflect(int data, int len)
523{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800524 int ref = 0;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700525
Ajay Dudanib01e5062011-12-03 23:23:42 -0800526 for (int i = 0; i < len; i++) {
527 if (data & 0x1) {
528 ref |= (1 << ((len - 1) - i));
529 }
530 data = (data >> 1);
531 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700532
Ajay Dudanib01e5062011-12-03 23:23:42 -0800533 return ref;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700534}
535
536/*
537* Function to calculate the CRC32
538*/
539unsigned int calculate_crc32(unsigned char *buffer, int len)
540{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800541 int byte_length = 8; /*length of unit (i.e. byte) */
542 int msb = 0;
Channagoud Kadabi39f13522013-07-31 14:46:22 -0700543 int polynomial = 0x04C11DB7; /* IEEE 32bit polynomial */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800544 unsigned int regs = 0xFFFFFFFF; /* init to all ones */
545 int regs_mask = 0xFFFFFFFF; /* ensure only 32 bit answer */
546 int regs_msb = 0;
547 unsigned int reflected_regs;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700548
Ajay Dudanib01e5062011-12-03 23:23:42 -0800549 for (int i = 0; i < len; i++) {
550 int data_byte = buffer[i];
551 data_byte = reflect(data_byte, 8);
552 for (int j = 0; j < byte_length; j++) {
553 msb = data_byte >> (byte_length - 1); /* get MSB */
554 msb &= 1; /* ensure just 1 bit */
555 regs_msb = (regs >> 31) & 1; /* MSB of regs */
556 regs = regs << 1; /* shift regs for CRC-CCITT */
557 if (regs_msb ^ msb) { /* MSB is a 1 */
558 regs = regs ^ polynomial; /* XOR with generator poly */
559 }
560 regs = regs & regs_mask; /* Mask off excess upper bits */
561 data_byte <<= 1; /* get to next bit */
562 }
563 }
564 regs = regs & regs_mask;
565 reflected_regs = reflect(regs, 32) ^ 0xFFFFFFFF;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700566
Ajay Dudanib01e5062011-12-03 23:23:42 -0800567 return reflected_regs;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700568}
569
570/*
571 * Write the GPT Partition Entry Array to the MMC.
572 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800573static unsigned int
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700574write_gpt_partition_array(uint8_t *header,
575 uint32_t partition_array_start,
576 uint32_t array_size,
577 uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700578{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700579 unsigned int ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800580 unsigned long long partition_entry_lba;
581 unsigned long long partition_entry_array_start_location;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700582
Ajay Dudanib01e5062011-12-03 23:23:42 -0800583 partition_entry_lba =
584 GET_LLWORD_FROM_BYTE(&header[PARTITION_ENTRIES_OFFSET]);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700585 partition_entry_array_start_location = partition_entry_lba * block_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700586
Ajay Dudanib01e5062011-12-03 23:23:42 -0800587 ret = mmc_write(partition_entry_array_start_location, array_size,
588 (unsigned int *)partition_array_start);
589 if (ret) {
590 dprintf(CRITICAL,
591 "GPT: FAILED to write the partition entry array\n");
592 goto end;
593 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700594
Ajay Dudanib01e5062011-12-03 23:23:42 -0800595 end:
596 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700597}
598
Ajay Dudanib01e5062011-12-03 23:23:42 -0800599static void
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700600patch_gpt(uint8_t *gptImage, uint64_t density, uint32_t array_size,
601 uint32_t max_part_count, uint32_t part_entry_size, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700602{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800603 unsigned int partition_entry_array_start;
604 unsigned char *primary_gpt_header;
605 unsigned char *secondary_gpt_header;
jianzhou26d8a012018-07-05 10:24:35 +0800606 //define as 64 bit unsigned int
607 unsigned long long *last_partition_entry;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800608 unsigned int offset;
609 unsigned long long card_size_sec;
610 int total_part = 0;
611 unsigned int last_part_offset;
612 unsigned int crc_value;
Mayank Groverf99769e2018-06-06 15:47:47 +0530613 unsigned ptn_entries_blocks = (NUM_PARTITIONS * ENTRY_SIZE)/block_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700614
Ajay Dudanib01e5062011-12-03 23:23:42 -0800615 /* Get size of MMC */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700616 card_size_sec = (density) / block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800617 /* Working around cap at 4GB */
618 if (card_size_sec == 0) {
619 card_size_sec = 4 * 1024 * 1024 * 2 - 1;
620 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700621
Ajay Dudanib01e5062011-12-03 23:23:42 -0800622 /* Patching primary header */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700623 primary_gpt_header = (gptImage + block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800624 PUT_LONG_LONG(primary_gpt_header + BACKUP_HEADER_OFFSET,
625 ((long long)(card_size_sec - 1)));
626 PUT_LONG_LONG(primary_gpt_header + LAST_USABLE_LBA_OFFSET,
Mayank Groverf99769e2018-06-06 15:47:47 +0530627 ((long long)(card_size_sec -
628 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1))));
Neeti Desai5f26aff2011-09-30 10:27:40 -0700629
Ajay Dudanib01e5062011-12-03 23:23:42 -0800630 /* Patching backup GPT */
631 offset = (2 * array_size);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700632 secondary_gpt_header = offset + block_size + primary_gpt_header;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800633 PUT_LONG_LONG(secondary_gpt_header + PRIMARY_HEADER_OFFSET,
634 ((long long)(card_size_sec - 1)));
635 PUT_LONG_LONG(secondary_gpt_header + LAST_USABLE_LBA_OFFSET,
Mayank Groverf99769e2018-06-06 15:47:47 +0530636 ((long long)(card_size_sec -
637 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1))));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800638 PUT_LONG_LONG(secondary_gpt_header + PARTITION_ENTRIES_OFFSET,
Mayank Groverf99769e2018-06-06 15:47:47 +0530639 ((long long)(card_size_sec -
640 (ptn_entries_blocks + GPT_HEADER_BLOCKS))));
Neeti Desai5f26aff2011-09-30 10:27:40 -0700641
Ajay Dudanib01e5062011-12-03 23:23:42 -0800642 /* Find last partition */
jianzhou26d8a012018-07-05 10:24:35 +0800643 last_partition_entry = (unsigned long long *)
644 (primary_gpt_header + block_size + total_part * ENTRY_SIZE);
645 //need check 128 bit for GUID
646 while (*last_partition_entry != 0 ||
647 *(last_partition_entry + 1) != 0 ) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800648 total_part++;
jianzhou26d8a012018-07-05 10:24:35 +0800649 last_partition_entry = (unsigned long long *)
650 (primary_gpt_header + block_size + total_part * ENTRY_SIZE);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800651 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700652
Ajay Dudanib01e5062011-12-03 23:23:42 -0800653 /* Patching last partition */
654 last_part_offset =
655 (total_part - 1) * ENTRY_SIZE + PARTITION_ENTRY_LAST_LBA;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700656 PUT_LONG_LONG(primary_gpt_header + block_size + last_part_offset,
Mayank Groverf99769e2018-06-06 15:47:47 +0530657 (long long)(card_size_sec -
658 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1)));
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700659 PUT_LONG_LONG(primary_gpt_header + block_size + last_part_offset +
Mayank Groverf99769e2018-06-06 15:47:47 +0530660 array_size, (long long)(card_size_sec -
661 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1)));
Neeti Desai5f26aff2011-09-30 10:27:40 -0700662
Ajay Dudanib01e5062011-12-03 23:23:42 -0800663 /* Updating CRC of the Partition entry array in both headers */
vijay kumar4f4405f2014-08-08 11:49:53 +0530664 partition_entry_array_start = (unsigned int)primary_gpt_header + block_size;
665 crc_value = calculate_crc32((unsigned char *)partition_entry_array_start,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800666 max_part_count * part_entry_size);
667 PUT_LONG(primary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700668
vijay kumar4f4405f2014-08-08 11:49:53 +0530669 crc_value = calculate_crc32((unsigned char *)partition_entry_array_start + array_size,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800670 max_part_count * part_entry_size);
671 PUT_LONG(secondary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700672
Ajay Dudanib01e5062011-12-03 23:23:42 -0800673 /* Clearing CRC fields to calculate */
674 PUT_LONG(primary_gpt_header + HEADER_CRC_OFFSET, 0);
675 crc_value = calculate_crc32(primary_gpt_header, 92);
676 PUT_LONG(primary_gpt_header + HEADER_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700677
Ajay Dudanib01e5062011-12-03 23:23:42 -0800678 PUT_LONG(secondary_gpt_header + HEADER_CRC_OFFSET, 0);
679 crc_value = (calculate_crc32(secondary_gpt_header, 92));
680 PUT_LONG(secondary_gpt_header + HEADER_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700681
682}
683
684/*
685 * Write the GPT to the MMC.
686 */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700687static unsigned int write_gpt(uint32_t size, uint8_t *gptImage, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700688{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700689 unsigned int ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800690 unsigned int header_size;
691 unsigned long long first_usable_lba;
692 unsigned long long backup_header_lba;
693 unsigned int max_partition_count = 0;
694 unsigned int partition_entry_size;
695 unsigned int partition_entry_array_start;
696 unsigned char *primary_gpt_header;
697 unsigned char *secondary_gpt_header;
698 unsigned int offset;
699 unsigned int partition_entry_array_size;
700 unsigned long long primary_header_location; /* address on the emmc card */
701 unsigned long long secondary_header_location; /* address on the emmc card */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700702 uint64_t device_density;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700703
Ajay Dudanib01e5062011-12-03 23:23:42 -0800704 /* Verify that passed block has a valid GPT primary header */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700705 primary_gpt_header = (gptImage + block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800706 ret = partition_parse_gpt_header(primary_gpt_header, &first_usable_lba,
707 &partition_entry_size, &header_size,
708 &max_partition_count);
709 if (ret) {
710 dprintf(CRITICAL,
711 "GPT: Primary signature invalid cannot write GPT\n");
712 goto end;
713 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700714
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700715 /* Get the density of the mmc device */
716
717 device_density = mmc_get_device_capacity();
718
Ajay Dudanib01e5062011-12-03 23:23:42 -0800719 /* Verify that passed block has a valid backup GPT HEADER */
720 partition_entry_array_size = partition_entry_size * max_partition_count;
721 if (partition_entry_array_size < MIN_PARTITION_ARRAY_SIZE) {
722 partition_entry_array_size = MIN_PARTITION_ARRAY_SIZE;
723 }
724 offset = (2 * partition_entry_array_size);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700725 secondary_gpt_header = offset + block_size + primary_gpt_header;
vijay kumar24c9ed12015-04-28 13:05:04 +0530726 parse_secondary_gpt = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800727 ret =
728 partition_parse_gpt_header(secondary_gpt_header, &first_usable_lba,
729 &partition_entry_size, &header_size,
730 &max_partition_count);
vijay kumar24c9ed12015-04-28 13:05:04 +0530731 parse_secondary_gpt = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800732 if (ret) {
733 dprintf(CRITICAL,
734 "GPT: Backup signature invalid cannot write GPT\n");
735 goto end;
736 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700737
Ajay Dudanib01e5062011-12-03 23:23:42 -0800738 /* Patching the primary and the backup header of the GPT table */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700739 patch_gpt(gptImage, device_density, partition_entry_array_size,
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700740 max_partition_count, partition_entry_size, block_size);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700741
Ajay Dudanib01e5062011-12-03 23:23:42 -0800742 /* Erasing the eMMC card before writing */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700743 ret = mmc_erase_card(0x00000000, device_density);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800744 if (ret) {
745 dprintf(CRITICAL, "Failed to erase the eMMC card\n");
746 goto end;
747 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700748
Ajay Dudanib01e5062011-12-03 23:23:42 -0800749 /* Writing protective MBR */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700750 ret = mmc_write(0, block_size, (unsigned int *)gptImage);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800751 if (ret) {
752 dprintf(CRITICAL, "Failed to write Protective MBR\n");
753 goto end;
754 }
755 /* Writing the primary GPT header */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700756 primary_header_location = block_size;
757 ret = mmc_write(primary_header_location, block_size,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800758 (unsigned int *)primary_gpt_header);
759 if (ret) {
760 dprintf(CRITICAL, "Failed to write GPT header\n");
761 goto end;
762 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700763
Ajay Dudanib01e5062011-12-03 23:23:42 -0800764 /* Writing the backup GPT header */
765 backup_header_lba = GET_LLWORD_FROM_BYTE
766 (&primary_gpt_header[BACKUP_HEADER_OFFSET]);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700767 secondary_header_location = backup_header_lba * block_size;
768 ret = mmc_write(secondary_header_location, block_size,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800769 (unsigned int *)secondary_gpt_header);
770 if (ret) {
771 dprintf(CRITICAL, "Failed to write GPT backup header\n");
772 goto end;
773 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700774
Ajay Dudanib01e5062011-12-03 23:23:42 -0800775 /* Writing the partition entries array for the primary header */
vijay kumar4f4405f2014-08-08 11:49:53 +0530776 partition_entry_array_start = (unsigned int)primary_gpt_header + block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800777 ret = write_gpt_partition_array(primary_gpt_header,
778 partition_entry_array_start,
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700779 partition_entry_array_size, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800780 if (ret) {
781 dprintf(CRITICAL,
782 "GPT: Could not write GPT Partition entries array\n");
783 goto end;
784 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700785
Ajay Dudanib01e5062011-12-03 23:23:42 -0800786 /*Writing the partition entries array for the backup header */
vijay kumar4f4405f2014-08-08 11:49:53 +0530787 partition_entry_array_start = (unsigned int)primary_gpt_header + block_size +
Ajay Dudanib01e5062011-12-03 23:23:42 -0800788 partition_entry_array_size;
789 ret = write_gpt_partition_array(secondary_gpt_header,
790 partition_entry_array_start,
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700791 partition_entry_array_size, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800792 if (ret) {
793 dprintf(CRITICAL,
794 "GPT: Could not write GPT Partition entries array\n");
795 goto end;
796 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700797
Ajay Dudanib01e5062011-12-03 23:23:42 -0800798 /* Re-read the GPT partition table */
799 dprintf(INFO, "Re-reading the GPT Partition Table\n");
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800800 partition_count = 0;
vijay kumar24c9ed12015-04-28 13:05:04 +0530801 flashing_gpt = 0;
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800802 mmc_read_partition_table(0);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800803 partition_dump();
804 dprintf(CRITICAL, "GPT: Partition Table written\n");
805 memset(primary_gpt_header, 0x00, size);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700806
Ajay Dudanib01e5062011-12-03 23:23:42 -0800807 end:
808 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700809}
810
Ajay Dudanib01e5062011-12-03 23:23:42 -0800811unsigned int write_partition(unsigned size, unsigned char *partition)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700812{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700813 unsigned int ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800814 unsigned int partition_type;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700815 uint32_t block_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700816
Ajay Dudanib01e5062011-12-03 23:23:42 -0800817 if (partition == 0) {
818 dprintf(CRITICAL, "NULL partition\n");
819 goto end;
820 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700821
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700822 block_size = mmc_get_device_blocksize();
Ajay Dudanib01e5062011-12-03 23:23:42 -0800823 ret = partition_get_type(size, partition, &partition_type);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700824 if (ret)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800825 goto end;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700826
Ajay Dudanib01e5062011-12-03 23:23:42 -0800827 switch (partition_type) {
828 case PARTITION_TYPE_MBR:
829 dprintf(INFO, "Writing MBR partition\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700830 ret = write_mbr(size, partition, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800831 break;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700832
Ajay Dudanib01e5062011-12-03 23:23:42 -0800833 case PARTITION_TYPE_GPT:
834 dprintf(INFO, "Writing GPT partition\n");
vijay kumar24c9ed12015-04-28 13:05:04 +0530835 flashing_gpt = 1;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700836 ret = write_gpt(size, partition, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800837 dprintf(CRITICAL, "Re-Flash all the partitions\n");
838 break;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700839
Ajay Dudanib01e5062011-12-03 23:23:42 -0800840 default:
841 dprintf(CRITICAL, "Invalid partition\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700842 ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800843 goto end;
844 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700845
Ajay Dudanib01e5062011-12-03 23:23:42 -0800846 end:
847 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700848}
Ajay Dudanib01e5062011-12-03 23:23:42 -0800849
Kinson Chikf1a43512011-07-14 11:28:39 -0700850/*
851 * Fill name for android partition found.
852 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800853static void
854mbr_fill_name(struct partition_entry *partition_ent, unsigned int type)
Kinson Chikf1a43512011-07-14 11:28:39 -0700855{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800856 switch (type) {
857 memset(partition_ent->name, 0, MAX_GPT_NAME_SIZE);
858 case MBR_MODEM_TYPE:
859 case MBR_MODEM_TYPE2:
860 /* if already assigned last name available then return */
861 if (!strcmp((const char *)vfat_partitions[vfat_count], "NONE"))
862 return;
863 strlcpy((char *)partition_ent->name,
864 (const char *)vfat_partitions[vfat_count],
865 sizeof(partition_ent->name));
866 vfat_count++;
867 break;
868 case MBR_SBL1_TYPE:
869 memcpy(partition_ent->name, "sbl1", 4);
870 break;
871 case MBR_SBL2_TYPE:
872 memcpy(partition_ent->name, "sbl2", 4);
873 break;
874 case MBR_SBL3_TYPE:
875 memcpy(partition_ent->name, "sbl3", 4);
876 break;
877 case MBR_RPM_TYPE:
878 memcpy(partition_ent->name, "rpm", 3);
879 break;
880 case MBR_TZ_TYPE:
881 memcpy(partition_ent->name, "tz", 2);
882 break;
883 case MBR_ABOOT_TYPE:
Channagoud Kadabi16f50952012-04-02 16:24:07 +0530884#if PLATFORM_MSM7X27A
885 memcpy(partition_ent->name, "FOTA", 4);
886#else
Ajay Dudanib01e5062011-12-03 23:23:42 -0800887 memcpy(partition_ent->name, "aboot", 5);
Channagoud Kadabi16f50952012-04-02 16:24:07 +0530888#endif
Ajay Dudanib01e5062011-12-03 23:23:42 -0800889 break;
890 case MBR_BOOT_TYPE:
891 memcpy(partition_ent->name, "boot", 4);
892 break;
893 case MBR_MODEM_ST1_TYPE:
894 memcpy(partition_ent->name, "modem_st1", 9);
895 break;
896 case MBR_MODEM_ST2_TYPE:
897 memcpy(partition_ent->name, "modem_st2", 9);
898 break;
899 case MBR_EFS2_TYPE:
900 memcpy(partition_ent->name, "efs2", 4);
901 break;
902 case MBR_USERDATA_TYPE:
903 if (ext3_count == sizeof(ext3_partitions) / sizeof(char *))
904 return;
905 strlcpy((char *)partition_ent->name,
906 (const char *)ext3_partitions[ext3_count],
907 sizeof(partition_ent->name));
908 ext3_count++;
909 break;
910 case MBR_RECOVERY_TYPE:
911 memcpy(partition_ent->name, "recovery", 8);
912 break;
913 case MBR_MISC_TYPE:
914 memcpy(partition_ent->name, "misc", 4);
915 break;
Neeti Desai2d6b0e42012-03-23 15:48:57 -0700916 case MBR_SSD_TYPE:
917 memcpy(partition_ent->name, "ssd", 3);
918 break;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800919 };
Kinson Chikf1a43512011-07-14 11:28:39 -0700920}
921
922/*
923 * Find index of parition in array of partition entries
924 */
Pavel Nedev285ad922013-04-26 10:39:19 +0300925int partition_get_index(const char *name)
Kinson Chikf1a43512011-07-14 11:28:39 -0700926{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800927 unsigned int input_string_length = strlen(name);
928 unsigned n;
Mayank Grovere358f1f2017-05-30 20:05:14 +0530929 int curr_slot = INVALID;
930 const char *suffix_curr_actv_slot = NULL;
931 char *curr_suffix = NULL;
Kinson Chik66552a82011-03-29 15:59:06 -0700932
neetid6c38de12011-12-02 12:04:50 -0800933 if( partition_count >= NUM_PARTITIONS)
934 {
935 return INVALID_PTN;
936 }
Mayank Grovere358f1f2017-05-30 20:05:14 +0530937
938 /* We iterate through the parition entries list,
939 to find the partition with active slot suffix.
940 */
941 for (n = 0; n < partition_count; n++)
942 {
943 if (!strncmp((const char*)name, (const char *)partition_entries[n].name,
944 input_string_length))
945 {
946 curr_suffix = (char *)(partition_entries[n].name+input_string_length);
947
948 /* if partition_entries.name is NULL terminated return the index */
949 if (*curr_suffix == '\0')
950 return n;
951
952 if (partition_multislot_is_supported())
953 {
954 curr_slot = partition_find_active_slot();
955
956 /* If suffix string matches with current active slot suffix return index */
957 if (curr_slot != INVALID)
958 {
959 suffix_curr_actv_slot = SUFFIX_SLOT(curr_slot);
960 if (!strncmp((const char *)curr_suffix, suffix_curr_actv_slot,
961 strlen(suffix_curr_actv_slot)))
962 return n;
963 else
964 continue;
965 }
966 else
967 {
968 /* No valid active slot */
969 return INVALID_PTN;
970 }
971 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800972 }
973 }
974 return INVALID_PTN;
Kinson Chikf1a43512011-07-14 11:28:39 -0700975}
976
Vijay Kumar Pendoti1c1d6702016-07-21 13:03:23 +0530977/*
978 * Find relative index of partition in lun
979 */
980int partition_get_index_in_lun(const char *name, unsigned int lun)
981{
982 unsigned int input_string_length = strlen(name);
983 unsigned int n, relative_index = 0;
Mayank Grovere358f1f2017-05-30 20:05:14 +0530984 int curr_slot = INVALID;
985 const char *suffix_curr_actv_slot = NULL;
986 char *curr_suffix = NULL;
987 for (n = 0; n < partition_count; n++)
988 {
Vijay Kumar Pendoti1c1d6702016-07-21 13:03:23 +0530989 if (lun == partition_entries[n].lun)
990 {
991 relative_index++;
Mayank Grovere358f1f2017-05-30 20:05:14 +0530992 if (!strncmp((const char*)name, (const char *)partition_entries[n].name,
993 input_string_length))
994 {
995 curr_suffix = (char *)(partition_entries[n].name+input_string_length);
996
997 /* if partition_entries.name is NULL terminated return relative index */
998 if (*curr_suffix == '\0')
999 return relative_index;
1000
1001 if (partition_multislot_is_supported())
1002 {
1003 curr_slot = partition_find_active_slot();
1004
1005 /* If suffix string matches with current active slot suffix return index */
1006 if (curr_slot != INVALID)
1007 {
1008 suffix_curr_actv_slot = SUFFIX_SLOT(curr_slot);
1009 if (!strncmp((const char *)curr_suffix, suffix_curr_actv_slot,
1010 strlen(suffix_curr_actv_slot)))
1011 return relative_index;
1012 else
1013 continue;
1014 }
1015 else
1016 {
1017 /* No valid active slot */
1018 return INVALID_PTN;
1019 }
1020 }
Vijay Kumar Pendoti1c1d6702016-07-21 13:03:23 +05301021 }
1022 }
1023 }
1024 return INVALID_PTN;
1025}
1026
Kinson Chikf1a43512011-07-14 11:28:39 -07001027/* Get size of the partition */
Ajay Dudanib01e5062011-12-03 23:23:42 -08001028unsigned long long partition_get_size(int index)
Kinson Chikf1a43512011-07-14 11:28:39 -07001029{
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001030 uint32_t block_size;
1031
1032 block_size = mmc_get_device_blocksize();
1033
Ajay Dudanib01e5062011-12-03 23:23:42 -08001034 if (index == INVALID_PTN)
1035 return 0;
1036 else {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001037 return partition_entries[index].size * block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001038 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001039}
1040
1041/* Get offset of the partition */
Ajay Dudanib01e5062011-12-03 23:23:42 -08001042unsigned long long partition_get_offset(int index)
Kinson Chikf1a43512011-07-14 11:28:39 -07001043{
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001044 uint32_t block_size;
1045
1046 block_size = mmc_get_device_blocksize();
1047
Ajay Dudanib01e5062011-12-03 23:23:42 -08001048 if (index == INVALID_PTN)
1049 return 0;
1050 else {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001051 return partition_entries[index].first_lba * block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001052 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001053}
1054
Sundarajan Srinivasan9ec69632014-04-10 13:33:10 -07001055struct partition_info partition_get_info(const char *name)
1056{
1057 struct partition_info info = {0};
1058
1059 int index = INVALID_PTN;
1060
1061 if(!name)
1062 {
1063 dprintf(CRITICAL, "Invalid partition name passed\n");
1064 goto out;
1065 }
1066
1067 index = partition_get_index(name);
1068
1069 if (index != INVALID_PTN)
1070 {
1071 info.offset = partition_get_offset(index);
1072 info.size = partition_get_size(index);
1073 }
1074 else
1075 {
1076 dprintf(CRITICAL, "Error unable to find partition : [%s]\n", name);
1077 }
1078out:
1079 return info;
1080}
1081
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -08001082uint8_t partition_get_lun(int index)
1083{
1084 return partition_entries[index].lun;
1085}
1086
Kinson Chikf1a43512011-07-14 11:28:39 -07001087/* Debug: Print all parsed partitions */
1088void partition_dump()
1089{
Ajay Dudanib01e5062011-12-03 23:23:42 -08001090 unsigned i = 0;
1091 for (i = 0; i < partition_count; i++) {
1092 dprintf(SPEW,
1093 "ptn[%d]:Name[%s] Size[%llu] Type[%u] First[%llu] Last[%llu]\n",
1094 i, partition_entries[i].name, partition_entries[i].size,
1095 partition_entries[i].dtype,
1096 partition_entries[i].first_lba,
1097 partition_entries[i].last_lba);
1098 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001099}
1100
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001101static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001102partition_verify_mbr_signature(unsigned size, unsigned char *buffer)
Kinson Chikf1a43512011-07-14 11:28:39 -07001103{
Ajay Dudanib01e5062011-12-03 23:23:42 -08001104 /* Avoid checking past end of buffer */
1105 if ((TABLE_SIGNATURE + 1) > size) {
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001106 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001107 }
1108 /* Check to see if signature exists */
1109 if ((buffer[TABLE_SIGNATURE] != MMC_MBR_SIGNATURE_BYTE_0) ||
1110 (buffer[TABLE_SIGNATURE + 1] != MMC_MBR_SIGNATURE_BYTE_1)) {
1111 dprintf(CRITICAL, "MBR signature does not match.\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001112 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001113 }
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001114 return 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001115}
1116
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001117static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001118mbr_partition_get_type(unsigned size, unsigned char *partition,
1119 unsigned int *partition_type)
Kinson Chikf1a43512011-07-14 11:28:39 -07001120{
Ajay Dudanib01e5062011-12-03 23:23:42 -08001121 unsigned int type_offset = TABLE_ENTRY_0 + OFFSET_TYPE;
Kinson Chikf1a43512011-07-14 11:28:39 -07001122
Channagoud Kadabi98b11072015-03-12 15:14:22 -07001123 if (size < (type_offset + sizeof (*partition_type))) {
Ajay Dudanib01e5062011-12-03 23:23:42 -08001124 goto end;
1125 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001126
Ajay Dudanib01e5062011-12-03 23:23:42 -08001127 *partition_type = partition[type_offset];
1128 end:
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001129 return 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001130}
1131
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001132static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001133partition_get_type(unsigned size, unsigned char *partition,
1134 unsigned int *partition_type)
Kinson Chikf1a43512011-07-14 11:28:39 -07001135{
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001136 unsigned int ret = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001137
Ajay Dudanib01e5062011-12-03 23:23:42 -08001138 /*
1139 * If the block contains the MBR signature, then it's likely either
1140 * MBR or MBR with protective type (GPT). If the MBR signature is
1141 * not there, then it could be the GPT backup.
1142 */
Kinson Chikf1a43512011-07-14 11:28:39 -07001143
Ajay Dudanib01e5062011-12-03 23:23:42 -08001144 /* First check the MBR signature */
1145 ret = partition_verify_mbr_signature(size, partition);
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001146 if (!ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -08001147 unsigned int mbr_partition_type = PARTITION_TYPE_MBR;
Kinson Chikf1a43512011-07-14 11:28:39 -07001148
Ajay Dudanib01e5062011-12-03 23:23:42 -08001149 /* MBR signature verified. This could be MBR, MBR + EBR, or GPT */
1150 ret =
1151 mbr_partition_get_type(size, partition,
1152 &mbr_partition_type);
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001153 if (ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -08001154 dprintf(CRITICAL, "Cannot get TYPE of partition");
1155 } else if (MBR_PROTECTED_TYPE == mbr_partition_type) {
1156 *partition_type = PARTITION_TYPE_GPT;
1157 } else {
1158 *partition_type = PARTITION_TYPE_MBR;
1159 }
1160 } else {
1161 /*
1162 * This could be the GPT backup. Make that assumption for now.
1163 * Anybody who treats the block as GPT backup should check the
1164 * signature.
1165 */
1166 *partition_type = PARTITION_TYPE_GPT_BACKUP;
1167 }
1168 return ret;
Kinson Chik66552a82011-03-29 15:59:06 -07001169}
Kinson Chik4d7444f2011-09-13 15:48:51 -07001170
1171/*
1172 * Parse the gpt header and get the required header fields
1173 * Return 0 on valid signature
1174 */
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001175static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001176partition_parse_gpt_header(unsigned char *buffer,
1177 unsigned long long *first_usable_lba,
1178 unsigned int *partition_entry_size,
1179 unsigned int *header_size,
1180 unsigned int *max_partition_count)
Kinson Chik4d7444f2011-09-13 15:48:51 -07001181{
vijay kumar24c9ed12015-04-28 13:05:04 +05301182 uint32_t crc_val_org = 0;
1183 uint32_t crc_val = 0;
1184 uint32_t ret = 0;
1185 uint32_t partitions_for_block = 0;
1186 uint32_t blocks_to_read = 0;
vijay kumar24c9ed12015-04-28 13:05:04 +05301187 unsigned long long last_usable_lba = 0;
1188 unsigned long long partition_0 = 0;
1189 unsigned long long current_lba = 0;
1190 uint32_t block_size = mmc_get_device_blocksize();
Mayank Grover45d9c2c2018-06-04 17:25:52 +05301191 uint32_t blocks_for_entries =
1192 (NUM_PARTITIONS * PARTITION_ENTRY_SIZE)/ block_size;
vijay kumar24c9ed12015-04-28 13:05:04 +05301193 /* Get the density of the mmc device */
1194 uint64_t device_density = mmc_get_device_capacity();
1195
Ajay Dudanib01e5062011-12-03 23:23:42 -08001196 /* Check GPT Signature */
1197 if (((uint32_t *) buffer)[0] != GPT_SIGNATURE_2 ||
1198 ((uint32_t *) buffer)[1] != GPT_SIGNATURE_1)
1199 return 1;
Kinson Chik4d7444f2011-09-13 15:48:51 -07001200
Ajay Dudanib01e5062011-12-03 23:23:42 -08001201 *header_size = GET_LWORD_FROM_BYTE(&buffer[HEADER_SIZE_OFFSET]);
vijay kumar24c9ed12015-04-28 13:05:04 +05301202 /*check for header size too small*/
1203 if (*header_size < GPT_HEADER_SIZE) {
1204 dprintf(CRITICAL,"GPT Header size is too small\n");
1205 return 1;
1206 }
1207 /*check for header size too large*/
1208 if (*header_size > block_size) {
1209 dprintf(CRITICAL,"GPT Header size is too large\n");
1210 return 1;
1211 }
1212
1213 crc_val_org = GET_LWORD_FROM_BYTE(&buffer[HEADER_CRC_OFFSET]);
1214 /*Write CRC to 0 before we calculate the crc of the GPT header*/
1215 crc_val = 0;
1216 PUT_LONG(&buffer[HEADER_CRC_OFFSET], crc_val);
1217
1218 crc_val = crc32(~0L,buffer, *header_size) ^ (~0L);
1219 if (crc_val != crc_val_org) {
1220 dprintf(CRITICAL,"Header crc mismatch crc_val = %u with crc_val_org = %u\n", crc_val,crc_val_org);
1221 return 1;
1222 }
1223 else
1224 PUT_LONG(&buffer[HEADER_CRC_OFFSET], crc_val);
1225
1226 current_lba =
1227 GET_LLWORD_FROM_BYTE(&buffer[PRIMARY_HEADER_OFFSET]);
Ajay Dudanib01e5062011-12-03 23:23:42 -08001228 *first_usable_lba =
1229 GET_LLWORD_FROM_BYTE(&buffer[FIRST_USABLE_LBA_OFFSET]);
1230 *max_partition_count =
1231 GET_LWORD_FROM_BYTE(&buffer[PARTITION_COUNT_OFFSET]);
1232 *partition_entry_size =
1233 GET_LWORD_FROM_BYTE(&buffer[PENTRY_SIZE_OFFSET]);
vijay kumar24c9ed12015-04-28 13:05:04 +05301234 last_usable_lba =
1235 GET_LLWORD_FROM_BYTE(&buffer[LAST_USABLE_LBA_OFFSET]);
Kinson Chik4d7444f2011-09-13 15:48:51 -07001236
vijay kumar24c9ed12015-04-28 13:05:04 +05301237 /*current lba and GPT lba should be same*/
1238 if (!parse_secondary_gpt) {
1239 if (current_lba != GPT_LBA) {
Mayank Groverdcdc33c2018-06-04 16:35:06 +05301240 dprintf(CRITICAL,"Primary GPT first usable LBA mismatch\n");
vijay kumar24c9ed12015-04-28 13:05:04 +05301241 return 1;
1242 }
1243 }
Mayank Groverdcdc33c2018-06-04 16:35:06 +05301244 else
1245 {
Mayank Grover7bfbb0e2018-08-02 13:06:43 +05301246 /*
1247 Check only in case of reading, skip for flashing as this is patched
1248 in patch_gpt() later in flow.
1249 */
1250 if (!flashing_gpt && (current_lba != ((device_density/block_size) - 1)))
Mayank Groverdcdc33c2018-06-04 16:35:06 +05301251 {
1252 dprintf(CRITICAL,"Secondary GPT first usable LBA mismatch\n");
1253 return 1;
1254 }
1255 }
1256
vijay kumar24c9ed12015-04-28 13:05:04 +05301257 /*check for first lba should be with in the valid range*/
1258 if (*first_usable_lba > (device_density/block_size)) {
1259 dprintf(CRITICAL,"Invalid first_usable_lba\n");
1260 return 1;
1261 }
1262 /*check for last lba should be with in the valid range*/
1263 if (last_usable_lba > (device_density/block_size)) {
1264 dprintf(CRITICAL,"Invalid last_usable_lba\n");
1265 return 1;
1266 }
1267 /*check for partition entry size*/
1268 if (*partition_entry_size != PARTITION_ENTRY_SIZE) {
1269 dprintf(CRITICAL,"Invalid parition entry size\n");
1270 return 1;
1271 }
1272
1273 if ((*max_partition_count) > (MIN_PARTITION_ARRAY_SIZE /(*partition_entry_size))) {
1274 dprintf(CRITICAL, "Invalid maximum partition count\n");
1275 return 1;
1276 }
1277
1278 partitions_for_block = block_size / (*partition_entry_size);
1279
1280 blocks_to_read = (*max_partition_count)/ partitions_for_block;
1281 if ((*max_partition_count) % partitions_for_block) {
1282 blocks_to_read += 1;
1283 }
1284
1285 new_buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP((blocks_to_read * block_size),CACHE_LINE));
1286
1287 if (!new_buffer)
1288 {
1289 dprintf(CRITICAL, "Failed to Allocate memory to read partition table\n");
1290 return 1;
1291 }
1292
1293 if (!flashing_gpt) {
1294 partition_0 = GET_LLWORD_FROM_BYTE(&buffer[PARTITION_ENTRIES_OFFSET]);
1295 /*start LBA should always be 2 in primary GPT*/
Mayank Grover45d9c2c2018-06-04 17:25:52 +05301296 if (!parse_secondary_gpt)
1297 {
1298 if (partition_0 != 0x2)
1299 {
1300 dprintf(CRITICAL, "PrimaryGPT starting LBA mismatch\n");
1301 ret = 1;
1302 goto fail;
1303 }
1304 }
1305 else
1306 {
1307 if (partition_0 != ((device_density/block_size) -
1308 (blocks_for_entries + GPT_HEADER_BLOCKS)))
1309 {
1310 dprintf(CRITICAL, "BackupGPT starting LBA mismatch\n");
1311 ret = 1;
1312 goto fail;
1313 }
vijay kumar24c9ed12015-04-28 13:05:04 +05301314 }
1315 /*read the partition entries to new_buffer*/
1316 ret = mmc_read((partition_0) * (block_size), (unsigned int *)new_buffer, (blocks_to_read * block_size));
1317 if (ret)
1318 {
1319 dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
1320 goto fail;
1321 }
1322 crc_val_org = GET_LWORD_FROM_BYTE(&buffer[PARTITION_CRC_OFFSET]);
1323
1324 crc_val = crc32(~0L,new_buffer, ((*max_partition_count) * (*partition_entry_size))) ^ (~0L);
1325 if (crc_val != crc_val_org) {
1326 dprintf(CRITICAL,"Partition entires crc mismatch crc_val= %u with crc_val_org= %u\n",crc_val,crc_val_org);
1327 ret = 1;
1328 }
Mayank Grover07f7ca62018-05-30 16:33:33 +05301329 return ret;
vijay kumar24c9ed12015-04-28 13:05:04 +05301330 }
1331fail:
1332 free(new_buffer);
Saranya Chidura9c9d90a2018-10-22 12:32:25 +05301333 new_buffer = NULL;
1334
vijay kumar24c9ed12015-04-28 13:05:04 +05301335 return ret;
Kinson Chik4d7444f2011-09-13 15:48:51 -07001336}
Pavel Nedevb5ba62d2013-07-22 11:57:41 +03001337
1338bool partition_gpt_exists()
1339{
1340 return (gpt_partitions_exist != 0);
1341}
Channagoud Kadabifaf20f62014-10-21 22:22:37 -07001342
1343int partition_read_only(int index)
1344{
1345 return partition_entries[index].attribute_flag >> PART_ATT_READONLY_OFFSET;
1346}