blob: 35268685f3c8f9bc0358f8d0e968f3d0d96488c7 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <config.h>
7#include <common.h>
8#include <command.h>
9#include <errno.h>
10#include <mmc.h>
11#include <part.h>
12#include <memalign.h>
13#include <malloc.h>
14#include <linux/list.h>
15#include <div64.h>
16#include <amlogic/mmc_private.h>
17#include <amlogic/emmc_partitions.h>
18#include <amlogic/cpu_id.h>
19#include <part_efi.h>
20#include <amlogic/partition_table.h>
21#include <linux/compat.h>
ruixuan.li554d4e92023-02-28 17:11:25 +080022#include <u-boot/crc.h>
Bo Lv72d0e902023-01-02 14:27:34 +000023
24DECLARE_GLOBAL_DATA_PTR;
25/* using mbr*/
26#define CONFIG_PTBL_MBR (0)
27#if (CONFIG_PTBL_MBR)
28 /* cmpare partition name? */
29 #define CONFIG_CMP_PARTNAME (0)
30 /* cmpare partition mask */
31 #define CONFIG_CMP_PARTMASK (0)
32#else
33 #define CONFIG_CMP_PARTNAME (1)
34 #define CONFIG_CMP_PARTMASK (1)
35#endif
36/* debug info*/
37#define CONFIG_MPT_DEBUG (0)
38#define GPT_PRIORITY (1)
39
40#define apt_err(fmt, ...) printf( "%s()-%d: " fmt , \
41 __func__, __LINE__, ##__VA_ARGS__)
42
43#define apt_wrn(fmt, ...) printf( "%s()-%d: " fmt , \
44 __func__, __LINE__, ##__VA_ARGS__)
45#if (CONFIG_MPT_DEBUG)
46/* for detail debug info */
47#define apt_info(fmt, ...) printf( "%s()-%d: " fmt , \
48 __func__, __LINE__, ##__VA_ARGS__)
49#else
50#define apt_info(fmt, ...)
51#endif
52
53/* creat MBR for emmc */
54#define MAX_PNAME_LEN MAX_MMC_PART_NAME_LEN
55#define MAX_PART_COUNT MAX_MMC_PART_NUM
56
57/*
58 Global offset of reserved partition is 36MBytes
59 since MMC_BOOT_PARTITION_RESERVED is 32MBytes and
60 MMC_BOOT_DEVICE_SIZE is 4MBytes.
61 MMC_RESERVED_SIZE is 64MBytes for now.
62 layout detail inside reserved partition.
63 0x000000 - 0x003fff: partition table
64 0x004000 - 0x03ffff: storage key area (16k offset & 256k size)
65 0x400000 - 0x47ffff: dtb area (4M offset & 512k size)
66 0x480000 - 64MBytes: resv for other usage.
67 ...
68 */
69/*
70#define RSV_DTB_OFFSET_GLB (SZ_1M*40)
71#define RSV_DTB_SIZE (512*1024UL)
72#define RSV_PTBL_OFFSET (SZ_1M*0)
73#define RSV_PTBL_SIZE (16*1024UL)
74#define RSV_SKEY_OFFSET (16*1024UL)
75#define RSV_SKEY_SIZE (256*1024UL)
76#define RSV_DTB_OFFSET (SZ_1M*4)
77*/
78
79/* virtual partitions which are in "reserved" */
80#define MAX_MMC_VIRTUAL_PART_CNT (5)
81
82/* BinaryLayout of partition table stored in rsv area */
83struct ptbl_rsv {
84 char magic[4]; /* MPT */
85 unsigned char version[12]; /* binary version */
86 int count; /* partition count in using */
87 int checksum;
88 struct partitions partitions[MAX_MMC_PART_NUM];
89};
90
91/* partition table for innor usage*/
92struct _iptbl {
93 struct partitions *partitions;
94 int count; /* partition count in use */
95};
96
97unsigned device_boot_flag = 0xff;
98extern bool is_partition_checked;
99
100#ifndef CONFIG_AML_MMC_INHERENT_PART
101/* fixme, name should be changed as aml_inherent_ptbl */
102struct partitions emmc_partition_table[] = {
103 PARTITION_ELEMENT(MMC_BOOT_NAME, MMC_BOOT_DEVICE_SIZE, 0),
104 PARTITION_ELEMENT(MMC_RESERVED_NAME, MMC_RESERVED_SIZE, 0),
105 /* prior partitions, same partition name with dts*/
106 /* partition size will be override by dts*/
107 PARTITION_ELEMENT(MMC_CACHE_NAME, 0, 0),
108 PARTITION_ELEMENT(MMC_ENV_NAME, MMC_ENV_SIZE, 0),
109};
110
111struct virtual_partition virtual_partition_table[] = {
112 /* partition for name idx, off & size will not be used! */
113#if (CONFIG_PTBL_MBR)
114 VIRTUAL_PARTITION_ELEMENT(MMC_MBR_NAME, MMC_MBR_OFFSET, MMC_MBR_SIZE),
115#endif
116 VIRTUAL_PARTITION_ELEMENT(MMC_BOOT_NAME0, 0, 0),
117 VIRTUAL_PARTITION_ELEMENT(MMC_BOOT_NAME1, 0, 0),
118
119 /* virtual partition in reserved partition, take care off and size */
120#ifdef CONFIG_AML_PARTITION
121 VIRTUAL_PARTITION_ELEMENT(MMC_TABLE_NAME, MMC_TABLE_OFFSET, MMC_TABLE_SIZE),
122#endif
123 VIRTUAL_PARTITION_ELEMENT(MMC_KEY_NAME, EMMCKEY_RESERVE_OFFSET, MMC_KEY_SIZE),
124 VIRTUAL_PARTITION_ELEMENT(MMC_PATTERN_NAME, CALI_PATTERN_OFFSET, CALI_PATTERN_SIZE),
125 VIRTUAL_PARTITION_ELEMENT(MMC_MAGIC_NAME, MAGIC_OFFSET, MAGIC_SIZE),
126 VIRTUAL_PARTITION_ELEMENT(MMC_RANDOM_NAME, RANDOM_OFFSET, RANDOM_SIZE),
127#ifndef DTB_BIND_KERNEL
128 VIRTUAL_PARTITION_ELEMENT(MMC_DTB_NAME, DTB_OFFSET, DTB_SIZE),
129#endif
130 VIRTUAL_PARTITION_ELEMENT(MMC_FASTBOOT_CONTEXT_NAME,
131 FASTBOOT_CONTEXT_OFFSET, FASTBOOT_CONTEXT_SIZE),
132 VIRTUAL_PARTITION_ELEMENT(MMC_DDR_PARAMETER_NAME,DDR_PARAMETER_OFFSET, DDR_PARAMETER_SIZE),
133};
134
135int get_emmc_partition_arraysize(void)
136{
137 return ARRAY_SIZE(emmc_partition_table);
138}
139
140int get_emmc_virtual_partition_arraysize(void)
141{
142 return ARRAY_SIZE(virtual_partition_table);
143}
144
145#endif
146
147void __attribute__((unused)) _dump_part_tbl(struct partitions *p, int count)
148{
149 int i = 0;
150 apt_info("count %d\n", count);
151 while (i < count) {
152 printf("%02d %10s %016llx %016llx\n", i, p[i].name, p[i].offset, p[i].size);
153 i++;
154 }
155 return;
156}
157
158static int _get_part_index_by_name(struct partitions *tbl,
159 int cnt, const char *name)
160{
161 int i = 0;
162 struct partitions *part = NULL;
163
164 while (i < cnt) {
165 part = &tbl[i];
166 if (!strcmp(name, part->name)) {
167 apt_info("find %s @ tbl[%d]\n", name, i);
168 break;
169 }
170 i++;
171 };
172
173 if (i == cnt) {
174 i = -1;
175 apt_wrn("do not find match in table %s\n", name);
176 }
177
178 if (gpt_partition)
179 i += 1;
180
181 return i;
182}
183
184static struct partitions *_find_partition_by_name(struct partitions *tbl,
185 int cnt, const char *name)
186{
187 int i = 0;
188 struct partitions *part = NULL;
189
190 while (i < cnt) {
191 part = &tbl[i];
192 if (!strcmp(name, part->name)) {
193 apt_info("find %s @ tbl[%d]\n", name, i);
194 break;
195 }
196 i++;
197 };
198 if (i == cnt) {
199 part = NULL;
200 apt_wrn("do not find match in table %s\n", name);
201 }
202 return part;
203}
204
205/* fixme, must called after offset was calculated. */
206static ulong _get_inherent_offset(const char *name)
207{
208 struct partitions *part;
209
210 part = _find_partition_by_name(emmc_partition_table,
211 get_emmc_partition_arraysize(), name);
212 if (NULL == part)
213 return -1;
214 else
215 return part->offset;
216}
217/* partition table (Emmc Partition Table) */
218struct _iptbl *p_iptbl_ept = NULL;
219
220/* trans byte into lba manner for rsv area read/write */
221#ifdef CONFIG_AML_PARTITION
222static ulong _mmc_rsv_read(struct mmc *mmc, ulong offset, ulong size, void * buffer)
223{
224 lbaint_t _blk, _cnt;
225 if (0 == size)
226 return 0;
227
228 _blk = offset / mmc->read_bl_len;
229 _cnt = size / mmc->read_bl_len;
230 _cnt = blk_dread(mmc_get_blk_desc(mmc), _blk, _cnt, buffer);
231
232 return (ulong)(_cnt * mmc->read_bl_len);
233}
234
235static ulong _mmc_rsv_write(struct mmc *mmc, ulong offset, ulong size, void * buffer)
236{
237 lbaint_t _blk, _cnt;
238 if (0 == size)
239 return 0;
240
241 _blk = offset / mmc->read_bl_len;
242 _cnt = size / mmc->read_bl_len;
243 _cnt = blk_dwrite(mmc_get_blk_desc(mmc), _blk, _cnt, buffer);
244
245 return (ulong)(_cnt * mmc->read_bl_len);
246}
247#endif
248
ruixuan.li554d4e92023-02-28 17:11:25 +0800249int fill_ept_by_gpt(struct mmc *mmc)
Bo Lv72d0e902023-01-02 14:27:34 +0000250{
251 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
252 gpt_entry *gpt_pte = NULL;
253 int i, k;
254 size_t efiname_len, dosname_len;
ruixuan.li554d4e92023-02-28 17:11:25 +0800255 struct _iptbl *ept = NULL;
256 struct partitions *partitions = NULL;
257
258 if (!p_iptbl_ept)
259 return 1;
260
261 ept = p_iptbl_ept;
262 partitions = ept->partitions;
Bo Lv72d0e902023-01-02 14:27:34 +0000263
264 if (!dev_desc) {
265 printf("%s: Invalid Argument(s)\n", __func__);
266 return 1;
267 }
268
269 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
270
271 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
272 gpt_head, &gpt_pte) != 1) {
273 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
274 gpt_head, &gpt_pte) != 1) {
275 printf("%s: invalid gpt\n", __func__);
276 return 1;
277 }
278 printf("%s: *** Using Backup GPT ***\n", __func__);
279 }
280
281 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
282 if (!is_pte_valid(&gpt_pte[i]))
283 break;
284
285 partitions[i].offset = le64_to_cpu(gpt_pte[i].starting_lba << 9ULL);
286 partitions[i].size = ((le64_to_cpu(gpt_pte[i].ending_lba) + 1) -
287 le64_to_cpu(gpt_pte[i].starting_lba)) << 9ULL;
288 /* mask flag */
289 partitions[i].mask_flags =
290 (uint32_t)le64_to_cpu(gpt_pte[i].attributes.fields.type_guid_specific);
291 /* partition name */
292 efiname_len = sizeof(gpt_pte[i].partition_name)
293 / sizeof(efi_char16_t);
294 dosname_len = sizeof(partitions[i].name);
295
296 memset(partitions[i].name, 0, sizeof(partitions[i].name));
297 for (k = 0; k < min(dosname_len, efiname_len); k++)
298 partitions[i].name[k] = (char)gpt_pte[i].partition_name[k];
299
300 if (strcmp(partitions[i].name, "boot_a") == 0) {
301 has_boot_slot = 1;
302 printf("set has_boot_slot = 1\n");
303 } else if (strcmp(partitions[i].name, "boot") == 0) {
304 has_boot_slot = 0;
305 printf("set has_boot_slot = 0\n");
306 }
307 if (strcmp(partitions[i].name, "system_a") == 0)
308 has_system_slot = 1;
309 else if (strcmp(partitions[i].name, "system") == 0)
310 has_system_slot = 0;
311
312 if (strcmp(partitions[i].name, "super") == 0) {
313 dynamic_partition = true;
314 env_set("partition_mode", "dynamic");
315 printf("enable dynamic_partition\n");
316 }
317
318 if (strncmp(partitions[i].name, "vendor_boot", 11) == 0) {
319 vendor_boot_partition = true;
320 env_set("vendor_boot_mode", "true");
321 printf("enable vendor_boot\n");
322 }
323 }
324 ept->count = i;
325 free(gpt_pte);
326 return 0;
327}
328
329/*
330 * 1. gpt is writed on emmc
331 * parse gpt and compose ept and part_table
332 *
333 */
334int get_ept_from_gpt(struct mmc *mmc)
335{
ruixuan.li554d4e92023-02-28 17:11:25 +0800336 struct partitions *ptbl;
Bo Lv72d0e902023-01-02 14:27:34 +0000337
ruixuan.li554d4e92023-02-28 17:11:25 +0800338 if (!p_iptbl_ept)
339 return -1;
340
341 ptbl = p_iptbl_ept->partitions;
342
343 if (part_table && part_table[0].offset != 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000344 memcpy(ptbl, part_table, sizeof(struct partitions) * parts_total_num);
345 p_iptbl_ept->count = parts_total_num;
346 printf("get ept from part_table success\n");
347 gpt_partition = true;
348 return 0;
ruixuan.li554d4e92023-02-28 17:11:25 +0800349 } else if (!fill_ept_by_gpt(mmc)) {
350 printf("get ept from gpt success\n");
351 gpt_partition = true;
352 return 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000353 }
354
ruixuan.li554d4e92023-02-28 17:11:25 +0800355 return -1;
Bo Lv72d0e902023-01-02 14:27:34 +0000356}
357
358static struct partitions * get_ptbl_from_dtb(struct mmc *mmc)
359{
360 struct partitions * ptbl = NULL;
361#ifdef CONFIG_AML_PARTITION
362#ifndef DTB_BIND_KERNEL
363 unsigned char * buffer = NULL;
364 ulong ret, offset;
365 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
366
367 /* try get dtb table from ddr, which may exsit while usb burning */
368 if (NULL == get_partitions()) {
369 /* if failed, try rsv dtb area then. */
370 buffer = malloc(vpart->size * DTB_COPIES);
371 if (NULL == buffer) {
372 apt_err("Can not alloc enough buffer\n");
373 goto _err;
374 }
375 offset = _get_inherent_offset(MMC_RESERVED_NAME) + vpart->offset;
376 ret = _mmc_rsv_read(mmc, offset, (vpart->size * DTB_COPIES), buffer);
377 if (ret != (vpart->size * DTB_COPIES)) {
378 apt_err("Can not alloc enough buffer\n");
379 goto _err1;
380 }
381 /* parse it */
382 if (get_partition_from_dts(buffer)) {
383 apt_err("get partition table from dts faild\n");
384 goto _err1;
385 }
386 /* double check part_table(glb) */
387 if (NULL == get_partitions()) {
388 goto _err1;
389 }
390 apt_info("get partition table from dts successfully\n");
391
392 free(buffer);
393 buffer = NULL;
394 }
395#endif
396#endif
397 /* asign partition info to *ptbl */
398 ptbl = get_partitions();
399 return ptbl;
400#ifdef CONFIG_AML_PARTITION
401#ifndef DTB_BIND_KERNEL
402_err1:
403 if (buffer)
404 free(buffer);
405_err:
406 free (ptbl);
407 return NULL;
408#endif
409#endif
410}
411
412static struct partitions *is_prio_partition(struct _iptbl *list, struct partitions *part)
413{
414 int i;
415 struct partitions *plist = NULL;
416
417 if (list->count == 0)
418 goto _out;
419
420 apt_info("count %d\n", list->count);
421 for (i=0; i<list->count; i++) {
422 plist = &list->partitions[i];
423 apt_info("%d: %s, %s\n", i, part->name, plist->name);
424 if (!strcmp(plist->name, part->name)) {
425 apt_info("%s is prio in list[%d]\n", part->name, i);
426 break;
427 }
428 }
429 if (i == list->count)
430 plist = NULL;
431_out:
432 return plist;
433}
434
435/* calculate offset of each partitions.
436 bottom is a flag for considering
437 */
438static int _calculate_offset(struct mmc *mmc, struct _iptbl *itbl, u32 bottom)
439{
440 int i;
441 struct partitions *part;
442 ulong gap = PARTITION_RESERVED;
443 int ret = 0;
444
445 if (itbl->count <= 0)
446 return -1;
447 part = itbl->partitions;
448#if (CONFIG_MPT_DEBUG)
449 _dump_part_tbl(part, itbl->count);
450#endif
451
452 if (!strcmp(part->name, "bootloader")) {
453 part->offset = 0;
454 gap = MMC_BOOT_PARTITION_RESERVED;
455 }
456 for (i=1; i<itbl->count; i++) {
457 /**/
458 part[i].offset = part[i-1].offset + part[i-1].size + gap;
459 /* check capacity overflow ?*/
460 if (((part[i].offset + part[i].size) > mmc->capacity) ||
461 (part[i].size == -1)) {
462 part[i].size = mmc->capacity - part[i].offset;
463 /* reserv space @ the bottom */
464 if (bottom && (part[i].size > MMC_BOTTOM_RSV_SIZE)) {
465 apt_info("reserv %d bytes at bottom\n", MMC_BOTTOM_RSV_SIZE);
466 part[i].size -= MMC_BOTTOM_RSV_SIZE;
467 }
468 break;
469 }
470 if ((part[i].mask_flags & 0x100) != 0)
471 gap = PARTITION_MIN_RESERVED;
472 else
473 gap = PARTITION_RESERVED;
474 }
475
476#if (ADD_LAST_PARTITION)
477 i += 1;
478 if (i == itbl->count - 1 && bottom == 1) {
479 part[i - 1].size -= gap + part[i].size;
480 part[i].offset = part[i - 1].offset + part[i - 1].size + gap;
481 }
482#endif
483
484 if (i < (itbl->count - 1)) {
485 apt_err("too large partition table for current emmc, overflow!\n");
486 ret = -1;
487 }
488#if (CONFIG_MPT_DEBUG)
489 _dump_part_tbl(part, itbl->count);
490#endif
491 return ret;
492}
493
494static void compose_ept(struct _iptbl *dtb, struct _iptbl *inh,
495 struct _iptbl *ept)
496{
497 int i;
498 struct partitions *partition = NULL;
499 struct partitions *dst, *src, *prio;
500
501 /* override inh info by dts */
502 apt_info("dtb %p, inh %p, ept %p\n", dtb, inh, ept);
503 apt_info("ept->partitions %p\n", ept->partitions);
504 partition = ept->partitions;
505 apt_info("partition %p\n", partition);
506 for (i=0; i<MAX_PART_COUNT; i++) {
507 apt_info("i %d, ept->count %d\n", i, ept->count);
508 dst = &partition[ept->count];
509 src = (i < inh->count) ? &inh->partitions[i]:&dtb->partitions[i-inh->count];
510
511 prio = is_prio_partition(ept, src);
512 if (prio) {
513 /* override prio partition by new */
514 apt_info("override %d: %s\n", ept->count, prio->name);
515 //*prio = *src;
516 dst = prio;
517 } else
518 ept->count ++;
519 *dst = *src;
520 if (-1 == src->size) {
521 apt_info("break! %s\n", src->name);
522 break;
523 }
524 }
525
526#if (ADD_LAST_PARTITION)
527 i += 1;
528 dst = &partition[ept->count];
529 src = &dtb->partitions[i - inh->count];
530 ept->count += 1;
531 *dst = *src;
532#endif
533
534 return;
535}
536#ifdef CONFIG_AML_PARTITION
537static int _get_version(unsigned char * s)
538{
539 int version = 0;
540 if (!strncmp((char *)s, MMC_MPT_VERSION_2, sizeof(MMC_MPT_VERSION_2)))
541 version = 2;
542 else if (!strncmp((char *)s, MMC_MPT_VERSION_1, sizeof(MMC_MPT_VERSION_1)))
543 version = 1;
544 else
545 version = -1;
546
547 return version;
548}
549
550/* calc checksum.
551 there's a bug on v1 which did not calculate all the partitions.
552 */
553static int _calc_iptbl_check_v2(struct partitions * part, int count)
554{
555 int ret = 0, i;
556 int size = count * sizeof(struct partitions) >> 2;
557 int *buf = (int *)part;
558
559 for (i = 0; i < size; i++)
560 ret +=buf[i];
561
562 return ret;
563}
564
565static int _calc_iptbl_check_v1(struct partitions *part, int count)
566{
567 int i, j;
568 u32 checksum = 0, *p;
569
570 for (i = 0; i < count; i++) {
571 p = (u32*)part;
572 /*BUG here, do not fix it!!*/
573 for (j = sizeof(struct partitions)/sizeof(checksum); j > 0; j--) {
574 checksum += *p;
575 p++;
576 }
577 }
578
579 return checksum;
580}
581
582static int _calc_iptbl_check(struct partitions * part, int count, int version)
583{
584 if (1 == version)
585 return _calc_iptbl_check_v1(part, count);
586 else if (2 == version)
587 return _calc_iptbl_check_v2(part, count);
588 else
589 return -1;
590}
591
592/* ept is malloced out side */
593static int _cpy_iptbl(struct _iptbl * dst, struct _iptbl * src)
594{
595 int ret = 0;
596 if (!dst || !src) {
597 apt_err("invalid arg %s\n", !dst ? "dst" : "src");
598 ret = -1;
599 goto _out;
600 }
601 if (!dst->partitions || !src->partitions) {
602 apt_err("invalid arg %s->partitions\n", !dst ? "dst" : "src");
603 ret = -2;
604 goto _out;
605 }
606
607 dst->count = src->count;
608 memcpy(dst->partitions, src->partitions, sizeof(struct partitions) * src->count);
609
610_out:
611 return ret;
612}
613
614/* get ptbl from rsv area from emmc */
615static int get_ptbl_rsv(struct mmc *mmc, struct _iptbl *rsv)
616{
617 struct ptbl_rsv * ptbl_rsv = NULL;
618 uchar * buffer = NULL;
619 ulong size, offset;
620 int checksum, version, ret = 0;
621 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_TABLE_NAME);
622
623 size = (sizeof(struct ptbl_rsv) + 511) / 512 * 512;
624 if (vpart->size < size) {
625 apt_err("too much partitions\n");
626 ret = -1;
627 goto _out;
628 }
629 buffer = malloc(size);
630 if (NULL == buffer) {
631 apt_err("no enough memory for ptbl rsv\n");
632 ret = -2;
633 goto _out;
634 }
635 /* read it from emmc. */
636 offset = _get_inherent_offset(MMC_RESERVED_NAME) + vpart->offset;
637 if (size != _mmc_rsv_read(mmc, offset, size, buffer)) {
638 apt_err("read ptbl from rsv failed\n");
639 ret = -3;
640 goto _out;
641 }
642
643 ptbl_rsv = (struct ptbl_rsv *) buffer;
644 apt_info("magic %3.3s, version %8.8s, checksum %x\n", ptbl_rsv->magic,
645 ptbl_rsv->version, ptbl_rsv->checksum);
646 /* fixme, check magic ?*/
647 if (strncmp(ptbl_rsv->magic, MMC_PARTITIONS_MAGIC, sizeof(MMC_PARTITIONS_MAGIC))) {
648 apt_err("magic faild %s, %3.3s\n", MMC_PARTITIONS_MAGIC, ptbl_rsv->magic);
649 ret = -4;
650 goto _out;
651 }
652 /* check version*/
653 version = _get_version(ptbl_rsv->version);
654 if (version < 0) {
655 apt_err("version faild %s, %3.3s\n", MMC_PARTITIONS_MAGIC, ptbl_rsv->magic);
656 ret = -5;
657 goto _out;
658 }
659 if (ptbl_rsv->count > MAX_MMC_PART_NUM) {
660 apt_err("invalid partition count %d\n", ptbl_rsv->count);
661 ret = -1;
662 goto _out;
663 }
664 /* check sum */
665 checksum = _calc_iptbl_check(ptbl_rsv->partitions, ptbl_rsv->count, version);
666 if (checksum != ptbl_rsv->checksum) {
667 apt_err("checksum faild 0x%x, 0x%x\n", ptbl_rsv->checksum, checksum);
668 ret = -6;
669 goto _out;
670 }
671
672 rsv->count = ptbl_rsv->count;
673 memcpy(rsv->partitions, ptbl_rsv->partitions, rsv->count * sizeof(struct partitions));
674
675_out:
676 if (buffer)
677 free (buffer);
678 return ret;
679}
680
681/* update partition tables from src
682 if success, return 0;
683 else, return 1
684 */
685static int update_ptbl_rsv(struct mmc *mmc, struct _iptbl *src)
686{
687 struct ptbl_rsv *ptbl_rsv = NULL;
688 uchar *buffer;
689 ulong size, offset;
690 int ret = 0, version;
691 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_TABLE_NAME);
692
693 size = (sizeof(struct ptbl_rsv) + 511) / 512 * 512;
694 buffer = malloc(size);
695 if (NULL == buffer) {
696 apt_err("no enough memory for ptbl rsv\n");
697 return -1;
698 }
699 memset(buffer, 0 , size);
700 /* version, magic and checksum */
701 ptbl_rsv = (struct ptbl_rsv *) buffer;
702 strcpy((char *)ptbl_rsv->version, MMC_MPT_VERSION);
703 strcpy(ptbl_rsv->magic, MMC_PARTITIONS_MAGIC);
704 if (src->count > MAX_MMC_PART_NUM) {
705 apt_err("too much partitions\n");
706 ret = -1;
707 goto _err;
708 }
709 ptbl_rsv->count = src->count;
710 memcpy(ptbl_rsv->partitions, src->partitions,
711 sizeof(struct partitions)*src->count);
712 version = _get_version(ptbl_rsv->version);
713 ptbl_rsv->checksum = _calc_iptbl_check(src->partitions, src->count, version);
714 /* write it to emmc. */
715 apt_info("magic %3.3s, version %8.8s, checksum %x\n", ptbl_rsv->magic, ptbl_rsv->version, ptbl_rsv->checksum);
716 offset = _get_inherent_offset(MMC_RESERVED_NAME) + vpart->offset;
717 if (_mmc_rsv_write(mmc, offset, size, buffer) != size) {
718 apt_err("write ptbl to rsv failed\n");
719 ret = -1;
720 goto _err;
721 }
722_err:
723 free (buffer);
724 return ret;
725}
726
727static void _free_iptbl(struct _iptbl *iptbl)
728{
729 if (iptbl && iptbl->partitions) {
730 free(iptbl->partitions);
731 iptbl->partitions = NULL;
732 }
733 if (iptbl) {
734 free(iptbl);
735 iptbl = NULL;
736 }
737
738 return;
739}
740
741#endif
742static int _cmp_partition(struct partitions *dst, struct partitions *src, int override)
743{
744 int ret = 0;
745#if (CONFIG_CMP_PARTNAME)
746 if (strncmp(dst->name, src->name, sizeof(src->name)))
747 ret = -2;
748#endif
749 if (dst->size != src->size)
750 ret = -3;
751 if (dst->offset != src->offset)
752 ret = -4;
753#if (CONFIG_CMP_PARTMASK)
754 if (dst->mask_flags != src->mask_flags)
755 ret = -5;
756#endif
757
758 if (ret && (!override)) {
759 apt_err("name: %10.10s<->%10.10s\n", dst->name, src->name);
760 apt_err("size: %llx<->%llx\n", dst->size, src->size);
761 apt_err("offset: %llx<->%llx\n", dst->offset, src->offset);
762 apt_err("mask: %08x<->%08x\n", dst->mask_flags, src->mask_flags);
763 }
764
765 if (override) {
766 *dst = *src;
767 ret = 0;
768 }
769
770 return ret;
771}
772
773/* compare partition tables
774 if same, do nothing then return 0;
775 else, print the diff ones and return -x
776 -1:count
777 -2:name
778 -3:size
779 -4:offset
780 */
781static int _cmp_iptbl(struct _iptbl * dst, struct _iptbl * src)
782{
783 int ret = 0, i = 0;
784 struct partitions *dstp;
785 struct partitions *srcp;
786
787 if (dst->count != src->count) {
788 apt_err("partition count is not same %d:%d\n", dst->count, src->count);
789 ret = -1;
790 goto _out;
791 }
792
793 while (i < dst->count) {
794 dstp = &dst->partitions[i];
795 srcp = &src->partitions[i];
796 ret = _cmp_partition(dstp, srcp, 0);
797 if (ret) {
798 env_set("part_changed", "1");
799 apt_err("partition %d has changed\n", i);
800 break;
801 }
802 i++;
803 }
804
805_out:
806 return ret;
807}
808
809/* iptbl buffer opt. */
810static int _zalloc_iptbl(struct _iptbl **_iptbl)
811{
812 int ret = 0;
813 struct _iptbl *iptbl;
814 struct partitions *partition = NULL;
815
816 partition = malloc(sizeof(struct partitions)*MAX_PART_COUNT);
817 if (NULL == partition) {
818 ret = -1;
819 apt_err("no enough memory for partitions\n");
820 goto _out;
821 }
822
823 iptbl = malloc(sizeof(struct _iptbl));
824 if (NULL == iptbl) {
825 ret = -2;
826 apt_err("no enough memory for ept\n");
827 free(partition);
828 goto _out;
829 }
830 memset(partition, 0, sizeof(struct partitions)*MAX_PART_COUNT);
831 memset(iptbl, 0, sizeof(struct _iptbl));
832
833 iptbl->partitions = partition;
834 apt_info("iptbl %p, partition %p, iptbl->partitions %p\n",
835 iptbl, partition, iptbl->partitions);
836 *_iptbl = iptbl;
837_out:
838 return ret;
839}
840
841
842/*
843 * fixme, need check space size later.
844 */
845
846static inline int le32_to_int(unsigned char *le32)
847{
848 return ((le32[3] << 24) +
849 (le32[2] << 16) +
850 (le32[1] << 8) +
851 le32[0]
852 );
853}
854
855static int test_block_type(unsigned char *buffer)
856{
857 int slot;
858 struct dos_partition *p;
859
860 if ((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
861 (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
862 return (-1);
863 } /* no DOS Signature at all */
864 p = (struct dos_partition *)&buffer[DOS_PART_TBL_OFFSET];
865 for (slot = 0; slot < 3; slot++) {
866 if (p->boot_ind != 0 && p->boot_ind != 0x80) {
867 if (!slot &&
868 (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],
869 "FAT", 3) == 0 ||
870 strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],
871 "FAT32", 5) == 0)) {
872 return DOS_PBR; /* is PBR */
873 } else {
874 return -1;
875 }
876 }
877 }
878 return DOS_MBR; /* Is MBR */
879}
880
881//DOS_MBR OR DOS_PBR
882/*
883 * re-constructed iptbl from mbr&ebr infos.
884 * memory for iptbl_mbr must be alloced outside.
885 *
886 */
887static void _construct_ptbl_by_mbr(struct mmc *mmc, struct _iptbl *iptbl_mbr)
888{
889 int ret,i;
890 int flag = 0;
891 lbaint_t read_offset = 0;
892 int part_num = 0;
893 int primary_num = 0;
894 uint64_t logic_start = 0;
895 uint64_t extended_start = 0;
896 struct dos_partition *pt;
897 struct partitions *partitions = iptbl_mbr->partitions;
898
899 apt_info("aml MBR&EBR debug...\n");
900 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 512);
901 for (;;) {
902 apt_info("**%02d: read_offset %016llx\n", part_num, (uint64_t)read_offset<<9);
903 ret = blk_dread(mmc_get_blk_desc(mmc), read_offset, 1, buffer);
904 if (read_offset == 0)
905 flag = 1;
906 else
907 flag = 0;
908 /* debug code */
909 // print_buffer(0,buffer,1,512,16);
910 if (ret != 1) {
911 apt_err("ret %d fail to read current ebr&mbr from emmc! \n", ret);
912 break;
913 }
914 ret = test_block_type(buffer);
915 if (ret != 0 && ret != 1) {
916 apt_err("invalid magic value: 0x%02x%02x\n",
917 buffer[DOS_PART_MAGIC_OFFSET], buffer[DOS_PART_MAGIC_OFFSET + 1]);
918 break;
919 }
920
921 pt = (dos_partition_t *)(&buffer[0] + DOS_PART_TBL_OFFSET);
922 for (i = 0; i < 4; i++, pt++) {
923 if ( (pt->boot_ind == 0x00 || pt->boot_ind == 0x80) && pt->sys_ind == 0x83 ) {
924 //emmc_partition[part_num]->name = NULL;
925 partitions[part_num].offset = ((uint64_t)(le32_to_int(pt->start4)+read_offset) << 9ULL);
926 partitions[part_num].size = (uint64_t)le32_to_int(pt->size4) << 9ULL;
927 partitions[part_num].mask_flags = pt->sys_ind;
928
929 apt_info("--partition[%d]: %016llx, %016llx, 0x%08x \n",
930 part_num, partitions[part_num].offset,
931 partitions[part_num].size,
932 le32_to_int(pt->size4));
933 part_num++;
934 if ( flag )
935 primary_num++;
936 }else{/* get the next extended partition info */
937 if ( pt->boot_ind == 0x00 && pt->sys_ind == 0x05) {
938 logic_start = (uint64_t)le32_to_int (pt->start4);
939 //logic_size = (uint64_t)le32_to_int (pt->size4);
940 }
941 }
942 }
943 /* mbr & ebr debug infos */
944 apt_info("******%02d: read_offset=%016llx, logic_start=%016llx\n",
945 part_num,(uint64_t)read_offset*512ULL,logic_start*512ULL);
946
947 if (part_num == primary_num) {
948 extended_start = logic_start;
949 read_offset = extended_start;
950 }else
951 read_offset = extended_start + logic_start;
952 if (logic_start == 0)
953 break;
954 logic_start = 0;
955
956 }
957 iptbl_mbr->count = part_num;
958 apt_info("iptbl_mbr->count = %d\n", iptbl_mbr->count);
959
960 return;
961}
962
963static int __attribute__((unused)) _check_ptbl_mbr(struct mmc *mmc, struct _iptbl *ept)
964{
965 int ret = 0;
966 /* re-constructed by mbr */
967 struct _iptbl *iptbl_mbr = NULL;
968 struct partitions *partitions = NULL;
969
970 iptbl_mbr = malloc(sizeof(struct _iptbl));
971 if (NULL == iptbl_mbr) {
972 apt_err("no enough memory for iptbl_mbr\n");
973 return -1;
974 }
975 memset(iptbl_mbr , 0, sizeof(struct _iptbl));
976 partitions = (struct partitions *)malloc(sizeof(struct partitions) * DOS_PARTITION_COUNT);
977 if (NULL == partitions) {
978 apt_err("no enough memory for partitions\n");
979 free(iptbl_mbr);
980 return -1;
981 }
982 memset(partitions, 0, sizeof(struct partitions) * DOS_PARTITION_COUNT);
983 iptbl_mbr->partitions = partitions;
984
985 _construct_ptbl_by_mbr(mmc, iptbl_mbr);
986
987 ret = _cmp_iptbl(iptbl_mbr, ept);
988
989 if (partitions)
990 free(partitions);
991 if (iptbl_mbr)
992 free(iptbl_mbr);
993
994 apt_wrn("MBR is %s\n", ret?"Improper!":"OK!");
995 return ret;
996}
997
998/* construct a partition table entry of EBR */
999static int _construct_ebr_1st_entry(struct _iptbl *p_iptbl,struct dos_partition *p_ebr, int part_num )
1000{
1001 uint64_t start_offset = 0;
1002 uint64_t logic_size = 0;
1003
1004 p_ebr->boot_ind = 0x00;
1005 p_ebr->sys_ind = 0x83;
1006 /* Starting = relative offset between this EBR sector and the first sector of the logical partition
1007 * the gap between two partition is a fixed value of PARTITION_RESERVED ,otherwise the emmc partition
1008 * is different with reserved */
1009 start_offset = PARTITION_RESERVED >> 9;
1010 /* Number of sectors = total count of sectors for this logical partition */
1011 // logic_size = (p_iptbl->partitions[part_num].size) >> 9ULL;
1012 logic_size = lldiv(p_iptbl->partitions[part_num].size, 512);
1013 apt_info("*** %02d: size 0x%016llx, logic_size 0x%016llx\n", part_num, p_iptbl->partitions[part_num].size, logic_size);
1014 memcpy((unsigned char *)(p_ebr->start4), &start_offset, 4);
1015 memcpy((unsigned char *)(p_ebr->size4), &logic_size, 4);
1016 return 0;
1017}
1018
1019static int _construct_ebr_2nd_entry(struct _iptbl *p_iptbl, struct dos_partition *p_ebr, int part_num)
1020{
1021 uint64_t start_offset = 0;
1022 uint64_t logic_size = 0;
1023
1024 if ((part_num+2) > p_iptbl->count)
1025 return 0;
1026
1027 p_ebr->boot_ind = 0x00;
1028 p_ebr->sys_ind = 0x05;
1029 /* Starting sector = LBA address of next EBR minus LBA address of extended partition's first EBR */
1030 start_offset = (p_iptbl->partitions[part_num+1].offset - PARTITION_RESERVED -
1031 (p_iptbl->partitions[3].offset - PARTITION_RESERVED)) >> 9;
1032 /* total count of sectors for next logical partition, but count starts from the next EBR sector */
1033 logic_size = (p_iptbl->partitions[part_num+1].size + PARTITION_RESERVED) >> 9;
1034
1035 memcpy((unsigned char *)(p_ebr->start4), &start_offset, 4);
1036 memcpy((unsigned char *)(p_ebr->size4), &logic_size, 4);
1037
1038 return 0;
1039}
1040
1041/* construct a partition table entry of MBR OR EBR */
1042static int _construct_mbr_entry(struct _iptbl *p_iptbl, struct dos_partition *p_entry, int part_num)
1043{
1044 uint64_t start_offset = 0;
1045 uint64_t primary_size = 0;
1046 uint64_t extended_size = 0;
1047 int i;
1048 /* the entry is active or not */
1049 p_entry->boot_ind = 0x00;
1050
1051 if (part_num == 3) {/* the logic partition entry */
1052 /* the entry type */
1053 p_entry->sys_ind = 0x05;
1054 start_offset = (p_iptbl->partitions[3].offset - PARTITION_RESERVED) >> 9;
1055 for ( i = 3;i< p_iptbl->count;i++)
1056 extended_size = p_iptbl->partitions[i].size >> 9;
1057
1058 memcpy((unsigned char *)p_entry->start4, &start_offset, 4);
1059 memcpy((unsigned char *)p_entry->size4, &extended_size, 4);
1060 }else{/* the primary partition entry */
1061 /* the entry type */
1062 p_entry->sys_ind = 0x83;
1063 start_offset = (p_iptbl->partitions[part_num].offset) >> 9;
1064 primary_size = (p_iptbl->partitions[part_num].size)>>9;
1065 memcpy((unsigned char *)p_entry->start4, &start_offset, 4);
1066 memcpy((unsigned char *)p_entry->size4, &primary_size, 4);
1067 }
1068
1069 return 0;
1070}
1071
1072static int _construct_mbr_or_ebr(struct _iptbl *p_iptbl, struct dos_mbr_or_ebr *p_br,
1073 int part_num, int type)
1074{
1075 int i;
1076
1077 if (DOS_MBR == type) {
1078 /* construct a integral MBR */
1079 for (i = 0; i<4 ; i++)
1080 _construct_mbr_entry(p_iptbl, &p_br->part_entry[i], i);
1081
1082 }else{
1083 /* construct a integral EBR */
1084 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET] = 'F';
1085 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 1] = 'A';
1086 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 2] = 'T';
1087 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 3] = '3';
1088 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 4] = '2';
1089
1090 _construct_ebr_1st_entry(p_iptbl, &p_br->part_entry[0], part_num);
1091 _construct_ebr_2nd_entry(p_iptbl, &p_br->part_entry[1], part_num);
1092 }
1093
1094 p_br->magic[0] = 0x55 ;
1095 p_br->magic[1] = 0xAA ;
1096 return 0;
1097}
1098
1099static __attribute__((unused)) int _update_ptbl_mbr(struct mmc *mmc, struct _iptbl *p_iptbl)
1100{
1101 int ret = 0, start_blk = 0, blk_cnt = 1;
1102 unsigned char *src;
1103 int i;
1104 struct dos_mbr_or_ebr *mbr;
1105 struct _iptbl *ptb ;
1106
1107 ptb = p_iptbl;
1108 mbr = malloc(sizeof(struct dos_mbr_or_ebr));
1109
1110 for (i=0;i<ptb->count;i++) {
1111 apt_info("-update MBR-: partition[%02d]: %016llx - %016llx\n",i,
1112 ptb->partitions[i].offset, ptb->partitions[i].size);
1113 }
1114
1115 for (i = 0;i < ptb->count;) {
1116 memset(mbr ,0 ,sizeof(struct dos_mbr_or_ebr));
1117 if (i == 0) {
1118 _construct_mbr_or_ebr(ptb, mbr, i, 0);
1119 i = i+2;
1120 } else
1121 _construct_mbr_or_ebr(ptb, mbr, i, 2);
1122 src = (unsigned char *)mbr;
1123 apt_info("--%s(): %02d(%02d), off %x\n", __func__, i, ptb->count, start_blk);
1124 ret = blk_dwrite(mmc_get_blk_desc(mmc), start_blk, blk_cnt, src);
1125 i++;
1126 if (ret != blk_cnt) {
1127 apt_err("write current MBR failed! ret: %d != cnt: %d\n",ret,blk_cnt);
1128 break;
1129 }
1130 start_blk = (ptb->partitions[i].offset - PARTITION_RESERVED) >> 9;
1131 }
1132 free(mbr);
1133
1134 ret = !ret;
1135 if (ret)
1136 apt_err("write MBR failed!\n");
1137
1138 return ret;
1139}
1140
1141int is_gpt_changed(struct mmc *mmc, struct _iptbl *p_iptbl_ept)
1142{
1143 int i, k;
1144 gpt_entry *gpt_pte = NULL;
1145 size_t efiname_len;
1146 struct _iptbl *ept = p_iptbl_ept;
1147 struct partitions *partitions = ept->partitions;
1148 int parts_num = ept->count;
1149 uint64_t offset;
1150 uint64_t size;
1151 char name[PARTNAME_SZ];
1152 int gpt_changed = 0;
1153 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
1154
1155 if (dev_desc == NULL) {
1156 printf("%s: Invalid Argument(s)\n", __func__);
1157 return 1;
1158 }
1159
1160 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
1161
1162 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
1163 gpt_head, &gpt_pte) != 1) {
1164 printf("%s: ***ERROR:Invalid GPT ***\n", __func__);
1165 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
1166 gpt_head, &gpt_pte) != 1) {
1167 printf("%s: ***ERROR: Invalid Backup GPT ***\n",
1168 __func__);
1169 return 1;
1170 } else {
1171 printf("%s: *** Using Backup GPT ***\n",
1172 __func__);
1173 }
1174 //return 1;
1175 }
1176 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
1177 if (!is_pte_valid(&gpt_pte[i]))
1178 break;
1179
1180 offset = le64_to_cpu(gpt_pte[i].starting_lba<<9ULL);
1181 if (partitions[i].offset != offset) {
1182 printf("Caution! GPT offset had been changed\n");
1183 gpt_changed = 1;
1184 break;
1185 }
1186
1187 size = ((le64_to_cpu(gpt_pte[i].ending_lba)+1) -
1188 le64_to_cpu(gpt_pte[i].starting_lba)) << 9ULL;
1189 if (i == parts_num - 1) {
1190 if ((partitions[i].size - GPT_TOTAL_SIZE) != size) {
1191 printf("Caution! GPT size had been changed\n");
1192 gpt_changed = 1;
1193 break;
1194 }
1195 } else {
1196 if (partitions[i].size != size) {
1197 printf("Caution! GPT size had been changed\n");
1198 gpt_changed = 1;
1199 break;
1200 }
1201 }
1202
1203 /* partition name */
1204 efiname_len = sizeof(gpt_pte[i].partition_name)
1205 / sizeof(efi_char16_t);
1206
1207 memset(name, 0, PARTNAME_SZ);
1208 for (k = 0; k < efiname_len; k++)
1209 name[k] = (char)gpt_pte[i].partition_name[k];
1210 if (strcmp(name, partitions[i].name) != 0) {
1211 printf("Caution! GPT name had been changed\n");
1212 gpt_changed = 1;
1213 break;
1214 }
1215
1216 }
1217 if ((i != parts_num) && (gpt_changed == 0)) {
1218 gpt_changed = 1;
1219 printf("Caution! GPT number had been changed\n");
1220 }
1221
1222 free(gpt_pte);
1223 return gpt_changed;
1224}
1225
1226int is_gpt_broken(struct mmc *mmc)
1227{
1228 gpt_entry *gpt_pte = NULL;
1229 int broken_status = 0;
1230 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
1231
1232 if (!dev_desc) {
1233 printf("%s: Invalid Argument(s)\n", __func__);
1234 return 1;
1235 }
1236 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
1237
1238 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
1239 gpt_head, &gpt_pte) != 1) {
1240 broken_status += 1;
1241 printf("%s: ***ERROR:Invalid GPT ***\n", __func__);
1242 }
1243 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
1244 gpt_head, &gpt_pte) != 1) {
1245 printf("%s: ***ERROR: Invalid Backup GPT ***\n",
1246 __func__);
1247 broken_status += 2;
1248 }
1249
1250 if (broken_status != 3)
1251 free(gpt_pte);
1252 return broken_status;
1253
1254}
1255
1256/*
1257 * check is gpt is valid
1258 * if valid return 0
1259 * else return 1
1260 */
1261int aml_gpt_valid(struct mmc *mmc) {
1262 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
1263 if (!dev_desc) {
1264 printf("%s: Invalid Argument(s)\n", __func__);
1265 return 1;
1266 } else {
1267 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
1268 gpt_entry *gpt_pte = NULL;
1269 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
1270 gpt_head, &gpt_pte) != 1) {
1271 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
1272 gpt_head, &gpt_pte) != 1) {
1273 printf("gpt is invalid\n");
1274 return 1;
1275 } else {
1276 printf("%s: *** Using Backup GPT ***\n",
1277 __func__);
1278 }
1279 }
1280 }
1281
1282 return 0;
1283}
1284
1285void trans_ept_to_diskpart(struct _iptbl *ept, disk_partition_t *disk_part) {
1286 struct partitions *part = ept->partitions;
1287 int count = ept->count;
1288 int i;
1289 for (i = 0; i < count; i++) {
1290 disk_part[i].start = part[i].offset >> 9;
1291 strcpy((char *)disk_part[i].name, part[i].name);
1292 /* store maskflag into type, 8bits ONLY! */
1293 disk_part[i].type[0] = (uchar)part[i].mask_flags;
1294#ifdef CONFIG_PARTITION_TYPE_GUID
1295 strcpy((char *)disk_part[i].type_guid, part[i].name);
1296#endif
1297#ifdef CONFIG_RANDOM_UUID
1298 gen_rand_uuid_str(disk_part[i].uuid, UUID_STR_FORMAT_STD);
1299#endif
1300 disk_part[i].bootable = 0;
1301 if ( i == (count - 1))
1302 disk_part[i].size = 0;
1303 else
1304 disk_part[i].size = (part[i].size) >> 9;
1305 }
1306 return;
1307}
1308
1309#ifdef CONFIG_AML_PARTITION
1310/*
1311 * compare ept and rsv
1312 *
1313 * if different:
1314 * update rsv write back on emmc
1315 *
1316 */
1317int enable_rsv_part_table(struct mmc *mmc)
1318{
1319 struct _iptbl *p_iptbl_rsv = NULL;
1320 int ret = -1;
1321
1322 /* try to get partition table from rsv */
1323 ret = _zalloc_iptbl(&p_iptbl_rsv);
1324 if (ret)
1325 return ret;
1326 if (!get_ptbl_rsv(mmc, p_iptbl_rsv)) {
1327 if (_cmp_iptbl(p_iptbl_ept, p_iptbl_rsv)) {
1328 apt_wrn("update rsv with gpt!\n");
1329 ret = update_ptbl_rsv(mmc, p_iptbl_ept);
1330 if (ret)
1331 printf("update rsv with gpt failed\n");
1332 }
1333 } else {
1334 printf("rsv not exist\n");
1335 ret = update_ptbl_rsv(mmc, p_iptbl_ept);
1336 if (ret)
1337 printf("update rsv with gpt failed\n");
1338 }
1339
1340 _free_iptbl(p_iptbl_rsv);
1341 return ret;
1342}
1343#endif
1344
1345void __attribute__((unused)) _update_part_tbl(struct partitions *p, int count)
1346{
1347 int i = 0;
1348
1349 while (i < count) {
1350 if (strcmp(p[i].name, "boot_a") == 0)
1351 has_boot_slot = 1;
1352 else if (strcmp(p[i].name, "boot") == 0)
1353 has_boot_slot = 0;
1354
1355 if (strcmp(p[i].name, "system_a") == 0)
1356 has_system_slot = 1;
1357 else if (strcmp(p[i].name, "system") == 0)
1358 has_system_slot = 0;
1359
1360 if (strcmp(p[i].name, "super") == 0) {
1361 dynamic_partition = true;
1362 env_set("partition_mode", "dynamic");
1363 }
1364
1365 if (strncmp(p[i].name, "vendor_boot", 11) == 0) {
1366 vendor_boot_partition = true;
1367 env_set("vendor_boot_mode", "true");
1368 }
1369 i++;
1370 }
1371}
1372
1373/***************************************************
1374 * init partition table for emmc device.
1375 * returns 0 means ok.
1376 * other means failure.
1377 ***************************************************
1378 * work flows:
1379 * source of logic partition table(LPT) is from dts
1380 * no matter MACRO is on/off
1381 * 1. try to get LPT from dtb
1382 * 1.1 if dtb exist, compose ept by LPT&inh
1383 * 1.2 if not, go ahead
1384 * 2. try to get ept from emmc rsv partition
1385 * 2.1 if not:
1386 * 2.1.1 when dtb exists
1387 * 2.1.1.1 check ept with dtb
1388 * 2.1.1.2 update rsv if needed
1389 * 2.1.1 without dtb, exit
1390 * 2.2 if got:
1391 * 2.2.1 try to reconstruct ept by MBR
1392 * 2.2.2 check it with ept
1393 * 2.2.3 update MBR if needed
1394 ***************************************************
1395 * when normal boot:
1396 * without dtb, with rsv, with MBR
1397 * when blank emmc:
1398 * without dtb, without rsv, without MBR
1399 * when burning MBR on a blank emmc:
1400 * with dtb, without rsv, without MBR
1401 * when burning MBR on a emmc with rsv:
1402 * with dtb, with rsv, without MBR
1403 * when burning MBR on a emmc with rsv&MBR:
1404 * with dtb, with rsv, with MBR
1405 ***************************************************/
1406int mmc_device_init (struct mmc *mmc)
1407{
1408 int ret = 1;
1409
1410#ifdef CONFIG_AML_PARTITION
1411 int update = 1;
1412 struct _iptbl *p_iptbl_rsv = NULL;
1413#endif
1414
1415#if (CONFIG_PTBL_MBR) || (!CONFIG_AML_PARTITION)
1416 cpu_id_t cpu_id = get_cpu_id();
1417#endif
1418 /* partition table from dtb/code/emmc rsv */
1419 struct _iptbl iptbl_dtb, iptbl_inh;
1420
1421 /* For re-entry */
1422 if (!p_iptbl_ept) {
1423 ret = _zalloc_iptbl(&p_iptbl_ept);
1424 if (ret)
1425 goto _out;
1426 } else {
1427 p_iptbl_ept->count = 0;
1428 memset(p_iptbl_ept->partitions, 0,
1429 sizeof(struct partitions) * MAX_PART_COUNT);
1430 }
1431
1432 /* calculate inherent offset */
1433 iptbl_inh.count = get_emmc_partition_arraysize();
1434 if (iptbl_inh.count) {
1435 iptbl_inh.partitions = emmc_partition_table;
1436 _calculate_offset(mmc, &iptbl_inh, 0);
1437 }
1438 apt_info("inh count %d\n", iptbl_inh.count);
1439
1440 ret = get_ept_from_gpt(mmc);
1441 if (!ret) {
1442#ifdef CONFIG_AML_PARTITION
1443 /* init part again */
1444 part_init(mmc_get_blk_desc(mmc));
1445 return enable_rsv_part_table(mmc);
1446#else
1447 part_init(mmc_get_blk_desc(mmc));
1448 return ret;
1449#endif
1450 }
1451
1452#if (CONFIG_MPT_DEBUG)
1453 apt_info("inherent partition table\n");
1454 _dump_part_tbl(iptbl_inh.partitions, iptbl_inh.count);
1455#endif
1456
1457 /* try to get partition table from dtb(ddr or emmc) */
1458 iptbl_dtb.partitions = get_ptbl_from_dtb(mmc);
1459 /* construct ept by dtb if exist */
1460 if (iptbl_dtb.partitions) {
1461 iptbl_dtb.count = get_partition_count();
1462 apt_info("dtb %p, count %d\n", iptbl_dtb.partitions, iptbl_dtb.count);
1463 /* reserved partition must exist! */
1464 if (iptbl_inh.count) {
1465 compose_ept(&iptbl_dtb, &iptbl_inh, p_iptbl_ept);
1466 if (0 == p_iptbl_ept->count) {
1467 apt_err("compose partition table failed!\n");
1468 goto _out;
1469 }
1470 /* calculate offset infos. considering GAPs */
1471 if (_calculate_offset(mmc, p_iptbl_ept, 1)) {
1472 goto _out;
1473 }
1474 #if (CONFIG_MPT_DEBUG)
1475 apt_info("ept partition table\n");
1476 _dump_part_tbl(p_iptbl_ept->partitions, p_iptbl_ept->count);
1477 #endif
1478 } else {
1479 /* report fail, because there is no reserved partitions */
1480 apt_err("compose partition table failed!\n");
1481 ret = -1;
1482 goto _out;
1483 }
1484 } else
1485 apt_wrn("get partition table from dtb failed\n");
1486#ifndef CONFIG_AML_PARTITION
1487 if (cpu_id.family_id < MESON_CPU_MAJOR_ID_G12B) {
1488 printf("CONFIG_AML_PARTITION should define before G12B\n");
1489 goto _out;
1490 }
1491#endif
1492
1493#ifdef CONFIG_AML_PARTITION
1494 /* try to get partition table from rsv */
1495 ret = _zalloc_iptbl(&p_iptbl_rsv);
1496 if (ret)
1497 goto _out;
1498 ret = get_ptbl_rsv(mmc, p_iptbl_rsv);
1499 if (p_iptbl_rsv->count) {
1500 /* dtb exist, p_iptbl_ept already inited */
1501 if (iptbl_dtb.partitions) {
1502 ret = _cmp_iptbl(p_iptbl_ept, p_iptbl_rsv);
1503 if (!ret) {
1504 update = 0;
1505 }
1506 } else {
1507 /* without dtb, update ept with rsv */
1508 #if 0
1509 p_iptbl_ept->count = p_iptbl_rsv->count;
1510 memcpy(p_iptbl_ept->partitions, p_iptbl_rsv->partitions,
1511 p_iptbl_ept->count * sizeof(struct partitions));
1512 #endif
1513 _cpy_iptbl(p_iptbl_ept, p_iptbl_rsv);
1514 update = 0;
1515 }
1516 } else {
1517 /* without dtb& rsv */
1518 if (!iptbl_dtb.partitions) {
1519 apt_err("dtb&rsv are not exist, no LPT source\n");
1520 ret = -9;
1521 goto _out;
1522 }
1523 }
1524
1525 if (update && iptbl_dtb.partitions && (aml_gpt_valid(mmc) != 0)) {
1526 apt_wrn("update rsv with dtb!\n");
1527 ret = update_ptbl_rsv(mmc, p_iptbl_ept);
1528 }
1529#endif
1530 //apt_wrn("ept source is %s\n", (ept_source == p_iptbl_ept)?"ept":"rsv");
1531#if (CONFIG_PTBL_MBR)
1532 /* 1st sector was reserved by romboot after gxl */
1533 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
1534 if (_check_ptbl_mbr(mmc, p_iptbl_ept)) {
1535 /*fixme, compatible for mbr&ebr */
1536 ret |= _update_ptbl_mbr(mmc, p_iptbl_ept);
1537 apt_wrn("MBR Updated!\n");
1538 }
1539 }
1540#endif
1541
1542 _update_part_tbl(p_iptbl_ept->partitions, p_iptbl_ept->count);
1543
1544 /* init part again */
1545 part_init(mmc_get_blk_desc(mmc));
1546
1547_out:
1548#ifdef CONFIG_AML_PARTITION
1549 if (p_iptbl_rsv)
1550 _free_iptbl(p_iptbl_rsv);
1551#endif
1552 return ret;
1553}
1554
ruixuan.liffca1b92023-02-24 16:18:59 +08001555int mmc_partition_init(void)
1556{
1557 struct mmc *mmc = find_mmc_device(1);
1558 int ret;
1559
1560 if (!mmc) {
1561 printf("emmc is not exist\n");
1562 return -1;
1563 }
1564
1565 if (!p_iptbl_ept) {
1566 ret = _zalloc_iptbl(&p_iptbl_ept);
1567 if (ret)
1568 return ret;
1569 } else {
1570 p_iptbl_ept->count = 0;
1571 memset(p_iptbl_ept->partitions, 0,
1572 sizeof(struct partitions) * MAX_PART_COUNT);
1573 }
1574
1575 ret = get_ept_from_gpt(mmc);
1576 if (!ret) {
1577 part_init(mmc_get_blk_desc(mmc));
1578 return ret;
1579 }
1580
1581 printf("gpt is not exist, partition registe failed\n");
1582 return ret;
1583}
1584
Bo Lv72d0e902023-01-02 14:27:34 +00001585struct partitions *find_mmc_partition_by_name (char const *name)
1586{
1587 struct partitions *partition = NULL;
1588
1589 apt_info("p_iptbl_ept %p\n", p_iptbl_ept);
1590 if (NULL == p_iptbl_ept) {
1591 goto _out;
1592 }
1593 partition = p_iptbl_ept->partitions;
1594 partition = _find_partition_by_name(partition,
1595 p_iptbl_ept->count, name);
1596 apt_info("partition %p\n", partition);
1597 if (!partition) {
1598 partition = _find_partition_by_name(emmc_partition_table,
1599 get_emmc_partition_arraysize(), name);
1600 }
1601 apt_info("partition %p\n", partition);
1602_out:
1603 return partition;
1604}
1605
1606/*
1607 find virtual partition in inherent table.
1608*/
1609int find_virtual_partition_by_name (char const *name, struct partitions *partition)
1610{
1611 int ret = 0;
1612 ulong offset;
1613 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
1614 if (NULL == partition)
1615 return -1;
1616
1617 offset = _get_inherent_offset(MMC_RESERVED_NAME);
1618 if (-1 == offset) {
1619 apt_err("can't find %s in inherent\n", MMC_RESERVED_NAME);
1620 return -1;
1621 }
1622
1623 if (!strcmp(name, "dtb")) {
1624 strncpy(partition->name, name, sizeof(partition->name) - 1);
1625 partition->name[sizeof(partition->name) - 1] = '\0';
1626 partition->offset = offset + vpart->offset;
1627 partition->size = (vpart->size * DTB_COPIES);
1628 }
1629
1630 return ret;
1631}
1632
1633int find_dev_num_by_partition_name (char const *name)
1634{
1635 int dev = -1;
1636
1637 /* card */
1638 if (!strcmp(name, MMC_CARD_PARTITION_NAME)) {
1639 dev = 0;
1640 } else { /* eMMC OR TSD */
1641 /* partition name is valid */
1642 if (find_mmc_partition_by_name(name)) {
1643 dev = 1;
1644 }
1645 }
1646 return dev;
1647}
1648
1649static inline uint64_t get_part_size(struct partitions *part, int num)
1650{
1651 return part[num].size;
1652}
1653
1654static inline uint64_t get_part_offset(struct partitions *part, int num)
1655{
1656 return part[num].offset;
1657}
1658
1659static inline char * get_part_name(struct partitions *part, int num)
1660{
1661 return (char *)part[num].name;
1662}
1663
1664int get_part_info_from_tbl(struct blk_desc *dev_desc,
1665 int num, disk_partition_t *info)
1666{
1667 int ret = 0;
1668 struct partitions *part;
1669
1670 if (NULL == p_iptbl_ept)
1671 return -1;
1672 if (num > (p_iptbl_ept->count-1))
1673 return -1;
1674 part = p_iptbl_ept->partitions;
1675
1676 /*get partition info by index! */
1677 info->start = (lbaint_t)(get_part_offset(part, num)/dev_desc->blksz);
1678 info->size = (lbaint_t)(get_part_size(part, num)/dev_desc->blksz);
1679 info->blksz = dev_desc->blksz;
1680 strcpy((char *)info->name, get_part_name(part, num));
1681
1682 return ret;
1683}
1684#if (CONFIG_MPT_DEBUG)
1685void show_partition_info(disk_partition_t *info)
1686{
1687 printf("----------%s----------\n", __func__);
1688 printf("name %10s\n", info->name);
1689 printf("blksz " LBAFU "\n", info->blksz);
1690 printf("sart %ld\n", info->start);
1691 printf("size %ld\n", info->size);
1692 printf("----------end----------\n");
1693}
1694#endif
1695
1696struct partitions *aml_get_partition_by_name(const char *name)
1697{
1698 struct partitions *partition = NULL;
1699 partition = _find_partition_by_name(emmc_partition_table,
1700 get_emmc_partition_arraysize(), name);
1701 if (partition == NULL)
1702 apt_wrn("do not find match in inherent table %s\n", name);
1703 return partition;
1704}
1705
1706struct virtual_partition *aml_get_virtual_partition_by_name(const char *name)
1707{
1708 int i = 0, cnt;
1709 struct virtual_partition *part = NULL;
1710 cnt = get_emmc_virtual_partition_arraysize();
1711 while (i < cnt) {
1712
1713 part = &virtual_partition_table[i];
1714 if (!strcmp(name, part->name)) {
1715 apt_info("find %10s @ tbl[%d]\n", name, i);
1716 break;
1717 }
1718 i++;
1719 };
1720 if (i == cnt) {
1721 part = NULL;
1722 apt_wrn("do not find match in table %10s\n", name);
1723 }
1724 return part;
1725}
1726
1727int get_part_info_by_name(struct blk_desc *dev_desc,
1728 const char *name, disk_partition_t *info)
1729{
1730 struct partitions *partition = NULL;
1731 struct partitions virtual;
1732 int ret = 0;
1733 cpu_id_t cpu_id = get_cpu_id();
1734
1735 partition = find_mmc_partition_by_name((char *)name);
1736 if (partition) {
1737 info->start = (lbaint_t)(partition->offset/dev_desc->blksz);
1738 info->size = (lbaint_t)(partition->size/dev_desc->blksz);
1739 info->blksz = dev_desc->blksz;
1740 strcpy((char *)info->name, partition->name);
1741 } else if (!find_virtual_partition_by_name((char *)name, &virtual)) {
1742 /* try virtual partitions */
1743 apt_wrn("Got %s in virtual table\n", name);
1744 info->start = (lbaint_t)(virtual.offset/dev_desc->blksz);
1745 info->size = (lbaint_t)(virtual.size/dev_desc->blksz);
1746 info->blksz = dev_desc->blksz;
1747 strcpy((char *)info->name, virtual.name);
1748 } else {
1749 /* all partitions were tried, fail */
1750 ret = -1;
1751 goto _out;
1752 }
1753 /* for bootloader */
1754 if ((0 == info->start) && (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL)) {
1755 info->start = 1;
1756 info->size -= 1;
1757 }
1758
1759#if (CONFIG_MPT_DEBUG)
1760 show_partition_info(info);
1761#endif
1762_out:
1763 return ret;
1764}
1765
1766
1767/*
1768 * get the partition number by name
1769 * return value
1770 * < 0 means no partition found
1771 * >= 0 means valid partition
1772 */
1773__weak int get_partition_num_by_name(char const *name)
1774{
1775 int ret = -1;
1776 struct partitions *partition = NULL;
1777
1778 if (NULL == p_iptbl_ept)
1779 goto _out;
1780 partition = p_iptbl_ept->partitions;
1781 ret = _get_part_index_by_name(partition,
1782 p_iptbl_ept->count, name);
1783_out:
1784 return ret;
1785}
1786
1787/*
1788 * get the partition info by number
1789 * return value
1790 * < 0 means no partition found
1791 * >= 0 means valid partition
1792 */
1793__weak struct partitions *get_partition_info_by_num(const int num)
1794{
1795 struct partitions *partition = NULL;
1796
1797 if ((NULL == p_iptbl_ept)
1798 || (num >= p_iptbl_ept->count))
1799 goto _out;
1800 partition = &p_iptbl_ept->partitions[num];
1801
1802_out:
1803 return partition;
1804}
ruixuan.li554d4e92023-02-28 17:11:25 +08001805
1806int check_gpt_part(struct blk_desc *dev_desc, void *buf)
1807{
1808 gpt_entry *gpt_pte = NULL;
1809 gpt_header *gpt_h;
1810 gpt_entry *gpt_e;
1811 u32 calc_crc32;
1812 int i;
1813 u32 entries_num;
1814#if (ADD_LAST_PARTITION)
1815 ulong gap = GPT_GAP;
1816#endif
1817 u64 offset_old, size_old;
1818 u64 offset_new, size_new;
1819 int ret = 0;
1820 bool alternate_flag = false;
1821
1822 /* determine start of GPT Header in the buffer */
1823 gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
1824 dev_desc->blksz);
1825
1826 /* determine start of GPT Entries in the buffer */
1827 gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
1828 dev_desc->blksz);
1829 entries_num = le32_to_cpu(gpt_h->num_partition_entries);
1830
1831 if (le64_to_cpu(gpt_h->alternate_lba) > dev_desc->lba ||
1832 le64_to_cpu(gpt_h->alternate_lba) == 0) {
1833 printf("GPT: alternate_lba: %llX, " LBAF ", reset it\n",
1834 le64_to_cpu(gpt_h->alternate_lba), dev_desc->lba);
1835 gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
1836 alternate_flag = true;
1837 }
1838
1839 if (le64_to_cpu(gpt_h->last_usable_lba) > dev_desc->lba) {
1840 printf("GPT: last_usable_lba incorrect: %llX > " LBAF ", reset it\n",
1841 le64_to_cpu(gpt_h->last_usable_lba), dev_desc->lba);
1842 if (alternate_flag)
1843 gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
1844 else
1845 gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 1);
1846 }
1847
1848 for (i = 0; i < entries_num; i++) {
1849#if (ADD_LAST_PARTITION)
1850 if (i == entries_num - 1) {
1851 gpt_e[i - 1].ending_lba -= gpt_e[i].ending_lba + le64_to_cpu(gap) + 1;
1852 gpt_e[i].starting_lba = gpt_e[i - 1].ending_lba + le64_to_cpu(gap) + 1;
1853 gpt_e[i].ending_lba = gpt_h->last_usable_lba;
1854 }
1855
1856#endif
1857 if (le64_to_cpu(gpt_e[i].ending_lba) > gpt_h->last_usable_lba) {
1858 printf("gpt_e[%d].ending_lba: %llX > %llX, reset it\n",
1859 i, le64_to_cpu(gpt_e[i].ending_lba), le64_to_cpu(gpt_h->last_usable_lba));
1860 if (alternate_flag)
1861 gpt_e[i].ending_lba = ((gpt_h->last_usable_lba >> 12) << 12) - 1;
1862 else
1863 gpt_e[i].ending_lba = gpt_h->last_usable_lba;
1864 printf("gpt_e[%d].ending_lba: %llX\n", i, gpt_e[i].ending_lba);
1865 }
1866 }
1867
1868 calc_crc32 = crc32(0, (const unsigned char *)gpt_e,
1869 entries_num * le32_to_cpu(gpt_h->sizeof_partition_entry));
1870 gpt_h->partition_entry_array_crc32 = calc_crc32;
1871 gpt_h->header_crc32 = 0;
1872 calc_crc32 = crc32(0, (const unsigned char *)gpt_h,
1873 le32_to_cpu(gpt_h->header_size));
1874 gpt_h->header_crc32 = calc_crc32;
1875
1876 for (i = 0; i < le32_to_cpu(gpt_h->num_partition_entries); i++) {
1877 if (!is_pte_valid(&gpt_pte[i]))
1878 break;
1879
1880 offset_old = le64_to_cpu(gpt_pte[i].starting_lba << 9ULL);
1881 size_old = ((le64_to_cpu(gpt_pte[i].ending_lba) + 1) -
1882 le64_to_cpu(gpt_pte[i].starting_lba)) << 9ULL;
1883
1884 offset_new = le64_to_cpu(gpt_e[i].starting_lba << 9ULL);
1885 size_new = ((le64_to_cpu(gpt_e[i].ending_lba) + 1) -
1886 le64_to_cpu(gpt_e[i].starting_lba)) << 9ULL;
1887
1888 if (offset_old != offset_new || size_old != size_new) {
1889 printf("old %02d %10ls %016llx %016llx\n",
1890 i, gpt_pte[i].partition_name,
1891 offset_old, size_old);
1892 printf("new %02d %10ls %016llx %016llx\n",
1893 i, gpt_e[i].partition_name,
1894 offset_new, size_new);
1895 ret = 1;
1896 printf("partition changes, erase\n");
1897 goto _out;
1898 }
1899 }
1900
1901_out:
1902 free(gpt_pte);
1903 return ret;
1904}