blob: 38103ddc616252a44cc00fddb24d72cf91b5db6c [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>
22
23
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
249int fill_ept_by_gpt(struct mmc *mmc, struct _iptbl *p_iptbl_ept)
250{
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;
255 struct _iptbl *ept = p_iptbl_ept;
256 struct partitions *partitions = ept->partitions;
257
258 if (!dev_desc) {
259 printf("%s: Invalid Argument(s)\n", __func__);
260 return 1;
261 }
262
263 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
264
265 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
266 gpt_head, &gpt_pte) != 1) {
267 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
268 gpt_head, &gpt_pte) != 1) {
269 printf("%s: invalid gpt\n", __func__);
270 return 1;
271 }
272 printf("%s: *** Using Backup GPT ***\n", __func__);
273 }
274
275 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
276 if (!is_pte_valid(&gpt_pte[i]))
277 break;
278
279 partitions[i].offset = le64_to_cpu(gpt_pte[i].starting_lba << 9ULL);
280 partitions[i].size = ((le64_to_cpu(gpt_pte[i].ending_lba) + 1) -
281 le64_to_cpu(gpt_pte[i].starting_lba)) << 9ULL;
282 /* mask flag */
283 partitions[i].mask_flags =
284 (uint32_t)le64_to_cpu(gpt_pte[i].attributes.fields.type_guid_specific);
285 /* partition name */
286 efiname_len = sizeof(gpt_pte[i].partition_name)
287 / sizeof(efi_char16_t);
288 dosname_len = sizeof(partitions[i].name);
289
290 memset(partitions[i].name, 0, sizeof(partitions[i].name));
291 for (k = 0; k < min(dosname_len, efiname_len); k++)
292 partitions[i].name[k] = (char)gpt_pte[i].partition_name[k];
293
294 if (strcmp(partitions[i].name, "boot_a") == 0) {
295 has_boot_slot = 1;
296 printf("set has_boot_slot = 1\n");
297 } else if (strcmp(partitions[i].name, "boot") == 0) {
298 has_boot_slot = 0;
299 printf("set has_boot_slot = 0\n");
300 }
301 if (strcmp(partitions[i].name, "system_a") == 0)
302 has_system_slot = 1;
303 else if (strcmp(partitions[i].name, "system") == 0)
304 has_system_slot = 0;
305
306 if (strcmp(partitions[i].name, "super") == 0) {
307 dynamic_partition = true;
308 env_set("partition_mode", "dynamic");
309 printf("enable dynamic_partition\n");
310 }
311
312 if (strncmp(partitions[i].name, "vendor_boot", 11) == 0) {
313 vendor_boot_partition = true;
314 env_set("vendor_boot_mode", "true");
315 printf("enable vendor_boot\n");
316 }
317 }
318 ept->count = i;
319 free(gpt_pte);
320 return 0;
321}
322
323/*
324 * 1. gpt is writed on emmc
325 * parse gpt and compose ept and part_table
326 *
327 */
328int get_ept_from_gpt(struct mmc *mmc)
329{
330 struct partitions *ptbl = p_iptbl_ept->partitions;
331
332 if (!fill_ept_by_gpt(mmc, p_iptbl_ept)) {
333 printf("get ept from gpt success\n");
334 gpt_partition = true;
335 return 0;
336 } else if (part_table && part_table[0].offset != 0) {
337 memcpy(ptbl, part_table, sizeof(struct partitions) * parts_total_num);
338 p_iptbl_ept->count = parts_total_num;
339 printf("get ept from part_table success\n");
340 gpt_partition = true;
341 return 0;
342 }
343
344 return 1;
345}
346
347static struct partitions * get_ptbl_from_dtb(struct mmc *mmc)
348{
349 struct partitions * ptbl = NULL;
350#ifdef CONFIG_AML_PARTITION
351#ifndef DTB_BIND_KERNEL
352 unsigned char * buffer = NULL;
353 ulong ret, offset;
354 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
355
356 /* try get dtb table from ddr, which may exsit while usb burning */
357 if (NULL == get_partitions()) {
358 /* if failed, try rsv dtb area then. */
359 buffer = malloc(vpart->size * DTB_COPIES);
360 if (NULL == buffer) {
361 apt_err("Can not alloc enough buffer\n");
362 goto _err;
363 }
364 offset = _get_inherent_offset(MMC_RESERVED_NAME) + vpart->offset;
365 ret = _mmc_rsv_read(mmc, offset, (vpart->size * DTB_COPIES), buffer);
366 if (ret != (vpart->size * DTB_COPIES)) {
367 apt_err("Can not alloc enough buffer\n");
368 goto _err1;
369 }
370 /* parse it */
371 if (get_partition_from_dts(buffer)) {
372 apt_err("get partition table from dts faild\n");
373 goto _err1;
374 }
375 /* double check part_table(glb) */
376 if (NULL == get_partitions()) {
377 goto _err1;
378 }
379 apt_info("get partition table from dts successfully\n");
380
381 free(buffer);
382 buffer = NULL;
383 }
384#endif
385#endif
386 /* asign partition info to *ptbl */
387 ptbl = get_partitions();
388 return ptbl;
389#ifdef CONFIG_AML_PARTITION
390#ifndef DTB_BIND_KERNEL
391_err1:
392 if (buffer)
393 free(buffer);
394_err:
395 free (ptbl);
396 return NULL;
397#endif
398#endif
399}
400
401static struct partitions *is_prio_partition(struct _iptbl *list, struct partitions *part)
402{
403 int i;
404 struct partitions *plist = NULL;
405
406 if (list->count == 0)
407 goto _out;
408
409 apt_info("count %d\n", list->count);
410 for (i=0; i<list->count; i++) {
411 plist = &list->partitions[i];
412 apt_info("%d: %s, %s\n", i, part->name, plist->name);
413 if (!strcmp(plist->name, part->name)) {
414 apt_info("%s is prio in list[%d]\n", part->name, i);
415 break;
416 }
417 }
418 if (i == list->count)
419 plist = NULL;
420_out:
421 return plist;
422}
423
424/* calculate offset of each partitions.
425 bottom is a flag for considering
426 */
427static int _calculate_offset(struct mmc *mmc, struct _iptbl *itbl, u32 bottom)
428{
429 int i;
430 struct partitions *part;
431 ulong gap = PARTITION_RESERVED;
432 int ret = 0;
433
434 if (itbl->count <= 0)
435 return -1;
436 part = itbl->partitions;
437#if (CONFIG_MPT_DEBUG)
438 _dump_part_tbl(part, itbl->count);
439#endif
440
441 if (!strcmp(part->name, "bootloader")) {
442 part->offset = 0;
443 gap = MMC_BOOT_PARTITION_RESERVED;
444 }
445 for (i=1; i<itbl->count; i++) {
446 /**/
447 part[i].offset = part[i-1].offset + part[i-1].size + gap;
448 /* check capacity overflow ?*/
449 if (((part[i].offset + part[i].size) > mmc->capacity) ||
450 (part[i].size == -1)) {
451 part[i].size = mmc->capacity - part[i].offset;
452 /* reserv space @ the bottom */
453 if (bottom && (part[i].size > MMC_BOTTOM_RSV_SIZE)) {
454 apt_info("reserv %d bytes at bottom\n", MMC_BOTTOM_RSV_SIZE);
455 part[i].size -= MMC_BOTTOM_RSV_SIZE;
456 }
457 break;
458 }
459 if ((part[i].mask_flags & 0x100) != 0)
460 gap = PARTITION_MIN_RESERVED;
461 else
462 gap = PARTITION_RESERVED;
463 }
464
465#if (ADD_LAST_PARTITION)
466 i += 1;
467 if (i == itbl->count - 1 && bottom == 1) {
468 part[i - 1].size -= gap + part[i].size;
469 part[i].offset = part[i - 1].offset + part[i - 1].size + gap;
470 }
471#endif
472
473 if (i < (itbl->count - 1)) {
474 apt_err("too large partition table for current emmc, overflow!\n");
475 ret = -1;
476 }
477#if (CONFIG_MPT_DEBUG)
478 _dump_part_tbl(part, itbl->count);
479#endif
480 return ret;
481}
482
483static void compose_ept(struct _iptbl *dtb, struct _iptbl *inh,
484 struct _iptbl *ept)
485{
486 int i;
487 struct partitions *partition = NULL;
488 struct partitions *dst, *src, *prio;
489
490 /* override inh info by dts */
491 apt_info("dtb %p, inh %p, ept %p\n", dtb, inh, ept);
492 apt_info("ept->partitions %p\n", ept->partitions);
493 partition = ept->partitions;
494 apt_info("partition %p\n", partition);
495 for (i=0; i<MAX_PART_COUNT; i++) {
496 apt_info("i %d, ept->count %d\n", i, ept->count);
497 dst = &partition[ept->count];
498 src = (i < inh->count) ? &inh->partitions[i]:&dtb->partitions[i-inh->count];
499
500 prio = is_prio_partition(ept, src);
501 if (prio) {
502 /* override prio partition by new */
503 apt_info("override %d: %s\n", ept->count, prio->name);
504 //*prio = *src;
505 dst = prio;
506 } else
507 ept->count ++;
508 *dst = *src;
509 if (-1 == src->size) {
510 apt_info("break! %s\n", src->name);
511 break;
512 }
513 }
514
515#if (ADD_LAST_PARTITION)
516 i += 1;
517 dst = &partition[ept->count];
518 src = &dtb->partitions[i - inh->count];
519 ept->count += 1;
520 *dst = *src;
521#endif
522
523 return;
524}
525#ifdef CONFIG_AML_PARTITION
526static int _get_version(unsigned char * s)
527{
528 int version = 0;
529 if (!strncmp((char *)s, MMC_MPT_VERSION_2, sizeof(MMC_MPT_VERSION_2)))
530 version = 2;
531 else if (!strncmp((char *)s, MMC_MPT_VERSION_1, sizeof(MMC_MPT_VERSION_1)))
532 version = 1;
533 else
534 version = -1;
535
536 return version;
537}
538
539/* calc checksum.
540 there's a bug on v1 which did not calculate all the partitions.
541 */
542static int _calc_iptbl_check_v2(struct partitions * part, int count)
543{
544 int ret = 0, i;
545 int size = count * sizeof(struct partitions) >> 2;
546 int *buf = (int *)part;
547
548 for (i = 0; i < size; i++)
549 ret +=buf[i];
550
551 return ret;
552}
553
554static int _calc_iptbl_check_v1(struct partitions *part, int count)
555{
556 int i, j;
557 u32 checksum = 0, *p;
558
559 for (i = 0; i < count; i++) {
560 p = (u32*)part;
561 /*BUG here, do not fix it!!*/
562 for (j = sizeof(struct partitions)/sizeof(checksum); j > 0; j--) {
563 checksum += *p;
564 p++;
565 }
566 }
567
568 return checksum;
569}
570
571static int _calc_iptbl_check(struct partitions * part, int count, int version)
572{
573 if (1 == version)
574 return _calc_iptbl_check_v1(part, count);
575 else if (2 == version)
576 return _calc_iptbl_check_v2(part, count);
577 else
578 return -1;
579}
580
581/* ept is malloced out side */
582static int _cpy_iptbl(struct _iptbl * dst, struct _iptbl * src)
583{
584 int ret = 0;
585 if (!dst || !src) {
586 apt_err("invalid arg %s\n", !dst ? "dst" : "src");
587 ret = -1;
588 goto _out;
589 }
590 if (!dst->partitions || !src->partitions) {
591 apt_err("invalid arg %s->partitions\n", !dst ? "dst" : "src");
592 ret = -2;
593 goto _out;
594 }
595
596 dst->count = src->count;
597 memcpy(dst->partitions, src->partitions, sizeof(struct partitions) * src->count);
598
599_out:
600 return ret;
601}
602
603/* get ptbl from rsv area from emmc */
604static int get_ptbl_rsv(struct mmc *mmc, struct _iptbl *rsv)
605{
606 struct ptbl_rsv * ptbl_rsv = NULL;
607 uchar * buffer = NULL;
608 ulong size, offset;
609 int checksum, version, ret = 0;
610 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_TABLE_NAME);
611
612 size = (sizeof(struct ptbl_rsv) + 511) / 512 * 512;
613 if (vpart->size < size) {
614 apt_err("too much partitions\n");
615 ret = -1;
616 goto _out;
617 }
618 buffer = malloc(size);
619 if (NULL == buffer) {
620 apt_err("no enough memory for ptbl rsv\n");
621 ret = -2;
622 goto _out;
623 }
624 /* read it from emmc. */
625 offset = _get_inherent_offset(MMC_RESERVED_NAME) + vpart->offset;
626 if (size != _mmc_rsv_read(mmc, offset, size, buffer)) {
627 apt_err("read ptbl from rsv failed\n");
628 ret = -3;
629 goto _out;
630 }
631
632 ptbl_rsv = (struct ptbl_rsv *) buffer;
633 apt_info("magic %3.3s, version %8.8s, checksum %x\n", ptbl_rsv->magic,
634 ptbl_rsv->version, ptbl_rsv->checksum);
635 /* fixme, check magic ?*/
636 if (strncmp(ptbl_rsv->magic, MMC_PARTITIONS_MAGIC, sizeof(MMC_PARTITIONS_MAGIC))) {
637 apt_err("magic faild %s, %3.3s\n", MMC_PARTITIONS_MAGIC, ptbl_rsv->magic);
638 ret = -4;
639 goto _out;
640 }
641 /* check version*/
642 version = _get_version(ptbl_rsv->version);
643 if (version < 0) {
644 apt_err("version faild %s, %3.3s\n", MMC_PARTITIONS_MAGIC, ptbl_rsv->magic);
645 ret = -5;
646 goto _out;
647 }
648 if (ptbl_rsv->count > MAX_MMC_PART_NUM) {
649 apt_err("invalid partition count %d\n", ptbl_rsv->count);
650 ret = -1;
651 goto _out;
652 }
653 /* check sum */
654 checksum = _calc_iptbl_check(ptbl_rsv->partitions, ptbl_rsv->count, version);
655 if (checksum != ptbl_rsv->checksum) {
656 apt_err("checksum faild 0x%x, 0x%x\n", ptbl_rsv->checksum, checksum);
657 ret = -6;
658 goto _out;
659 }
660
661 rsv->count = ptbl_rsv->count;
662 memcpy(rsv->partitions, ptbl_rsv->partitions, rsv->count * sizeof(struct partitions));
663
664_out:
665 if (buffer)
666 free (buffer);
667 return ret;
668}
669
670/* update partition tables from src
671 if success, return 0;
672 else, return 1
673 */
674static int update_ptbl_rsv(struct mmc *mmc, struct _iptbl *src)
675{
676 struct ptbl_rsv *ptbl_rsv = NULL;
677 uchar *buffer;
678 ulong size, offset;
679 int ret = 0, version;
680 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_TABLE_NAME);
681
682 size = (sizeof(struct ptbl_rsv) + 511) / 512 * 512;
683 buffer = malloc(size);
684 if (NULL == buffer) {
685 apt_err("no enough memory for ptbl rsv\n");
686 return -1;
687 }
688 memset(buffer, 0 , size);
689 /* version, magic and checksum */
690 ptbl_rsv = (struct ptbl_rsv *) buffer;
691 strcpy((char *)ptbl_rsv->version, MMC_MPT_VERSION);
692 strcpy(ptbl_rsv->magic, MMC_PARTITIONS_MAGIC);
693 if (src->count > MAX_MMC_PART_NUM) {
694 apt_err("too much partitions\n");
695 ret = -1;
696 goto _err;
697 }
698 ptbl_rsv->count = src->count;
699 memcpy(ptbl_rsv->partitions, src->partitions,
700 sizeof(struct partitions)*src->count);
701 version = _get_version(ptbl_rsv->version);
702 ptbl_rsv->checksum = _calc_iptbl_check(src->partitions, src->count, version);
703 /* write it to emmc. */
704 apt_info("magic %3.3s, version %8.8s, checksum %x\n", ptbl_rsv->magic, ptbl_rsv->version, ptbl_rsv->checksum);
705 offset = _get_inherent_offset(MMC_RESERVED_NAME) + vpart->offset;
706 if (_mmc_rsv_write(mmc, offset, size, buffer) != size) {
707 apt_err("write ptbl to rsv failed\n");
708 ret = -1;
709 goto _err;
710 }
711_err:
712 free (buffer);
713 return ret;
714}
715
716static void _free_iptbl(struct _iptbl *iptbl)
717{
718 if (iptbl && iptbl->partitions) {
719 free(iptbl->partitions);
720 iptbl->partitions = NULL;
721 }
722 if (iptbl) {
723 free(iptbl);
724 iptbl = NULL;
725 }
726
727 return;
728}
729
730#endif
731static int _cmp_partition(struct partitions *dst, struct partitions *src, int override)
732{
733 int ret = 0;
734#if (CONFIG_CMP_PARTNAME)
735 if (strncmp(dst->name, src->name, sizeof(src->name)))
736 ret = -2;
737#endif
738 if (dst->size != src->size)
739 ret = -3;
740 if (dst->offset != src->offset)
741 ret = -4;
742#if (CONFIG_CMP_PARTMASK)
743 if (dst->mask_flags != src->mask_flags)
744 ret = -5;
745#endif
746
747 if (ret && (!override)) {
748 apt_err("name: %10.10s<->%10.10s\n", dst->name, src->name);
749 apt_err("size: %llx<->%llx\n", dst->size, src->size);
750 apt_err("offset: %llx<->%llx\n", dst->offset, src->offset);
751 apt_err("mask: %08x<->%08x\n", dst->mask_flags, src->mask_flags);
752 }
753
754 if (override) {
755 *dst = *src;
756 ret = 0;
757 }
758
759 return ret;
760}
761
762/* compare partition tables
763 if same, do nothing then return 0;
764 else, print the diff ones and return -x
765 -1:count
766 -2:name
767 -3:size
768 -4:offset
769 */
770static int _cmp_iptbl(struct _iptbl * dst, struct _iptbl * src)
771{
772 int ret = 0, i = 0;
773 struct partitions *dstp;
774 struct partitions *srcp;
775
776 if (dst->count != src->count) {
777 apt_err("partition count is not same %d:%d\n", dst->count, src->count);
778 ret = -1;
779 goto _out;
780 }
781
782 while (i < dst->count) {
783 dstp = &dst->partitions[i];
784 srcp = &src->partitions[i];
785 ret = _cmp_partition(dstp, srcp, 0);
786 if (ret) {
787 env_set("part_changed", "1");
788 apt_err("partition %d has changed\n", i);
789 break;
790 }
791 i++;
792 }
793
794_out:
795 return ret;
796}
797
798/* iptbl buffer opt. */
799static int _zalloc_iptbl(struct _iptbl **_iptbl)
800{
801 int ret = 0;
802 struct _iptbl *iptbl;
803 struct partitions *partition = NULL;
804
805 partition = malloc(sizeof(struct partitions)*MAX_PART_COUNT);
806 if (NULL == partition) {
807 ret = -1;
808 apt_err("no enough memory for partitions\n");
809 goto _out;
810 }
811
812 iptbl = malloc(sizeof(struct _iptbl));
813 if (NULL == iptbl) {
814 ret = -2;
815 apt_err("no enough memory for ept\n");
816 free(partition);
817 goto _out;
818 }
819 memset(partition, 0, sizeof(struct partitions)*MAX_PART_COUNT);
820 memset(iptbl, 0, sizeof(struct _iptbl));
821
822 iptbl->partitions = partition;
823 apt_info("iptbl %p, partition %p, iptbl->partitions %p\n",
824 iptbl, partition, iptbl->partitions);
825 *_iptbl = iptbl;
826_out:
827 return ret;
828}
829
830
831/*
832 * fixme, need check space size later.
833 */
834
835static inline int le32_to_int(unsigned char *le32)
836{
837 return ((le32[3] << 24) +
838 (le32[2] << 16) +
839 (le32[1] << 8) +
840 le32[0]
841 );
842}
843
844static int test_block_type(unsigned char *buffer)
845{
846 int slot;
847 struct dos_partition *p;
848
849 if ((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
850 (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
851 return (-1);
852 } /* no DOS Signature at all */
853 p = (struct dos_partition *)&buffer[DOS_PART_TBL_OFFSET];
854 for (slot = 0; slot < 3; slot++) {
855 if (p->boot_ind != 0 && p->boot_ind != 0x80) {
856 if (!slot &&
857 (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],
858 "FAT", 3) == 0 ||
859 strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],
860 "FAT32", 5) == 0)) {
861 return DOS_PBR; /* is PBR */
862 } else {
863 return -1;
864 }
865 }
866 }
867 return DOS_MBR; /* Is MBR */
868}
869
870//DOS_MBR OR DOS_PBR
871/*
872 * re-constructed iptbl from mbr&ebr infos.
873 * memory for iptbl_mbr must be alloced outside.
874 *
875 */
876static void _construct_ptbl_by_mbr(struct mmc *mmc, struct _iptbl *iptbl_mbr)
877{
878 int ret,i;
879 int flag = 0;
880 lbaint_t read_offset = 0;
881 int part_num = 0;
882 int primary_num = 0;
883 uint64_t logic_start = 0;
884 uint64_t extended_start = 0;
885 struct dos_partition *pt;
886 struct partitions *partitions = iptbl_mbr->partitions;
887
888 apt_info("aml MBR&EBR debug...\n");
889 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 512);
890 for (;;) {
891 apt_info("**%02d: read_offset %016llx\n", part_num, (uint64_t)read_offset<<9);
892 ret = blk_dread(mmc_get_blk_desc(mmc), read_offset, 1, buffer);
893 if (read_offset == 0)
894 flag = 1;
895 else
896 flag = 0;
897 /* debug code */
898 // print_buffer(0,buffer,1,512,16);
899 if (ret != 1) {
900 apt_err("ret %d fail to read current ebr&mbr from emmc! \n", ret);
901 break;
902 }
903 ret = test_block_type(buffer);
904 if (ret != 0 && ret != 1) {
905 apt_err("invalid magic value: 0x%02x%02x\n",
906 buffer[DOS_PART_MAGIC_OFFSET], buffer[DOS_PART_MAGIC_OFFSET + 1]);
907 break;
908 }
909
910 pt = (dos_partition_t *)(&buffer[0] + DOS_PART_TBL_OFFSET);
911 for (i = 0; i < 4; i++, pt++) {
912 if ( (pt->boot_ind == 0x00 || pt->boot_ind == 0x80) && pt->sys_ind == 0x83 ) {
913 //emmc_partition[part_num]->name = NULL;
914 partitions[part_num].offset = ((uint64_t)(le32_to_int(pt->start4)+read_offset) << 9ULL);
915 partitions[part_num].size = (uint64_t)le32_to_int(pt->size4) << 9ULL;
916 partitions[part_num].mask_flags = pt->sys_ind;
917
918 apt_info("--partition[%d]: %016llx, %016llx, 0x%08x \n",
919 part_num, partitions[part_num].offset,
920 partitions[part_num].size,
921 le32_to_int(pt->size4));
922 part_num++;
923 if ( flag )
924 primary_num++;
925 }else{/* get the next extended partition info */
926 if ( pt->boot_ind == 0x00 && pt->sys_ind == 0x05) {
927 logic_start = (uint64_t)le32_to_int (pt->start4);
928 //logic_size = (uint64_t)le32_to_int (pt->size4);
929 }
930 }
931 }
932 /* mbr & ebr debug infos */
933 apt_info("******%02d: read_offset=%016llx, logic_start=%016llx\n",
934 part_num,(uint64_t)read_offset*512ULL,logic_start*512ULL);
935
936 if (part_num == primary_num) {
937 extended_start = logic_start;
938 read_offset = extended_start;
939 }else
940 read_offset = extended_start + logic_start;
941 if (logic_start == 0)
942 break;
943 logic_start = 0;
944
945 }
946 iptbl_mbr->count = part_num;
947 apt_info("iptbl_mbr->count = %d\n", iptbl_mbr->count);
948
949 return;
950}
951
952static int __attribute__((unused)) _check_ptbl_mbr(struct mmc *mmc, struct _iptbl *ept)
953{
954 int ret = 0;
955 /* re-constructed by mbr */
956 struct _iptbl *iptbl_mbr = NULL;
957 struct partitions *partitions = NULL;
958
959 iptbl_mbr = malloc(sizeof(struct _iptbl));
960 if (NULL == iptbl_mbr) {
961 apt_err("no enough memory for iptbl_mbr\n");
962 return -1;
963 }
964 memset(iptbl_mbr , 0, sizeof(struct _iptbl));
965 partitions = (struct partitions *)malloc(sizeof(struct partitions) * DOS_PARTITION_COUNT);
966 if (NULL == partitions) {
967 apt_err("no enough memory for partitions\n");
968 free(iptbl_mbr);
969 return -1;
970 }
971 memset(partitions, 0, sizeof(struct partitions) * DOS_PARTITION_COUNT);
972 iptbl_mbr->partitions = partitions;
973
974 _construct_ptbl_by_mbr(mmc, iptbl_mbr);
975
976 ret = _cmp_iptbl(iptbl_mbr, ept);
977
978 if (partitions)
979 free(partitions);
980 if (iptbl_mbr)
981 free(iptbl_mbr);
982
983 apt_wrn("MBR is %s\n", ret?"Improper!":"OK!");
984 return ret;
985}
986
987/* construct a partition table entry of EBR */
988static int _construct_ebr_1st_entry(struct _iptbl *p_iptbl,struct dos_partition *p_ebr, int part_num )
989{
990 uint64_t start_offset = 0;
991 uint64_t logic_size = 0;
992
993 p_ebr->boot_ind = 0x00;
994 p_ebr->sys_ind = 0x83;
995 /* Starting = relative offset between this EBR sector and the first sector of the logical partition
996 * the gap between two partition is a fixed value of PARTITION_RESERVED ,otherwise the emmc partition
997 * is different with reserved */
998 start_offset = PARTITION_RESERVED >> 9;
999 /* Number of sectors = total count of sectors for this logical partition */
1000 // logic_size = (p_iptbl->partitions[part_num].size) >> 9ULL;
1001 logic_size = lldiv(p_iptbl->partitions[part_num].size, 512);
1002 apt_info("*** %02d: size 0x%016llx, logic_size 0x%016llx\n", part_num, p_iptbl->partitions[part_num].size, logic_size);
1003 memcpy((unsigned char *)(p_ebr->start4), &start_offset, 4);
1004 memcpy((unsigned char *)(p_ebr->size4), &logic_size, 4);
1005 return 0;
1006}
1007
1008static int _construct_ebr_2nd_entry(struct _iptbl *p_iptbl, struct dos_partition *p_ebr, int part_num)
1009{
1010 uint64_t start_offset = 0;
1011 uint64_t logic_size = 0;
1012
1013 if ((part_num+2) > p_iptbl->count)
1014 return 0;
1015
1016 p_ebr->boot_ind = 0x00;
1017 p_ebr->sys_ind = 0x05;
1018 /* Starting sector = LBA address of next EBR minus LBA address of extended partition's first EBR */
1019 start_offset = (p_iptbl->partitions[part_num+1].offset - PARTITION_RESERVED -
1020 (p_iptbl->partitions[3].offset - PARTITION_RESERVED)) >> 9;
1021 /* total count of sectors for next logical partition, but count starts from the next EBR sector */
1022 logic_size = (p_iptbl->partitions[part_num+1].size + PARTITION_RESERVED) >> 9;
1023
1024 memcpy((unsigned char *)(p_ebr->start4), &start_offset, 4);
1025 memcpy((unsigned char *)(p_ebr->size4), &logic_size, 4);
1026
1027 return 0;
1028}
1029
1030/* construct a partition table entry of MBR OR EBR */
1031static int _construct_mbr_entry(struct _iptbl *p_iptbl, struct dos_partition *p_entry, int part_num)
1032{
1033 uint64_t start_offset = 0;
1034 uint64_t primary_size = 0;
1035 uint64_t extended_size = 0;
1036 int i;
1037 /* the entry is active or not */
1038 p_entry->boot_ind = 0x00;
1039
1040 if (part_num == 3) {/* the logic partition entry */
1041 /* the entry type */
1042 p_entry->sys_ind = 0x05;
1043 start_offset = (p_iptbl->partitions[3].offset - PARTITION_RESERVED) >> 9;
1044 for ( i = 3;i< p_iptbl->count;i++)
1045 extended_size = p_iptbl->partitions[i].size >> 9;
1046
1047 memcpy((unsigned char *)p_entry->start4, &start_offset, 4);
1048 memcpy((unsigned char *)p_entry->size4, &extended_size, 4);
1049 }else{/* the primary partition entry */
1050 /* the entry type */
1051 p_entry->sys_ind = 0x83;
1052 start_offset = (p_iptbl->partitions[part_num].offset) >> 9;
1053 primary_size = (p_iptbl->partitions[part_num].size)>>9;
1054 memcpy((unsigned char *)p_entry->start4, &start_offset, 4);
1055 memcpy((unsigned char *)p_entry->size4, &primary_size, 4);
1056 }
1057
1058 return 0;
1059}
1060
1061static int _construct_mbr_or_ebr(struct _iptbl *p_iptbl, struct dos_mbr_or_ebr *p_br,
1062 int part_num, int type)
1063{
1064 int i;
1065
1066 if (DOS_MBR == type) {
1067 /* construct a integral MBR */
1068 for (i = 0; i<4 ; i++)
1069 _construct_mbr_entry(p_iptbl, &p_br->part_entry[i], i);
1070
1071 }else{
1072 /* construct a integral EBR */
1073 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET] = 'F';
1074 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 1] = 'A';
1075 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 2] = 'T';
1076 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 3] = '3';
1077 p_br->bootstart[DOS_PBR32_FSTYPE_OFFSET + 4] = '2';
1078
1079 _construct_ebr_1st_entry(p_iptbl, &p_br->part_entry[0], part_num);
1080 _construct_ebr_2nd_entry(p_iptbl, &p_br->part_entry[1], part_num);
1081 }
1082
1083 p_br->magic[0] = 0x55 ;
1084 p_br->magic[1] = 0xAA ;
1085 return 0;
1086}
1087
1088static __attribute__((unused)) int _update_ptbl_mbr(struct mmc *mmc, struct _iptbl *p_iptbl)
1089{
1090 int ret = 0, start_blk = 0, blk_cnt = 1;
1091 unsigned char *src;
1092 int i;
1093 struct dos_mbr_or_ebr *mbr;
1094 struct _iptbl *ptb ;
1095
1096 ptb = p_iptbl;
1097 mbr = malloc(sizeof(struct dos_mbr_or_ebr));
1098
1099 for (i=0;i<ptb->count;i++) {
1100 apt_info("-update MBR-: partition[%02d]: %016llx - %016llx\n",i,
1101 ptb->partitions[i].offset, ptb->partitions[i].size);
1102 }
1103
1104 for (i = 0;i < ptb->count;) {
1105 memset(mbr ,0 ,sizeof(struct dos_mbr_or_ebr));
1106 if (i == 0) {
1107 _construct_mbr_or_ebr(ptb, mbr, i, 0);
1108 i = i+2;
1109 } else
1110 _construct_mbr_or_ebr(ptb, mbr, i, 2);
1111 src = (unsigned char *)mbr;
1112 apt_info("--%s(): %02d(%02d), off %x\n", __func__, i, ptb->count, start_blk);
1113 ret = blk_dwrite(mmc_get_blk_desc(mmc), start_blk, blk_cnt, src);
1114 i++;
1115 if (ret != blk_cnt) {
1116 apt_err("write current MBR failed! ret: %d != cnt: %d\n",ret,blk_cnt);
1117 break;
1118 }
1119 start_blk = (ptb->partitions[i].offset - PARTITION_RESERVED) >> 9;
1120 }
1121 free(mbr);
1122
1123 ret = !ret;
1124 if (ret)
1125 apt_err("write MBR failed!\n");
1126
1127 return ret;
1128}
1129
1130int is_gpt_changed(struct mmc *mmc, struct _iptbl *p_iptbl_ept)
1131{
1132 int i, k;
1133 gpt_entry *gpt_pte = NULL;
1134 size_t efiname_len;
1135 struct _iptbl *ept = p_iptbl_ept;
1136 struct partitions *partitions = ept->partitions;
1137 int parts_num = ept->count;
1138 uint64_t offset;
1139 uint64_t size;
1140 char name[PARTNAME_SZ];
1141 int gpt_changed = 0;
1142 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
1143
1144 if (dev_desc == NULL) {
1145 printf("%s: Invalid Argument(s)\n", __func__);
1146 return 1;
1147 }
1148
1149 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
1150
1151 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
1152 gpt_head, &gpt_pte) != 1) {
1153 printf("%s: ***ERROR:Invalid GPT ***\n", __func__);
1154 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
1155 gpt_head, &gpt_pte) != 1) {
1156 printf("%s: ***ERROR: Invalid Backup GPT ***\n",
1157 __func__);
1158 return 1;
1159 } else {
1160 printf("%s: *** Using Backup GPT ***\n",
1161 __func__);
1162 }
1163 //return 1;
1164 }
1165 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
1166 if (!is_pte_valid(&gpt_pte[i]))
1167 break;
1168
1169 offset = le64_to_cpu(gpt_pte[i].starting_lba<<9ULL);
1170 if (partitions[i].offset != offset) {
1171 printf("Caution! GPT offset had been changed\n");
1172 gpt_changed = 1;
1173 break;
1174 }
1175
1176 size = ((le64_to_cpu(gpt_pte[i].ending_lba)+1) -
1177 le64_to_cpu(gpt_pte[i].starting_lba)) << 9ULL;
1178 if (i == parts_num - 1) {
1179 if ((partitions[i].size - GPT_TOTAL_SIZE) != size) {
1180 printf("Caution! GPT size had been changed\n");
1181 gpt_changed = 1;
1182 break;
1183 }
1184 } else {
1185 if (partitions[i].size != size) {
1186 printf("Caution! GPT size had been changed\n");
1187 gpt_changed = 1;
1188 break;
1189 }
1190 }
1191
1192 /* partition name */
1193 efiname_len = sizeof(gpt_pte[i].partition_name)
1194 / sizeof(efi_char16_t);
1195
1196 memset(name, 0, PARTNAME_SZ);
1197 for (k = 0; k < efiname_len; k++)
1198 name[k] = (char)gpt_pte[i].partition_name[k];
1199 if (strcmp(name, partitions[i].name) != 0) {
1200 printf("Caution! GPT name had been changed\n");
1201 gpt_changed = 1;
1202 break;
1203 }
1204
1205 }
1206 if ((i != parts_num) && (gpt_changed == 0)) {
1207 gpt_changed = 1;
1208 printf("Caution! GPT number had been changed\n");
1209 }
1210
1211 free(gpt_pte);
1212 return gpt_changed;
1213}
1214
1215int is_gpt_broken(struct mmc *mmc)
1216{
1217 gpt_entry *gpt_pte = NULL;
1218 int broken_status = 0;
1219 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
1220
1221 if (!dev_desc) {
1222 printf("%s: Invalid Argument(s)\n", __func__);
1223 return 1;
1224 }
1225 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
1226
1227 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
1228 gpt_head, &gpt_pte) != 1) {
1229 broken_status += 1;
1230 printf("%s: ***ERROR:Invalid GPT ***\n", __func__);
1231 }
1232 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
1233 gpt_head, &gpt_pte) != 1) {
1234 printf("%s: ***ERROR: Invalid Backup GPT ***\n",
1235 __func__);
1236 broken_status += 2;
1237 }
1238
1239 if (broken_status != 3)
1240 free(gpt_pte);
1241 return broken_status;
1242
1243}
1244
1245/*
1246 * check is gpt is valid
1247 * if valid return 0
1248 * else return 1
1249 */
1250int aml_gpt_valid(struct mmc *mmc) {
1251 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
1252 if (!dev_desc) {
1253 printf("%s: Invalid Argument(s)\n", __func__);
1254 return 1;
1255 } else {
1256 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
1257 gpt_entry *gpt_pte = NULL;
1258 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
1259 gpt_head, &gpt_pte) != 1) {
1260 if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
1261 gpt_head, &gpt_pte) != 1) {
1262 printf("gpt is invalid\n");
1263 return 1;
1264 } else {
1265 printf("%s: *** Using Backup GPT ***\n",
1266 __func__);
1267 }
1268 }
1269 }
1270
1271 return 0;
1272}
1273
1274void trans_ept_to_diskpart(struct _iptbl *ept, disk_partition_t *disk_part) {
1275 struct partitions *part = ept->partitions;
1276 int count = ept->count;
1277 int i;
1278 for (i = 0; i < count; i++) {
1279 disk_part[i].start = part[i].offset >> 9;
1280 strcpy((char *)disk_part[i].name, part[i].name);
1281 /* store maskflag into type, 8bits ONLY! */
1282 disk_part[i].type[0] = (uchar)part[i].mask_flags;
1283#ifdef CONFIG_PARTITION_TYPE_GUID
1284 strcpy((char *)disk_part[i].type_guid, part[i].name);
1285#endif
1286#ifdef CONFIG_RANDOM_UUID
1287 gen_rand_uuid_str(disk_part[i].uuid, UUID_STR_FORMAT_STD);
1288#endif
1289 disk_part[i].bootable = 0;
1290 if ( i == (count - 1))
1291 disk_part[i].size = 0;
1292 else
1293 disk_part[i].size = (part[i].size) >> 9;
1294 }
1295 return;
1296}
1297
1298#ifdef CONFIG_AML_PARTITION
1299/*
1300 * compare ept and rsv
1301 *
1302 * if different:
1303 * update rsv write back on emmc
1304 *
1305 */
1306int enable_rsv_part_table(struct mmc *mmc)
1307{
1308 struct _iptbl *p_iptbl_rsv = NULL;
1309 int ret = -1;
1310
1311 /* try to get partition table from rsv */
1312 ret = _zalloc_iptbl(&p_iptbl_rsv);
1313 if (ret)
1314 return ret;
1315 if (!get_ptbl_rsv(mmc, p_iptbl_rsv)) {
1316 if (_cmp_iptbl(p_iptbl_ept, p_iptbl_rsv)) {
1317 apt_wrn("update rsv with gpt!\n");
1318 ret = update_ptbl_rsv(mmc, p_iptbl_ept);
1319 if (ret)
1320 printf("update rsv with gpt failed\n");
1321 }
1322 } else {
1323 printf("rsv not exist\n");
1324 ret = update_ptbl_rsv(mmc, p_iptbl_ept);
1325 if (ret)
1326 printf("update rsv with gpt failed\n");
1327 }
1328
1329 _free_iptbl(p_iptbl_rsv);
1330 return ret;
1331}
1332#endif
1333
1334void __attribute__((unused)) _update_part_tbl(struct partitions *p, int count)
1335{
1336 int i = 0;
1337
1338 while (i < count) {
1339 if (strcmp(p[i].name, "boot_a") == 0)
1340 has_boot_slot = 1;
1341 else if (strcmp(p[i].name, "boot") == 0)
1342 has_boot_slot = 0;
1343
1344 if (strcmp(p[i].name, "system_a") == 0)
1345 has_system_slot = 1;
1346 else if (strcmp(p[i].name, "system") == 0)
1347 has_system_slot = 0;
1348
1349 if (strcmp(p[i].name, "super") == 0) {
1350 dynamic_partition = true;
1351 env_set("partition_mode", "dynamic");
1352 }
1353
1354 if (strncmp(p[i].name, "vendor_boot", 11) == 0) {
1355 vendor_boot_partition = true;
1356 env_set("vendor_boot_mode", "true");
1357 }
1358 i++;
1359 }
1360}
1361
1362/***************************************************
1363 * init partition table for emmc device.
1364 * returns 0 means ok.
1365 * other means failure.
1366 ***************************************************
1367 * work flows:
1368 * source of logic partition table(LPT) is from dts
1369 * no matter MACRO is on/off
1370 * 1. try to get LPT from dtb
1371 * 1.1 if dtb exist, compose ept by LPT&inh
1372 * 1.2 if not, go ahead
1373 * 2. try to get ept from emmc rsv partition
1374 * 2.1 if not:
1375 * 2.1.1 when dtb exists
1376 * 2.1.1.1 check ept with dtb
1377 * 2.1.1.2 update rsv if needed
1378 * 2.1.1 without dtb, exit
1379 * 2.2 if got:
1380 * 2.2.1 try to reconstruct ept by MBR
1381 * 2.2.2 check it with ept
1382 * 2.2.3 update MBR if needed
1383 ***************************************************
1384 * when normal boot:
1385 * without dtb, with rsv, with MBR
1386 * when blank emmc:
1387 * without dtb, without rsv, without MBR
1388 * when burning MBR on a blank emmc:
1389 * with dtb, without rsv, without MBR
1390 * when burning MBR on a emmc with rsv:
1391 * with dtb, with rsv, without MBR
1392 * when burning MBR on a emmc with rsv&MBR:
1393 * with dtb, with rsv, with MBR
1394 ***************************************************/
1395int mmc_device_init (struct mmc *mmc)
1396{
1397 int ret = 1;
1398
1399#ifdef CONFIG_AML_PARTITION
1400 int update = 1;
1401 struct _iptbl *p_iptbl_rsv = NULL;
1402#endif
1403
1404#if (CONFIG_PTBL_MBR) || (!CONFIG_AML_PARTITION)
1405 cpu_id_t cpu_id = get_cpu_id();
1406#endif
1407 /* partition table from dtb/code/emmc rsv */
1408 struct _iptbl iptbl_dtb, iptbl_inh;
1409
1410 /* For re-entry */
1411 if (!p_iptbl_ept) {
1412 ret = _zalloc_iptbl(&p_iptbl_ept);
1413 if (ret)
1414 goto _out;
1415 } else {
1416 p_iptbl_ept->count = 0;
1417 memset(p_iptbl_ept->partitions, 0,
1418 sizeof(struct partitions) * MAX_PART_COUNT);
1419 }
1420
1421 /* calculate inherent offset */
1422 iptbl_inh.count = get_emmc_partition_arraysize();
1423 if (iptbl_inh.count) {
1424 iptbl_inh.partitions = emmc_partition_table;
1425 _calculate_offset(mmc, &iptbl_inh, 0);
1426 }
1427 apt_info("inh count %d\n", iptbl_inh.count);
1428
1429 ret = get_ept_from_gpt(mmc);
1430 if (!ret) {
1431#ifdef CONFIG_AML_PARTITION
1432 /* init part again */
1433 part_init(mmc_get_blk_desc(mmc));
1434 return enable_rsv_part_table(mmc);
1435#else
1436 part_init(mmc_get_blk_desc(mmc));
1437 return ret;
1438#endif
1439 }
1440
1441#if (CONFIG_MPT_DEBUG)
1442 apt_info("inherent partition table\n");
1443 _dump_part_tbl(iptbl_inh.partitions, iptbl_inh.count);
1444#endif
1445
1446 /* try to get partition table from dtb(ddr or emmc) */
1447 iptbl_dtb.partitions = get_ptbl_from_dtb(mmc);
1448 /* construct ept by dtb if exist */
1449 if (iptbl_dtb.partitions) {
1450 iptbl_dtb.count = get_partition_count();
1451 apt_info("dtb %p, count %d\n", iptbl_dtb.partitions, iptbl_dtb.count);
1452 /* reserved partition must exist! */
1453 if (iptbl_inh.count) {
1454 compose_ept(&iptbl_dtb, &iptbl_inh, p_iptbl_ept);
1455 if (0 == p_iptbl_ept->count) {
1456 apt_err("compose partition table failed!\n");
1457 goto _out;
1458 }
1459 /* calculate offset infos. considering GAPs */
1460 if (_calculate_offset(mmc, p_iptbl_ept, 1)) {
1461 goto _out;
1462 }
1463 #if (CONFIG_MPT_DEBUG)
1464 apt_info("ept partition table\n");
1465 _dump_part_tbl(p_iptbl_ept->partitions, p_iptbl_ept->count);
1466 #endif
1467 } else {
1468 /* report fail, because there is no reserved partitions */
1469 apt_err("compose partition table failed!\n");
1470 ret = -1;
1471 goto _out;
1472 }
1473 } else
1474 apt_wrn("get partition table from dtb failed\n");
1475#ifndef CONFIG_AML_PARTITION
1476 if (cpu_id.family_id < MESON_CPU_MAJOR_ID_G12B) {
1477 printf("CONFIG_AML_PARTITION should define before G12B\n");
1478 goto _out;
1479 }
1480#endif
1481
1482#ifdef CONFIG_AML_PARTITION
1483 /* try to get partition table from rsv */
1484 ret = _zalloc_iptbl(&p_iptbl_rsv);
1485 if (ret)
1486 goto _out;
1487 ret = get_ptbl_rsv(mmc, p_iptbl_rsv);
1488 if (p_iptbl_rsv->count) {
1489 /* dtb exist, p_iptbl_ept already inited */
1490 if (iptbl_dtb.partitions) {
1491 ret = _cmp_iptbl(p_iptbl_ept, p_iptbl_rsv);
1492 if (!ret) {
1493 update = 0;
1494 }
1495 } else {
1496 /* without dtb, update ept with rsv */
1497 #if 0
1498 p_iptbl_ept->count = p_iptbl_rsv->count;
1499 memcpy(p_iptbl_ept->partitions, p_iptbl_rsv->partitions,
1500 p_iptbl_ept->count * sizeof(struct partitions));
1501 #endif
1502 _cpy_iptbl(p_iptbl_ept, p_iptbl_rsv);
1503 update = 0;
1504 }
1505 } else {
1506 /* without dtb& rsv */
1507 if (!iptbl_dtb.partitions) {
1508 apt_err("dtb&rsv are not exist, no LPT source\n");
1509 ret = -9;
1510 goto _out;
1511 }
1512 }
1513
1514 if (update && iptbl_dtb.partitions && (aml_gpt_valid(mmc) != 0)) {
1515 apt_wrn("update rsv with dtb!\n");
1516 ret = update_ptbl_rsv(mmc, p_iptbl_ept);
1517 }
1518#endif
1519 //apt_wrn("ept source is %s\n", (ept_source == p_iptbl_ept)?"ept":"rsv");
1520#if (CONFIG_PTBL_MBR)
1521 /* 1st sector was reserved by romboot after gxl */
1522 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
1523 if (_check_ptbl_mbr(mmc, p_iptbl_ept)) {
1524 /*fixme, compatible for mbr&ebr */
1525 ret |= _update_ptbl_mbr(mmc, p_iptbl_ept);
1526 apt_wrn("MBR Updated!\n");
1527 }
1528 }
1529#endif
1530
1531 _update_part_tbl(p_iptbl_ept->partitions, p_iptbl_ept->count);
1532
1533 /* init part again */
1534 part_init(mmc_get_blk_desc(mmc));
1535
1536_out:
1537#ifdef CONFIG_AML_PARTITION
1538 if (p_iptbl_rsv)
1539 _free_iptbl(p_iptbl_rsv);
1540#endif
1541 return ret;
1542}
1543
1544struct partitions *find_mmc_partition_by_name (char const *name)
1545{
1546 struct partitions *partition = NULL;
1547
1548 apt_info("p_iptbl_ept %p\n", p_iptbl_ept);
1549 if (NULL == p_iptbl_ept) {
1550 goto _out;
1551 }
1552 partition = p_iptbl_ept->partitions;
1553 partition = _find_partition_by_name(partition,
1554 p_iptbl_ept->count, name);
1555 apt_info("partition %p\n", partition);
1556 if (!partition) {
1557 partition = _find_partition_by_name(emmc_partition_table,
1558 get_emmc_partition_arraysize(), name);
1559 }
1560 apt_info("partition %p\n", partition);
1561_out:
1562 return partition;
1563}
1564
1565/*
1566 find virtual partition in inherent table.
1567*/
1568int find_virtual_partition_by_name (char const *name, struct partitions *partition)
1569{
1570 int ret = 0;
1571 ulong offset;
1572 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
1573 if (NULL == partition)
1574 return -1;
1575
1576 offset = _get_inherent_offset(MMC_RESERVED_NAME);
1577 if (-1 == offset) {
1578 apt_err("can't find %s in inherent\n", MMC_RESERVED_NAME);
1579 return -1;
1580 }
1581
1582 if (!strcmp(name, "dtb")) {
1583 strncpy(partition->name, name, sizeof(partition->name) - 1);
1584 partition->name[sizeof(partition->name) - 1] = '\0';
1585 partition->offset = offset + vpart->offset;
1586 partition->size = (vpart->size * DTB_COPIES);
1587 }
1588
1589 return ret;
1590}
1591
1592int find_dev_num_by_partition_name (char const *name)
1593{
1594 int dev = -1;
1595
1596 /* card */
1597 if (!strcmp(name, MMC_CARD_PARTITION_NAME)) {
1598 dev = 0;
1599 } else { /* eMMC OR TSD */
1600 /* partition name is valid */
1601 if (find_mmc_partition_by_name(name)) {
1602 dev = 1;
1603 }
1604 }
1605 return dev;
1606}
1607
1608static inline uint64_t get_part_size(struct partitions *part, int num)
1609{
1610 return part[num].size;
1611}
1612
1613static inline uint64_t get_part_offset(struct partitions *part, int num)
1614{
1615 return part[num].offset;
1616}
1617
1618static inline char * get_part_name(struct partitions *part, int num)
1619{
1620 return (char *)part[num].name;
1621}
1622
1623int get_part_info_from_tbl(struct blk_desc *dev_desc,
1624 int num, disk_partition_t *info)
1625{
1626 int ret = 0;
1627 struct partitions *part;
1628
1629 if (NULL == p_iptbl_ept)
1630 return -1;
1631 if (num > (p_iptbl_ept->count-1))
1632 return -1;
1633 part = p_iptbl_ept->partitions;
1634
1635 /*get partition info by index! */
1636 info->start = (lbaint_t)(get_part_offset(part, num)/dev_desc->blksz);
1637 info->size = (lbaint_t)(get_part_size(part, num)/dev_desc->blksz);
1638 info->blksz = dev_desc->blksz;
1639 strcpy((char *)info->name, get_part_name(part, num));
1640
1641 return ret;
1642}
1643#if (CONFIG_MPT_DEBUG)
1644void show_partition_info(disk_partition_t *info)
1645{
1646 printf("----------%s----------\n", __func__);
1647 printf("name %10s\n", info->name);
1648 printf("blksz " LBAFU "\n", info->blksz);
1649 printf("sart %ld\n", info->start);
1650 printf("size %ld\n", info->size);
1651 printf("----------end----------\n");
1652}
1653#endif
1654
1655struct partitions *aml_get_partition_by_name(const char *name)
1656{
1657 struct partitions *partition = NULL;
1658 partition = _find_partition_by_name(emmc_partition_table,
1659 get_emmc_partition_arraysize(), name);
1660 if (partition == NULL)
1661 apt_wrn("do not find match in inherent table %s\n", name);
1662 return partition;
1663}
1664
1665struct virtual_partition *aml_get_virtual_partition_by_name(const char *name)
1666{
1667 int i = 0, cnt;
1668 struct virtual_partition *part = NULL;
1669 cnt = get_emmc_virtual_partition_arraysize();
1670 while (i < cnt) {
1671
1672 part = &virtual_partition_table[i];
1673 if (!strcmp(name, part->name)) {
1674 apt_info("find %10s @ tbl[%d]\n", name, i);
1675 break;
1676 }
1677 i++;
1678 };
1679 if (i == cnt) {
1680 part = NULL;
1681 apt_wrn("do not find match in table %10s\n", name);
1682 }
1683 return part;
1684}
1685
1686int get_part_info_by_name(struct blk_desc *dev_desc,
1687 const char *name, disk_partition_t *info)
1688{
1689 struct partitions *partition = NULL;
1690 struct partitions virtual;
1691 int ret = 0;
1692 cpu_id_t cpu_id = get_cpu_id();
1693
1694 partition = find_mmc_partition_by_name((char *)name);
1695 if (partition) {
1696 info->start = (lbaint_t)(partition->offset/dev_desc->blksz);
1697 info->size = (lbaint_t)(partition->size/dev_desc->blksz);
1698 info->blksz = dev_desc->blksz;
1699 strcpy((char *)info->name, partition->name);
1700 } else if (!find_virtual_partition_by_name((char *)name, &virtual)) {
1701 /* try virtual partitions */
1702 apt_wrn("Got %s in virtual table\n", name);
1703 info->start = (lbaint_t)(virtual.offset/dev_desc->blksz);
1704 info->size = (lbaint_t)(virtual.size/dev_desc->blksz);
1705 info->blksz = dev_desc->blksz;
1706 strcpy((char *)info->name, virtual.name);
1707 } else {
1708 /* all partitions were tried, fail */
1709 ret = -1;
1710 goto _out;
1711 }
1712 /* for bootloader */
1713 if ((0 == info->start) && (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL)) {
1714 info->start = 1;
1715 info->size -= 1;
1716 }
1717
1718#if (CONFIG_MPT_DEBUG)
1719 show_partition_info(info);
1720#endif
1721_out:
1722 return ret;
1723}
1724
1725
1726/*
1727 * get the partition number by name
1728 * return value
1729 * < 0 means no partition found
1730 * >= 0 means valid partition
1731 */
1732__weak int get_partition_num_by_name(char const *name)
1733{
1734 int ret = -1;
1735 struct partitions *partition = NULL;
1736
1737 if (NULL == p_iptbl_ept)
1738 goto _out;
1739 partition = p_iptbl_ept->partitions;
1740 ret = _get_part_index_by_name(partition,
1741 p_iptbl_ept->count, name);
1742_out:
1743 return ret;
1744}
1745
1746/*
1747 * get the partition info by number
1748 * return value
1749 * < 0 means no partition found
1750 * >= 0 means valid partition
1751 */
1752__weak struct partitions *get_partition_info_by_num(const int num)
1753{
1754 struct partitions *partition = NULL;
1755
1756 if ((NULL == p_iptbl_ept)
1757 || (num >= p_iptbl_ept->count))
1758 goto _out;
1759 partition = &p_iptbl_ept->partitions[num];
1760
1761_out:
1762 return partition;
1763}