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