blob: 3752ba87fe24600db778779900ef76d7e1ee6775 [file] [log] [blame]
lijuang0b655852017-05-22 16:21:48 +08001/* Copyright (c) 2011-2017, 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;
Kinson Chikf1a43512011-07-14 11:28:39 -070086
Mayank Grovere358f1f2017-05-30 20:05:14 +053087unsigned partition_get_partition_count()
88{
89 return partition_count;
90}
91
92struct partition_entry* partition_get_partition_entries()
93{
94 return partition_entries;
95}
96
Channagoud Kadabi0e332852013-04-19 12:55:53 -070097unsigned int partition_read_table()
Kinson Chikf1a43512011-07-14 11:28:39 -070098{
Ajay Dudanib01e5062011-12-03 23:23:42 -080099 unsigned int ret;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700100 uint32_t block_size;
101
102 block_size = mmc_get_device_blocksize();
Kinson Chikf1a43512011-07-14 11:28:39 -0700103
Channagoud Kadabie9cb1c22013-11-12 13:49:41 -0800104 /* Allocate partition entries array */
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800105 if(!partition_entries)
106 {
107 partition_entries = (struct partition_entry *) calloc(NUM_PARTITIONS, sizeof(struct partition_entry));
108 ASSERT(partition_entries);
109 }
Channagoud Kadabie9cb1c22013-11-12 13:49:41 -0800110
Ajay Dudanib01e5062011-12-03 23:23:42 -0800111 /* Read MBR of the card */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700112 ret = mmc_boot_read_mbr(block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700113 if (ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800114 dprintf(CRITICAL, "MMC Boot: MBR read failed!\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700115 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800116 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700117
Ajay Dudanib01e5062011-12-03 23:23:42 -0800118 /* Read GPT of the card if exist */
119 if (gpt_partitions_exist) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700120 ret = mmc_boot_read_gpt(block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700121 if (ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800122 dprintf(CRITICAL, "MMC Boot: GPT read failed!\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700123 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 }
125 }
Mayank Grovere358f1f2017-05-30 20:05:14 +0530126
127 /* Scan of multislot support */
128 /* TODO: Move this to mmc_boot_read_gpt() */
129 partition_scan_for_multislot();
130
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700131 return 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700132}
133
134/*
135 * Read MBR from MMC card and fill partition table.
136 */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700137static unsigned int mmc_boot_read_mbr(uint32_t block_size)
Kinson Chikf1a43512011-07-14 11:28:39 -0700138{
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700139 uint8_t *buffer = NULL;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800140 unsigned int dtype;
141 unsigned int dfirstsec;
142 unsigned int EBR_first_sec;
143 unsigned int EBR_current_sec;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700144 int ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800145 int idx, i;
Kinson Chikf1a43512011-07-14 11:28:39 -0700146
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700147 buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(block_size, CACHE_LINE));
148
149 if (!buffer)
150 {
151 dprintf(CRITICAL, "Error allocating memory while reading partition table\n");
152 ret = -1;
153 goto end;
154 }
155
Ajay Dudanib01e5062011-12-03 23:23:42 -0800156 /* Print out the MBR first */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700157 ret = mmc_read(0, (unsigned int *)buffer, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800158 if (ret) {
159 dprintf(CRITICAL, "Could not read partition from mmc\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700160 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800161 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700162
Ajay Dudanib01e5062011-12-03 23:23:42 -0800163 /* Check to see if signature exists */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700164 ret = partition_verify_mbr_signature(block_size, buffer);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800165 if (ret) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700166 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800167 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700168
Ajay Dudanib01e5062011-12-03 23:23:42 -0800169 /*
170 * Process each of the four partitions in the MBR by reading the table
171 * information into our mbr table.
172 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800173 idx = TABLE_ENTRY_0;
174 for (i = 0; i < 4; i++) {
175 /* Type 0xEE indicates end of MBR and GPT partitions exist */
176 dtype = buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
177 if (dtype == MBR_PROTECTED_TYPE) {
178 gpt_partitions_exist = 1;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700179 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800180 }
181 partition_entries[partition_count].dtype = dtype;
182 partition_entries[partition_count].attribute_flag =
183 buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
184 partition_entries[partition_count].first_lba =
185 GET_LWORD_FROM_BYTE(&buffer[idx +
186 i * TABLE_ENTRY_SIZE +
187 OFFSET_FIRST_SEC]);
188 partition_entries[partition_count].size =
189 GET_LWORD_FROM_BYTE(&buffer[idx +
190 i * TABLE_ENTRY_SIZE +
191 OFFSET_SIZE]);
192 dfirstsec = partition_entries[partition_count].first_lba;
193 mbr_fill_name(&partition_entries[partition_count],
194 partition_entries[partition_count].dtype);
195 partition_count++;
196 if (partition_count == NUM_PARTITIONS)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700197 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800198 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700199
Ajay Dudanib01e5062011-12-03 23:23:42 -0800200 /* See if the last partition is EBR, if not, parsing is done */
201 if (dtype != MBR_EBR_TYPE) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700202 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800203 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700204
Ajay Dudanib01e5062011-12-03 23:23:42 -0800205 EBR_first_sec = dfirstsec;
206 EBR_current_sec = dfirstsec;
Kinson Chikf1a43512011-07-14 11:28:39 -0700207
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700208 ret = mmc_read((EBR_first_sec * block_size), (unsigned int *)buffer, block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700209 if (ret)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700210 goto end;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700211
Ajay Dudanib01e5062011-12-03 23:23:42 -0800212 /* Loop to parse the EBR */
213 for (i = 0;; i++) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700214 ret = partition_verify_mbr_signature(block_size, buffer);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800215 if (ret) {
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700216 ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800217 break;
218 }
219 partition_entries[partition_count].attribute_flag =
220 buffer[TABLE_ENTRY_0 + OFFSET_STATUS];
221 partition_entries[partition_count].dtype =
222 buffer[TABLE_ENTRY_0 + OFFSET_TYPE];
223 partition_entries[partition_count].first_lba =
224 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 +
225 OFFSET_FIRST_SEC]) +
226 EBR_current_sec;
227 partition_entries[partition_count].size =
228 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + OFFSET_SIZE]);
229 mbr_fill_name(&(partition_entries[partition_count]),
230 partition_entries[partition_count].dtype);
231 partition_count++;
232 if (partition_count == NUM_PARTITIONS)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700233 goto end;
Kinson Chikf1a43512011-07-14 11:28:39 -0700234
Ajay Dudanib01e5062011-12-03 23:23:42 -0800235 dfirstsec =
236 GET_LWORD_FROM_BYTE(&buffer
237 [TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
238 if (dfirstsec == 0) {
239 /* Getting to the end of the EBR tables */
240 break;
241 }
242 /* More EBR to follow - read in the next EBR sector */
243 dprintf(SPEW, "Reading EBR block from 0x%X\n", EBR_first_sec
244 + dfirstsec);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700245 ret = mmc_read(((EBR_first_sec + dfirstsec) * block_size),(unsigned int *)buffer,
246 block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700247 if (ret)
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700248 goto end;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700249
Ajay Dudanib01e5062011-12-03 23:23:42 -0800250 EBR_current_sec = EBR_first_sec + dfirstsec;
251 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700252end:
253 if (buffer)
254 free(buffer);
255
Ajay Dudanib01e5062011-12-03 23:23:42 -0800256 return ret;
Kinson Chikf1a43512011-07-14 11:28:39 -0700257}
Kinson Chik66552a82011-03-29 15:59:06 -0700258
259/*
260 * Read GPT from MMC and fill partition table
261 */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700262static unsigned int mmc_boot_read_gpt(uint32_t block_size)
Kinson Chikf1a43512011-07-14 11:28:39 -0700263{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700264 int ret = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800265 unsigned int header_size;
266 unsigned long long first_usable_lba;
267 unsigned long long backup_header_lba;
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700268 unsigned long long card_size_sec;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800269 unsigned int max_partition_count = 0;
270 unsigned int partition_entry_size;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700271 unsigned int i = 0; /* Counter for each block */
272 unsigned int j = 0; /* Counter for each entry in a block */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800273 unsigned int n = 0; /* Counter for UTF-16 -> 8 conversion */
274 unsigned char UTF16_name[MAX_GPT_NAME_SIZE];
275 /* LBA of first partition -- 1 Block after Protected MBR + 1 for PT */
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700276 unsigned long long partition_0;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700277 uint64_t device_density;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700278 uint8_t *data = NULL;
279 uint32_t part_entry_cnt = block_size / ENTRY_SIZE;
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700280
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700281 /* Get the density of the mmc device */
282
283 device_density = mmc_get_device_capacity();
284
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700285 data = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(block_size, CACHE_LINE));
286 if (!data)
287 {
288 dprintf(CRITICAL, "Failed to Allocate memory to read partition table\n");
289 ret = -1;
290 goto end;
291 }
292
Ajay Dudanib01e5062011-12-03 23:23:42 -0800293 /* Print out the GPT first */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700294 ret = mmc_read(block_size, (unsigned int *)data, block_size);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700295 if (ret)
Channagoud Kadabi39f13522013-07-31 14:46:22 -0700296 {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800297 dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700298 goto end;
Channagoud Kadabi39f13522013-07-31 14:46:22 -0700299 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800300 ret = partition_parse_gpt_header(data, &first_usable_lba,
301 &partition_entry_size, &header_size,
302 &max_partition_count);
303 if (ret) {
304 dprintf(INFO, "GPT: (WARNING) Primary signature invalid\n");
Kinson Chik4d7444f2011-09-13 15:48:51 -0700305
Ajay Dudanib01e5062011-12-03 23:23:42 -0800306 /* Check the backup gpt */
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700307
308 /* Get size of MMC */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700309 card_size_sec = (device_density) / block_size;
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700310 ASSERT (card_size_sec > 0);
311
312 backup_header_lba = card_size_sec - 1;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700313 ret = mmc_read((backup_header_lba * block_size), (unsigned int *)data,
314 block_size);
Kinson Chik4d7444f2011-09-13 15:48:51 -0700315
Ajay Dudanib01e5062011-12-03 23:23:42 -0800316 if (ret) {
317 dprintf(CRITICAL,
318 "GPT: Could not read backup gpt from mmc\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700319 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800320 }
vijay kumared75ae42015-07-22 12:42:06 +0530321 parse_secondary_gpt = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800322 ret = partition_parse_gpt_header(data, &first_usable_lba,
323 &partition_entry_size,
324 &header_size,
325 &max_partition_count);
326 if (ret) {
327 dprintf(CRITICAL,
328 "GPT: Primary and backup signatures invalid\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700329 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800330 }
vijay kumared75ae42015-07-22 12:42:06 +0530331 parse_secondary_gpt = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800332 }
Neeti Desaice6ad9a2012-03-21 18:57:59 -0700333 partition_0 = GET_LLWORD_FROM_BYTE(&data[PARTITION_ENTRIES_OFFSET]);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800334 /* Read GPT Entries */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700335 for (i = 0; i < (ROUNDUP(max_partition_count, part_entry_cnt)) / part_entry_cnt; i++) {
neetid6c38de12011-12-02 12:04:50 -0800336 ASSERT(partition_count < NUM_PARTITIONS);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700337 ret = mmc_read((partition_0 * block_size) + (i * block_size),
338 (uint32_t *) data, block_size);
Kinson Chik66552a82011-03-29 15:59:06 -0700339
Ajay Dudanib01e5062011-12-03 23:23:42 -0800340 if (ret) {
341 dprintf(CRITICAL,
342 "GPT: mmc read card failed reading partition entries.\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700343 goto end;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800344 }
Kinson Chik66552a82011-03-29 15:59:06 -0700345
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700346 for (j = 0; j < part_entry_cnt; j++) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800347 memcpy(&(partition_entries[partition_count].type_guid),
348 &data[(j * partition_entry_size)],
349 PARTITION_TYPE_GUID_SIZE);
350 if (partition_entries[partition_count].type_guid[0] ==
351 0x00
352 && partition_entries[partition_count].
353 type_guid[1] == 0x00) {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700354 i = ROUNDUP(max_partition_count, part_entry_cnt);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800355 break;
356 }
357 memcpy(&
358 (partition_entries[partition_count].
359 unique_partition_guid),
360 &data[(j * partition_entry_size) +
361 UNIQUE_GUID_OFFSET],
362 UNIQUE_PARTITION_GUID_SIZE);
363 partition_entries[partition_count].first_lba =
364 GET_LLWORD_FROM_BYTE(&data
365 [(j * partition_entry_size) +
366 FIRST_LBA_OFFSET]);
367 partition_entries[partition_count].last_lba =
368 GET_LLWORD_FROM_BYTE(&data
369 [(j * partition_entry_size) +
370 LAST_LBA_OFFSET]);
371 partition_entries[partition_count].size =
372 partition_entries[partition_count].last_lba -
Neeti Desai4b8c1df2012-03-21 13:15:14 -0700373 partition_entries[partition_count].first_lba + 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800374 partition_entries[partition_count].attribute_flag =
375 GET_LLWORD_FROM_BYTE(&data
376 [(j * partition_entry_size) +
377 ATTRIBUTE_FLAG_OFFSET]);
Kinson Chik66552a82011-03-29 15:59:06 -0700378
Ajay Dudanib01e5062011-12-03 23:23:42 -0800379 memset(&UTF16_name, 0x00, MAX_GPT_NAME_SIZE);
380 memcpy(UTF16_name, &data[(j * partition_entry_size) +
381 PARTITION_NAME_OFFSET],
382 MAX_GPT_NAME_SIZE);
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800383 partition_entries[partition_count].lun = mmc_get_lun();
384
Ajay Dudanib01e5062011-12-03 23:23:42 -0800385 /*
386 * Currently partition names in *.xml are UTF-8 and lowercase
387 * Only supporting english for now so removing 2nd byte of UTF-16
388 */
389 for (n = 0; n < MAX_GPT_NAME_SIZE / 2; n++) {
390 partition_entries[partition_count].name[n] =
391 UTF16_name[n * 2];
392 }
393 partition_count++;
394 }
395 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700396end:
397 if (data)
398 free(data);
399
Ajay Dudanib01e5062011-12-03 23:23:42 -0800400 return ret;
Kinson Chik66552a82011-03-29 15:59:06 -0700401}
402
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700403static unsigned int write_mbr_in_blocks(uint32_t size, uint8_t *mbrImage, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700404{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800405 unsigned int dtype;
406 unsigned int dfirstsec;
407 unsigned int ebrSectorOffset;
408 unsigned char *ebrImage;
409 unsigned char *lastAddress;
410 int idx, i;
411 unsigned int ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700412
Ajay Dudanib01e5062011-12-03 23:23:42 -0800413 /* Write the first block */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700414 ret = mmc_write(0, block_size, (unsigned int *)mbrImage);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800415 if (ret) {
416 dprintf(CRITICAL, "Failed to write mbr partition\n");
417 goto end;
418 }
419 dprintf(SPEW, "write of first MBR block ok\n");
420 /*
421 Loop through the MBR table to see if there is an EBR.
422 If found, then figure out where to write the first EBR
423 */
424 idx = TABLE_ENTRY_0;
425 for (i = 0; i < 4; i++) {
426 dtype = mbrImage[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
427 if (MBR_EBR_TYPE == dtype) {
428 dprintf(SPEW, "EBR found.\n");
429 break;
430 }
431 }
432 if (MBR_EBR_TYPE != dtype) {
433 dprintf(SPEW, "No EBR in this image\n");
434 goto end;
435 }
436 /* EBR exists. Write each EBR block to mmc */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700437 ebrImage = mbrImage + block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800438 ebrSectorOffset =
439 GET_LWORD_FROM_BYTE(&mbrImage
440 [idx + i * TABLE_ENTRY_SIZE +
441 OFFSET_FIRST_SEC]);
442 dfirstsec = 0;
443 dprintf(SPEW, "first EBR to be written at sector 0x%X\n", dfirstsec);
444 lastAddress = mbrImage + size;
445 while (ebrImage < lastAddress) {
446 dprintf(SPEW, "writing to 0x%X\n",
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700447 (ebrSectorOffset + dfirstsec) * block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800448 ret =
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700449 mmc_write((ebrSectorOffset + dfirstsec) * block_size,
450 block_size, (unsigned int *)ebrImage);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800451 if (ret) {
452 dprintf(CRITICAL,
453 "Failed to write EBR block to sector 0x%X\n",
454 dfirstsec);
455 goto end;
456 }
457 dfirstsec =
458 GET_LWORD_FROM_BYTE(&ebrImage
459 [TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700460 ebrImage += block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800461 }
462 dprintf(INFO, "MBR written to mmc successfully\n");
463 end:
464 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700465}
466
467/* Write the MBR/EBR to the MMC. */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700468static unsigned int write_mbr(uint32_t size, uint8_t *mbrImage, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700469{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800470 unsigned int ret;
Vijay Kumar Pendoti17c38532016-05-04 20:27:52 +0530471 uint64_t device_density;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700472
Ajay Dudanib01e5062011-12-03 23:23:42 -0800473 /* Verify that passed in block is a valid MBR */
474 ret = partition_verify_mbr_signature(size, mbrImage);
475 if (ret) {
476 goto end;
477 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700478
Vijay Kumar Pendoti17c38532016-05-04 20:27:52 +0530479 device_density = mmc_get_device_capacity();
480
481 /* Erasing the eMMC card before writing */
482 ret = mmc_erase_card(0x00000000, device_density);
483 if (ret) {
484 dprintf(CRITICAL, "Failed to erase the eMMC card\n");
485 goto end;
486 }
487
Ajay Dudanib01e5062011-12-03 23:23:42 -0800488 /* Write the MBR/EBR to mmc */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700489 ret = write_mbr_in_blocks(size, mbrImage, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800490 if (ret) {
491 dprintf(CRITICAL, "Failed to write MBR block to mmc.\n");
492 goto end;
493 }
494 /* Re-read the MBR partition into mbr table */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700495 ret = mmc_boot_read_mbr(block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800496 if (ret) {
497 dprintf(CRITICAL, "Failed to re-read mbr partition.\n");
498 goto end;
499 }
500 partition_dump();
501 end:
502 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700503}
504
505/*
506 * A8h reflected is 15h, i.e. 10101000 <--> 00010101
507*/
508int reflect(int data, int len)
509{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800510 int ref = 0;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700511
Ajay Dudanib01e5062011-12-03 23:23:42 -0800512 for (int i = 0; i < len; i++) {
513 if (data & 0x1) {
514 ref |= (1 << ((len - 1) - i));
515 }
516 data = (data >> 1);
517 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700518
Ajay Dudanib01e5062011-12-03 23:23:42 -0800519 return ref;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700520}
521
522/*
523* Function to calculate the CRC32
524*/
525unsigned int calculate_crc32(unsigned char *buffer, int len)
526{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800527 int byte_length = 8; /*length of unit (i.e. byte) */
528 int msb = 0;
Channagoud Kadabi39f13522013-07-31 14:46:22 -0700529 int polynomial = 0x04C11DB7; /* IEEE 32bit polynomial */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800530 unsigned int regs = 0xFFFFFFFF; /* init to all ones */
531 int regs_mask = 0xFFFFFFFF; /* ensure only 32 bit answer */
532 int regs_msb = 0;
533 unsigned int reflected_regs;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700534
Ajay Dudanib01e5062011-12-03 23:23:42 -0800535 for (int i = 0; i < len; i++) {
536 int data_byte = buffer[i];
537 data_byte = reflect(data_byte, 8);
538 for (int j = 0; j < byte_length; j++) {
539 msb = data_byte >> (byte_length - 1); /* get MSB */
540 msb &= 1; /* ensure just 1 bit */
541 regs_msb = (regs >> 31) & 1; /* MSB of regs */
542 regs = regs << 1; /* shift regs for CRC-CCITT */
543 if (regs_msb ^ msb) { /* MSB is a 1 */
544 regs = regs ^ polynomial; /* XOR with generator poly */
545 }
546 regs = regs & regs_mask; /* Mask off excess upper bits */
547 data_byte <<= 1; /* get to next bit */
548 }
549 }
550 regs = regs & regs_mask;
551 reflected_regs = reflect(regs, 32) ^ 0xFFFFFFFF;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700552
Ajay Dudanib01e5062011-12-03 23:23:42 -0800553 return reflected_regs;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700554}
555
556/*
557 * Write the GPT Partition Entry Array to the MMC.
558 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800559static unsigned int
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700560write_gpt_partition_array(uint8_t *header,
561 uint32_t partition_array_start,
562 uint32_t array_size,
563 uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700564{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700565 unsigned int ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800566 unsigned long long partition_entry_lba;
567 unsigned long long partition_entry_array_start_location;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700568
Ajay Dudanib01e5062011-12-03 23:23:42 -0800569 partition_entry_lba =
570 GET_LLWORD_FROM_BYTE(&header[PARTITION_ENTRIES_OFFSET]);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700571 partition_entry_array_start_location = partition_entry_lba * block_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700572
Ajay Dudanib01e5062011-12-03 23:23:42 -0800573 ret = mmc_write(partition_entry_array_start_location, array_size,
574 (unsigned int *)partition_array_start);
575 if (ret) {
576 dprintf(CRITICAL,
577 "GPT: FAILED to write the partition entry array\n");
578 goto end;
579 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700580
Ajay Dudanib01e5062011-12-03 23:23:42 -0800581 end:
582 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700583}
584
Ajay Dudanib01e5062011-12-03 23:23:42 -0800585static void
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700586patch_gpt(uint8_t *gptImage, uint64_t density, uint32_t array_size,
587 uint32_t max_part_count, uint32_t part_entry_size, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700588{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800589 unsigned int partition_entry_array_start;
590 unsigned char *primary_gpt_header;
591 unsigned char *secondary_gpt_header;
592 unsigned int offset;
593 unsigned long long card_size_sec;
594 int total_part = 0;
595 unsigned int last_part_offset;
596 unsigned int crc_value;
Mayank Groverf99769e2018-06-06 15:47:47 +0530597 unsigned ptn_entries_blocks = (NUM_PARTITIONS * ENTRY_SIZE)/block_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700598
Ajay Dudanib01e5062011-12-03 23:23:42 -0800599 /* Get size of MMC */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700600 card_size_sec = (density) / block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800601 /* Working around cap at 4GB */
602 if (card_size_sec == 0) {
603 card_size_sec = 4 * 1024 * 1024 * 2 - 1;
604 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700605
Ajay Dudanib01e5062011-12-03 23:23:42 -0800606 /* Patching primary header */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700607 primary_gpt_header = (gptImage + block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800608 PUT_LONG_LONG(primary_gpt_header + BACKUP_HEADER_OFFSET,
609 ((long long)(card_size_sec - 1)));
610 PUT_LONG_LONG(primary_gpt_header + LAST_USABLE_LBA_OFFSET,
Mayank Groverf99769e2018-06-06 15:47:47 +0530611 ((long long)(card_size_sec -
612 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1))));
Neeti Desai5f26aff2011-09-30 10:27:40 -0700613
Ajay Dudanib01e5062011-12-03 23:23:42 -0800614 /* Patching backup GPT */
615 offset = (2 * array_size);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700616 secondary_gpt_header = offset + block_size + primary_gpt_header;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800617 PUT_LONG_LONG(secondary_gpt_header + PRIMARY_HEADER_OFFSET,
618 ((long long)(card_size_sec - 1)));
619 PUT_LONG_LONG(secondary_gpt_header + LAST_USABLE_LBA_OFFSET,
Mayank Groverf99769e2018-06-06 15:47:47 +0530620 ((long long)(card_size_sec -
621 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1))));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800622 PUT_LONG_LONG(secondary_gpt_header + PARTITION_ENTRIES_OFFSET,
Mayank Groverf99769e2018-06-06 15:47:47 +0530623 ((long long)(card_size_sec -
624 (ptn_entries_blocks + GPT_HEADER_BLOCKS))));
Neeti Desai5f26aff2011-09-30 10:27:40 -0700625
Ajay Dudanib01e5062011-12-03 23:23:42 -0800626 /* Find last partition */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700627 while (*(primary_gpt_header + block_size + total_part * ENTRY_SIZE) !=
Ajay Dudanib01e5062011-12-03 23:23:42 -0800628 0) {
629 total_part++;
630 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700631
Ajay Dudanib01e5062011-12-03 23:23:42 -0800632 /* Patching last partition */
633 last_part_offset =
634 (total_part - 1) * ENTRY_SIZE + PARTITION_ENTRY_LAST_LBA;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700635 PUT_LONG_LONG(primary_gpt_header + block_size + last_part_offset,
Mayank Groverf99769e2018-06-06 15:47:47 +0530636 (long long)(card_size_sec -
637 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1)));
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700638 PUT_LONG_LONG(primary_gpt_header + block_size + last_part_offset +
Mayank Groverf99769e2018-06-06 15:47:47 +0530639 array_size, (long long)(card_size_sec -
640 (ptn_entries_blocks + GPT_HEADER_BLOCKS + 1)));
Neeti Desai5f26aff2011-09-30 10:27:40 -0700641
Ajay Dudanib01e5062011-12-03 23:23:42 -0800642 /* Updating CRC of the Partition entry array in both headers */
vijay kumar4f4405f2014-08-08 11:49:53 +0530643 partition_entry_array_start = (unsigned int)primary_gpt_header + block_size;
644 crc_value = calculate_crc32((unsigned char *)partition_entry_array_start,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800645 max_part_count * part_entry_size);
646 PUT_LONG(primary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700647
vijay kumar4f4405f2014-08-08 11:49:53 +0530648 crc_value = calculate_crc32((unsigned char *)partition_entry_array_start + array_size,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800649 max_part_count * part_entry_size);
650 PUT_LONG(secondary_gpt_header + PARTITION_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700651
Ajay Dudanib01e5062011-12-03 23:23:42 -0800652 /* Clearing CRC fields to calculate */
653 PUT_LONG(primary_gpt_header + HEADER_CRC_OFFSET, 0);
654 crc_value = calculate_crc32(primary_gpt_header, 92);
655 PUT_LONG(primary_gpt_header + HEADER_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700656
Ajay Dudanib01e5062011-12-03 23:23:42 -0800657 PUT_LONG(secondary_gpt_header + HEADER_CRC_OFFSET, 0);
658 crc_value = (calculate_crc32(secondary_gpt_header, 92));
659 PUT_LONG(secondary_gpt_header + HEADER_CRC_OFFSET, crc_value);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700660
661}
662
663/*
664 * Write the GPT to the MMC.
665 */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700666static unsigned int write_gpt(uint32_t size, uint8_t *gptImage, uint32_t block_size)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700667{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700668 unsigned int ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800669 unsigned int header_size;
670 unsigned long long first_usable_lba;
671 unsigned long long backup_header_lba;
672 unsigned int max_partition_count = 0;
673 unsigned int partition_entry_size;
674 unsigned int partition_entry_array_start;
675 unsigned char *primary_gpt_header;
676 unsigned char *secondary_gpt_header;
677 unsigned int offset;
678 unsigned int partition_entry_array_size;
679 unsigned long long primary_header_location; /* address on the emmc card */
680 unsigned long long secondary_header_location; /* address on the emmc card */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700681 uint64_t device_density;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700682
Ajay Dudanib01e5062011-12-03 23:23:42 -0800683 /* Verify that passed block has a valid GPT primary header */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700684 primary_gpt_header = (gptImage + block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800685 ret = partition_parse_gpt_header(primary_gpt_header, &first_usable_lba,
686 &partition_entry_size, &header_size,
687 &max_partition_count);
688 if (ret) {
689 dprintf(CRITICAL,
690 "GPT: Primary signature invalid cannot write GPT\n");
691 goto end;
692 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700693
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700694 /* Get the density of the mmc device */
695
696 device_density = mmc_get_device_capacity();
697
Ajay Dudanib01e5062011-12-03 23:23:42 -0800698 /* Verify that passed block has a valid backup GPT HEADER */
699 partition_entry_array_size = partition_entry_size * max_partition_count;
700 if (partition_entry_array_size < MIN_PARTITION_ARRAY_SIZE) {
701 partition_entry_array_size = MIN_PARTITION_ARRAY_SIZE;
702 }
703 offset = (2 * partition_entry_array_size);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700704 secondary_gpt_header = offset + block_size + primary_gpt_header;
vijay kumar24c9ed12015-04-28 13:05:04 +0530705 parse_secondary_gpt = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800706 ret =
707 partition_parse_gpt_header(secondary_gpt_header, &first_usable_lba,
708 &partition_entry_size, &header_size,
709 &max_partition_count);
vijay kumar24c9ed12015-04-28 13:05:04 +0530710 parse_secondary_gpt = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800711 if (ret) {
712 dprintf(CRITICAL,
713 "GPT: Backup signature invalid cannot write GPT\n");
714 goto end;
715 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700716
Ajay Dudanib01e5062011-12-03 23:23:42 -0800717 /* Patching the primary and the backup header of the GPT table */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700718 patch_gpt(gptImage, device_density, partition_entry_array_size,
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700719 max_partition_count, partition_entry_size, block_size);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700720
Ajay Dudanib01e5062011-12-03 23:23:42 -0800721 /* Erasing the eMMC card before writing */
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700722 ret = mmc_erase_card(0x00000000, device_density);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800723 if (ret) {
724 dprintf(CRITICAL, "Failed to erase the eMMC card\n");
725 goto end;
726 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700727
Ajay Dudanib01e5062011-12-03 23:23:42 -0800728 /* Writing protective MBR */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700729 ret = mmc_write(0, block_size, (unsigned int *)gptImage);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800730 if (ret) {
731 dprintf(CRITICAL, "Failed to write Protective MBR\n");
732 goto end;
733 }
734 /* Writing the primary GPT header */
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700735 primary_header_location = block_size;
736 ret = mmc_write(primary_header_location, block_size,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800737 (unsigned int *)primary_gpt_header);
738 if (ret) {
739 dprintf(CRITICAL, "Failed to write GPT header\n");
740 goto end;
741 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700742
Ajay Dudanib01e5062011-12-03 23:23:42 -0800743 /* Writing the backup GPT header */
744 backup_header_lba = GET_LLWORD_FROM_BYTE
745 (&primary_gpt_header[BACKUP_HEADER_OFFSET]);
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700746 secondary_header_location = backup_header_lba * block_size;
747 ret = mmc_write(secondary_header_location, block_size,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800748 (unsigned int *)secondary_gpt_header);
749 if (ret) {
750 dprintf(CRITICAL, "Failed to write GPT backup header\n");
751 goto end;
752 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700753
Ajay Dudanib01e5062011-12-03 23:23:42 -0800754 /* Writing the partition entries array for the primary header */
vijay kumar4f4405f2014-08-08 11:49:53 +0530755 partition_entry_array_start = (unsigned int)primary_gpt_header + block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800756 ret = write_gpt_partition_array(primary_gpt_header,
757 partition_entry_array_start,
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700758 partition_entry_array_size, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800759 if (ret) {
760 dprintf(CRITICAL,
761 "GPT: Could not write GPT Partition entries array\n");
762 goto end;
763 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700764
Ajay Dudanib01e5062011-12-03 23:23:42 -0800765 /*Writing the partition entries array for the backup header */
vijay kumar4f4405f2014-08-08 11:49:53 +0530766 partition_entry_array_start = (unsigned int)primary_gpt_header + block_size +
Ajay Dudanib01e5062011-12-03 23:23:42 -0800767 partition_entry_array_size;
768 ret = write_gpt_partition_array(secondary_gpt_header,
769 partition_entry_array_start,
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700770 partition_entry_array_size, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800771 if (ret) {
772 dprintf(CRITICAL,
773 "GPT: Could not write GPT Partition entries array\n");
774 goto end;
775 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700776
Ajay Dudanib01e5062011-12-03 23:23:42 -0800777 /* Re-read the GPT partition table */
778 dprintf(INFO, "Re-reading the GPT Partition Table\n");
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800779 partition_count = 0;
vijay kumar24c9ed12015-04-28 13:05:04 +0530780 flashing_gpt = 0;
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -0800781 mmc_read_partition_table(0);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800782 partition_dump();
783 dprintf(CRITICAL, "GPT: Partition Table written\n");
784 memset(primary_gpt_header, 0x00, size);
Neeti Desai5f26aff2011-09-30 10:27:40 -0700785
Ajay Dudanib01e5062011-12-03 23:23:42 -0800786 end:
787 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700788}
789
Ajay Dudanib01e5062011-12-03 23:23:42 -0800790unsigned int write_partition(unsigned size, unsigned char *partition)
Neeti Desai5f26aff2011-09-30 10:27:40 -0700791{
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700792 unsigned int ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800793 unsigned int partition_type;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700794 uint32_t block_size;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700795
Ajay Dudanib01e5062011-12-03 23:23:42 -0800796 if (partition == 0) {
797 dprintf(CRITICAL, "NULL partition\n");
798 goto end;
799 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700800
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700801 block_size = mmc_get_device_blocksize();
Ajay Dudanib01e5062011-12-03 23:23:42 -0800802 ret = partition_get_type(size, partition, &partition_type);
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700803 if (ret)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800804 goto end;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700805
Ajay Dudanib01e5062011-12-03 23:23:42 -0800806 switch (partition_type) {
807 case PARTITION_TYPE_MBR:
808 dprintf(INFO, "Writing MBR partition\n");
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700809 ret = write_mbr(size, partition, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800810 break;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700811
Ajay Dudanib01e5062011-12-03 23:23:42 -0800812 case PARTITION_TYPE_GPT:
813 dprintf(INFO, "Writing GPT partition\n");
vijay kumar24c9ed12015-04-28 13:05:04 +0530814 flashing_gpt = 1;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700815 ret = write_gpt(size, partition, block_size);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800816 dprintf(CRITICAL, "Re-Flash all the partitions\n");
817 break;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700818
Ajay Dudanib01e5062011-12-03 23:23:42 -0800819 default:
820 dprintf(CRITICAL, "Invalid partition\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -0700821 ret = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800822 goto end;
823 }
Neeti Desai5f26aff2011-09-30 10:27:40 -0700824
Ajay Dudanib01e5062011-12-03 23:23:42 -0800825 end:
826 return ret;
Neeti Desai5f26aff2011-09-30 10:27:40 -0700827}
Ajay Dudanib01e5062011-12-03 23:23:42 -0800828
Kinson Chikf1a43512011-07-14 11:28:39 -0700829/*
830 * Fill name for android partition found.
831 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800832static void
833mbr_fill_name(struct partition_entry *partition_ent, unsigned int type)
Kinson Chikf1a43512011-07-14 11:28:39 -0700834{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800835 switch (type) {
836 memset(partition_ent->name, 0, MAX_GPT_NAME_SIZE);
837 case MBR_MODEM_TYPE:
838 case MBR_MODEM_TYPE2:
839 /* if already assigned last name available then return */
840 if (!strcmp((const char *)vfat_partitions[vfat_count], "NONE"))
841 return;
842 strlcpy((char *)partition_ent->name,
843 (const char *)vfat_partitions[vfat_count],
844 sizeof(partition_ent->name));
845 vfat_count++;
846 break;
847 case MBR_SBL1_TYPE:
848 memcpy(partition_ent->name, "sbl1", 4);
849 break;
850 case MBR_SBL2_TYPE:
851 memcpy(partition_ent->name, "sbl2", 4);
852 break;
853 case MBR_SBL3_TYPE:
854 memcpy(partition_ent->name, "sbl3", 4);
855 break;
856 case MBR_RPM_TYPE:
857 memcpy(partition_ent->name, "rpm", 3);
858 break;
859 case MBR_TZ_TYPE:
860 memcpy(partition_ent->name, "tz", 2);
861 break;
862 case MBR_ABOOT_TYPE:
Channagoud Kadabi16f50952012-04-02 16:24:07 +0530863#if PLATFORM_MSM7X27A
864 memcpy(partition_ent->name, "FOTA", 4);
865#else
Ajay Dudanib01e5062011-12-03 23:23:42 -0800866 memcpy(partition_ent->name, "aboot", 5);
Channagoud Kadabi16f50952012-04-02 16:24:07 +0530867#endif
Ajay Dudanib01e5062011-12-03 23:23:42 -0800868 break;
869 case MBR_BOOT_TYPE:
870 memcpy(partition_ent->name, "boot", 4);
871 break;
872 case MBR_MODEM_ST1_TYPE:
873 memcpy(partition_ent->name, "modem_st1", 9);
874 break;
875 case MBR_MODEM_ST2_TYPE:
876 memcpy(partition_ent->name, "modem_st2", 9);
877 break;
878 case MBR_EFS2_TYPE:
879 memcpy(partition_ent->name, "efs2", 4);
880 break;
881 case MBR_USERDATA_TYPE:
882 if (ext3_count == sizeof(ext3_partitions) / sizeof(char *))
883 return;
884 strlcpy((char *)partition_ent->name,
885 (const char *)ext3_partitions[ext3_count],
886 sizeof(partition_ent->name));
887 ext3_count++;
888 break;
889 case MBR_RECOVERY_TYPE:
890 memcpy(partition_ent->name, "recovery", 8);
891 break;
892 case MBR_MISC_TYPE:
893 memcpy(partition_ent->name, "misc", 4);
894 break;
Neeti Desai2d6b0e42012-03-23 15:48:57 -0700895 case MBR_SSD_TYPE:
896 memcpy(partition_ent->name, "ssd", 3);
897 break;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800898 };
Kinson Chikf1a43512011-07-14 11:28:39 -0700899}
900
901/*
902 * Find index of parition in array of partition entries
903 */
Pavel Nedev285ad922013-04-26 10:39:19 +0300904int partition_get_index(const char *name)
Kinson Chikf1a43512011-07-14 11:28:39 -0700905{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800906 unsigned int input_string_length = strlen(name);
907 unsigned n;
Mayank Grovere358f1f2017-05-30 20:05:14 +0530908 int curr_slot = INVALID;
909 const char *suffix_curr_actv_slot = NULL;
910 char *curr_suffix = NULL;
Kinson Chik66552a82011-03-29 15:59:06 -0700911
neetid6c38de12011-12-02 12:04:50 -0800912 if( partition_count >= NUM_PARTITIONS)
913 {
914 return INVALID_PTN;
915 }
Mayank Grovere358f1f2017-05-30 20:05:14 +0530916
917 /* We iterate through the parition entries list,
918 to find the partition with active slot suffix.
919 */
920 for (n = 0; n < partition_count; n++)
921 {
922 if (!strncmp((const char*)name, (const char *)partition_entries[n].name,
923 input_string_length))
924 {
925 curr_suffix = (char *)(partition_entries[n].name+input_string_length);
926
927 /* if partition_entries.name is NULL terminated return the index */
928 if (*curr_suffix == '\0')
929 return n;
930
931 if (partition_multislot_is_supported())
932 {
933 curr_slot = partition_find_active_slot();
934
935 /* If suffix string matches with current active slot suffix return index */
936 if (curr_slot != INVALID)
937 {
938 suffix_curr_actv_slot = SUFFIX_SLOT(curr_slot);
939 if (!strncmp((const char *)curr_suffix, suffix_curr_actv_slot,
940 strlen(suffix_curr_actv_slot)))
941 return n;
942 else
943 continue;
944 }
945 else
946 {
947 /* No valid active slot */
948 return INVALID_PTN;
949 }
950 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800951 }
952 }
953 return INVALID_PTN;
Kinson Chikf1a43512011-07-14 11:28:39 -0700954}
955
Vijay Kumar Pendoti1c1d6702016-07-21 13:03:23 +0530956/*
957 * Find relative index of partition in lun
958 */
959int partition_get_index_in_lun(const char *name, unsigned int lun)
960{
961 unsigned int input_string_length = strlen(name);
962 unsigned int n, relative_index = 0;
Mayank Grovere358f1f2017-05-30 20:05:14 +0530963 int curr_slot = INVALID;
964 const char *suffix_curr_actv_slot = NULL;
965 char *curr_suffix = NULL;
966 for (n = 0; n < partition_count; n++)
967 {
Vijay Kumar Pendoti1c1d6702016-07-21 13:03:23 +0530968 if (lun == partition_entries[n].lun)
969 {
970 relative_index++;
Mayank Grovere358f1f2017-05-30 20:05:14 +0530971 if (!strncmp((const char*)name, (const char *)partition_entries[n].name,
972 input_string_length))
973 {
974 curr_suffix = (char *)(partition_entries[n].name+input_string_length);
975
976 /* if partition_entries.name is NULL terminated return relative index */
977 if (*curr_suffix == '\0')
978 return relative_index;
979
980 if (partition_multislot_is_supported())
981 {
982 curr_slot = partition_find_active_slot();
983
984 /* If suffix string matches with current active slot suffix return index */
985 if (curr_slot != INVALID)
986 {
987 suffix_curr_actv_slot = SUFFIX_SLOT(curr_slot);
988 if (!strncmp((const char *)curr_suffix, suffix_curr_actv_slot,
989 strlen(suffix_curr_actv_slot)))
990 return relative_index;
991 else
992 continue;
993 }
994 else
995 {
996 /* No valid active slot */
997 return INVALID_PTN;
998 }
999 }
Vijay Kumar Pendoti1c1d6702016-07-21 13:03:23 +05301000 }
1001 }
1002 }
1003 return INVALID_PTN;
1004}
1005
Kinson Chikf1a43512011-07-14 11:28:39 -07001006/* Get size of the partition */
Ajay Dudanib01e5062011-12-03 23:23:42 -08001007unsigned long long partition_get_size(int index)
Kinson Chikf1a43512011-07-14 11:28:39 -07001008{
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001009 uint32_t block_size;
1010
1011 block_size = mmc_get_device_blocksize();
1012
Ajay Dudanib01e5062011-12-03 23:23:42 -08001013 if (index == INVALID_PTN)
1014 return 0;
1015 else {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001016 return partition_entries[index].size * block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001017 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001018}
1019
1020/* Get offset of the partition */
Ajay Dudanib01e5062011-12-03 23:23:42 -08001021unsigned long long partition_get_offset(int index)
Kinson Chikf1a43512011-07-14 11:28:39 -07001022{
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001023 uint32_t block_size;
1024
1025 block_size = mmc_get_device_blocksize();
1026
Ajay Dudanib01e5062011-12-03 23:23:42 -08001027 if (index == INVALID_PTN)
1028 return 0;
1029 else {
Channagoud Kadabi96c629e2013-09-10 14:21:30 -07001030 return partition_entries[index].first_lba * block_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001031 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001032}
1033
Sundarajan Srinivasan9ec69632014-04-10 13:33:10 -07001034struct partition_info partition_get_info(const char *name)
1035{
1036 struct partition_info info = {0};
1037
1038 int index = INVALID_PTN;
1039
1040 if(!name)
1041 {
1042 dprintf(CRITICAL, "Invalid partition name passed\n");
1043 goto out;
1044 }
1045
1046 index = partition_get_index(name);
1047
1048 if (index != INVALID_PTN)
1049 {
1050 info.offset = partition_get_offset(index);
1051 info.size = partition_get_size(index);
1052 }
1053 else
1054 {
1055 dprintf(CRITICAL, "Error unable to find partition : [%s]\n", name);
1056 }
1057out:
1058 return info;
1059}
1060
Sundarajan Srinivasan554863f2013-12-04 17:14:37 -08001061uint8_t partition_get_lun(int index)
1062{
1063 return partition_entries[index].lun;
1064}
1065
Kinson Chikf1a43512011-07-14 11:28:39 -07001066/* Debug: Print all parsed partitions */
1067void partition_dump()
1068{
Ajay Dudanib01e5062011-12-03 23:23:42 -08001069 unsigned i = 0;
1070 for (i = 0; i < partition_count; i++) {
1071 dprintf(SPEW,
1072 "ptn[%d]:Name[%s] Size[%llu] Type[%u] First[%llu] Last[%llu]\n",
1073 i, partition_entries[i].name, partition_entries[i].size,
1074 partition_entries[i].dtype,
1075 partition_entries[i].first_lba,
1076 partition_entries[i].last_lba);
1077 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001078}
1079
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001080static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001081partition_verify_mbr_signature(unsigned size, unsigned char *buffer)
Kinson Chikf1a43512011-07-14 11:28:39 -07001082{
Ajay Dudanib01e5062011-12-03 23:23:42 -08001083 /* Avoid checking past end of buffer */
1084 if ((TABLE_SIGNATURE + 1) > size) {
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001085 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001086 }
1087 /* Check to see if signature exists */
1088 if ((buffer[TABLE_SIGNATURE] != MMC_MBR_SIGNATURE_BYTE_0) ||
1089 (buffer[TABLE_SIGNATURE + 1] != MMC_MBR_SIGNATURE_BYTE_1)) {
1090 dprintf(CRITICAL, "MBR signature does not match.\n");
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001091 return 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -08001092 }
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001093 return 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001094}
1095
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001096static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001097mbr_partition_get_type(unsigned size, unsigned char *partition,
1098 unsigned int *partition_type)
Kinson Chikf1a43512011-07-14 11:28:39 -07001099{
Ajay Dudanib01e5062011-12-03 23:23:42 -08001100 unsigned int type_offset = TABLE_ENTRY_0 + OFFSET_TYPE;
Kinson Chikf1a43512011-07-14 11:28:39 -07001101
Channagoud Kadabi98b11072015-03-12 15:14:22 -07001102 if (size < (type_offset + sizeof (*partition_type))) {
Ajay Dudanib01e5062011-12-03 23:23:42 -08001103 goto end;
1104 }
Kinson Chikf1a43512011-07-14 11:28:39 -07001105
Ajay Dudanib01e5062011-12-03 23:23:42 -08001106 *partition_type = partition[type_offset];
1107 end:
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001108 return 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001109}
1110
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001111static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001112partition_get_type(unsigned size, unsigned char *partition,
1113 unsigned int *partition_type)
Kinson Chikf1a43512011-07-14 11:28:39 -07001114{
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001115 unsigned int ret = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001116
Ajay Dudanib01e5062011-12-03 23:23:42 -08001117 /*
1118 * If the block contains the MBR signature, then it's likely either
1119 * MBR or MBR with protective type (GPT). If the MBR signature is
1120 * not there, then it could be the GPT backup.
1121 */
Kinson Chikf1a43512011-07-14 11:28:39 -07001122
Ajay Dudanib01e5062011-12-03 23:23:42 -08001123 /* First check the MBR signature */
1124 ret = partition_verify_mbr_signature(size, partition);
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001125 if (!ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -08001126 unsigned int mbr_partition_type = PARTITION_TYPE_MBR;
Kinson Chikf1a43512011-07-14 11:28:39 -07001127
Ajay Dudanib01e5062011-12-03 23:23:42 -08001128 /* MBR signature verified. This could be MBR, MBR + EBR, or GPT */
1129 ret =
1130 mbr_partition_get_type(size, partition,
1131 &mbr_partition_type);
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001132 if (ret) {
Ajay Dudanib01e5062011-12-03 23:23:42 -08001133 dprintf(CRITICAL, "Cannot get TYPE of partition");
1134 } else if (MBR_PROTECTED_TYPE == mbr_partition_type) {
1135 *partition_type = PARTITION_TYPE_GPT;
1136 } else {
1137 *partition_type = PARTITION_TYPE_MBR;
1138 }
1139 } else {
1140 /*
1141 * This could be the GPT backup. Make that assumption for now.
1142 * Anybody who treats the block as GPT backup should check the
1143 * signature.
1144 */
1145 *partition_type = PARTITION_TYPE_GPT_BACKUP;
1146 }
1147 return ret;
Kinson Chik66552a82011-03-29 15:59:06 -07001148}
Kinson Chik4d7444f2011-09-13 15:48:51 -07001149
1150/*
1151 * Parse the gpt header and get the required header fields
1152 * Return 0 on valid signature
1153 */
Channagoud Kadabi0e332852013-04-19 12:55:53 -07001154static unsigned int
Ajay Dudanib01e5062011-12-03 23:23:42 -08001155partition_parse_gpt_header(unsigned char *buffer,
1156 unsigned long long *first_usable_lba,
1157 unsigned int *partition_entry_size,
1158 unsigned int *header_size,
1159 unsigned int *max_partition_count)
Kinson Chik4d7444f2011-09-13 15:48:51 -07001160{
vijay kumar24c9ed12015-04-28 13:05:04 +05301161 uint32_t crc_val_org = 0;
1162 uint32_t crc_val = 0;
1163 uint32_t ret = 0;
1164 uint32_t partitions_for_block = 0;
1165 uint32_t blocks_to_read = 0;
1166 unsigned char *new_buffer = NULL;
1167 unsigned long long last_usable_lba = 0;
1168 unsigned long long partition_0 = 0;
1169 unsigned long long current_lba = 0;
1170 uint32_t block_size = mmc_get_device_blocksize();
1171 /* Get the density of the mmc device */
1172 uint64_t device_density = mmc_get_device_capacity();
1173
Ajay Dudanib01e5062011-12-03 23:23:42 -08001174 /* Check GPT Signature */
1175 if (((uint32_t *) buffer)[0] != GPT_SIGNATURE_2 ||
1176 ((uint32_t *) buffer)[1] != GPT_SIGNATURE_1)
1177 return 1;
Kinson Chik4d7444f2011-09-13 15:48:51 -07001178
Ajay Dudanib01e5062011-12-03 23:23:42 -08001179 *header_size = GET_LWORD_FROM_BYTE(&buffer[HEADER_SIZE_OFFSET]);
vijay kumar24c9ed12015-04-28 13:05:04 +05301180 /*check for header size too small*/
1181 if (*header_size < GPT_HEADER_SIZE) {
1182 dprintf(CRITICAL,"GPT Header size is too small\n");
1183 return 1;
1184 }
1185 /*check for header size too large*/
1186 if (*header_size > block_size) {
1187 dprintf(CRITICAL,"GPT Header size is too large\n");
1188 return 1;
1189 }
1190
1191 crc_val_org = GET_LWORD_FROM_BYTE(&buffer[HEADER_CRC_OFFSET]);
1192 /*Write CRC to 0 before we calculate the crc of the GPT header*/
1193 crc_val = 0;
1194 PUT_LONG(&buffer[HEADER_CRC_OFFSET], crc_val);
1195
1196 crc_val = crc32(~0L,buffer, *header_size) ^ (~0L);
1197 if (crc_val != crc_val_org) {
1198 dprintf(CRITICAL,"Header crc mismatch crc_val = %u with crc_val_org = %u\n", crc_val,crc_val_org);
1199 return 1;
1200 }
1201 else
1202 PUT_LONG(&buffer[HEADER_CRC_OFFSET], crc_val);
1203
1204 current_lba =
1205 GET_LLWORD_FROM_BYTE(&buffer[PRIMARY_HEADER_OFFSET]);
Ajay Dudanib01e5062011-12-03 23:23:42 -08001206 *first_usable_lba =
1207 GET_LLWORD_FROM_BYTE(&buffer[FIRST_USABLE_LBA_OFFSET]);
1208 *max_partition_count =
1209 GET_LWORD_FROM_BYTE(&buffer[PARTITION_COUNT_OFFSET]);
1210 *partition_entry_size =
1211 GET_LWORD_FROM_BYTE(&buffer[PENTRY_SIZE_OFFSET]);
vijay kumar24c9ed12015-04-28 13:05:04 +05301212 last_usable_lba =
1213 GET_LLWORD_FROM_BYTE(&buffer[LAST_USABLE_LBA_OFFSET]);
Kinson Chik4d7444f2011-09-13 15:48:51 -07001214
vijay kumar24c9ed12015-04-28 13:05:04 +05301215 /*current lba and GPT lba should be same*/
1216 if (!parse_secondary_gpt) {
1217 if (current_lba != GPT_LBA) {
1218 dprintf(CRITICAL,"GPT first usable LBA mismatch\n");
1219 return 1;
1220 }
1221 }
1222 /*check for first lba should be with in the valid range*/
1223 if (*first_usable_lba > (device_density/block_size)) {
1224 dprintf(CRITICAL,"Invalid first_usable_lba\n");
1225 return 1;
1226 }
1227 /*check for last lba should be with in the valid range*/
1228 if (last_usable_lba > (device_density/block_size)) {
1229 dprintf(CRITICAL,"Invalid last_usable_lba\n");
1230 return 1;
1231 }
1232 /*check for partition entry size*/
1233 if (*partition_entry_size != PARTITION_ENTRY_SIZE) {
1234 dprintf(CRITICAL,"Invalid parition entry size\n");
1235 return 1;
1236 }
1237
1238 if ((*max_partition_count) > (MIN_PARTITION_ARRAY_SIZE /(*partition_entry_size))) {
1239 dprintf(CRITICAL, "Invalid maximum partition count\n");
1240 return 1;
1241 }
1242
1243 partitions_for_block = block_size / (*partition_entry_size);
1244
1245 blocks_to_read = (*max_partition_count)/ partitions_for_block;
1246 if ((*max_partition_count) % partitions_for_block) {
1247 blocks_to_read += 1;
1248 }
1249
1250 new_buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP((blocks_to_read * block_size),CACHE_LINE));
1251
1252 if (!new_buffer)
1253 {
1254 dprintf(CRITICAL, "Failed to Allocate memory to read partition table\n");
1255 return 1;
1256 }
1257
1258 if (!flashing_gpt) {
1259 partition_0 = GET_LLWORD_FROM_BYTE(&buffer[PARTITION_ENTRIES_OFFSET]);
1260 /*start LBA should always be 2 in primary GPT*/
lijuang0b655852017-05-22 16:21:48 +08001261 if(partition_0 != 0x2 && !parse_secondary_gpt) {
vijay kumar24c9ed12015-04-28 13:05:04 +05301262 dprintf(CRITICAL, "Starting LBA mismatch\n");
lijuang0b655852017-05-22 16:21:48 +08001263 ret = 1;
vijay kumar24c9ed12015-04-28 13:05:04 +05301264 goto fail;
1265
1266 }
1267 /*read the partition entries to new_buffer*/
1268 ret = mmc_read((partition_0) * (block_size), (unsigned int *)new_buffer, (blocks_to_read * block_size));
1269 if (ret)
1270 {
1271 dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
1272 goto fail;
1273 }
1274 crc_val_org = GET_LWORD_FROM_BYTE(&buffer[PARTITION_CRC_OFFSET]);
1275
1276 crc_val = crc32(~0L,new_buffer, ((*max_partition_count) * (*partition_entry_size))) ^ (~0L);
1277 if (crc_val != crc_val_org) {
1278 dprintf(CRITICAL,"Partition entires crc mismatch crc_val= %u with crc_val_org= %u\n",crc_val,crc_val_org);
1279 ret = 1;
1280 }
1281 }
1282fail:
1283 free(new_buffer);
1284 return ret;
Kinson Chik4d7444f2011-09-13 15:48:51 -07001285}
Pavel Nedevb5ba62d2013-07-22 11:57:41 +03001286
1287bool partition_gpt_exists()
1288{
1289 return (gpt_partitions_exist != 0);
1290}
Channagoud Kadabifaf20f62014-10-21 22:22:37 -07001291
1292int partition_read_only(int index)
1293{
1294 return partition_entries[index].attribute_flag >> PART_ATT_READONLY_OFFSET;
1295}