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