blob: ea50f9ab3a5bb9cf58a96ac88b918660560c9e1c [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
Dongjin Kim3f0c8b72025-05-08 18:25:56 +09001764#ifdef CONFIG_S7D_ODROIDC5
1765 {
1766 const char *sign = "@ML";
1767 int len = strlen(sign);
1768 char buf[512];
1769
1770 ret = blk_dread(mmc_get_blk_desc(mmc), 1, 1, buf);
1771 if (ret) {
1772 if (!memcmp(buf, sign, len))
1773 return 0;
1774 }
1775 }
1776#endif
1777
Ruixuan.lifd943de2024-01-19 15:48:40 +08001778 iptbl_inh.count = get_emmc_partition_arraysize();
1779 if (iptbl_inh.count) {
1780 iptbl_inh.partitions = emmc_partition_table;
1781 _calculate_offset(mmc, &iptbl_inh, 0);
1782 }
1783
ruixuan.liffca1b92023-02-24 16:18:59 +08001784 if (!p_iptbl_ept) {
1785 ret = _zalloc_iptbl(&p_iptbl_ept);
1786 if (ret)
1787 return ret;
1788 } else {
1789 p_iptbl_ept->count = 0;
1790 memset(p_iptbl_ept->partitions, 0,
1791 sizeof(struct partitions) * MAX_PART_COUNT);
1792 }
1793
1794 ret = get_ept_from_gpt(mmc);
1795 if (!ret) {
1796 part_init(mmc_get_blk_desc(mmc));
1797 return ret;
1798 }
1799
1800 printf("gpt is not exist, partition registe failed\n");
1801 return ret;
1802}
1803
jinbiao890dba62024-09-04 04:04:22 +00001804struct partitions *find_mmc_partition_by_name(char const *name)
Bo Lv72d0e902023-01-02 14:27:34 +00001805{
1806 struct partitions *partition = NULL;
1807
1808 apt_info("p_iptbl_ept %p\n", p_iptbl_ept);
1809 if (NULL == p_iptbl_ept) {
1810 goto _out;
1811 }
1812 partition = p_iptbl_ept->partitions;
1813 partition = _find_partition_by_name(partition,
1814 p_iptbl_ept->count, name);
1815 apt_info("partition %p\n", partition);
1816 if (!partition) {
1817 partition = _find_partition_by_name(emmc_partition_table,
1818 get_emmc_partition_arraysize(), name);
1819 }
1820 apt_info("partition %p\n", partition);
1821_out:
1822 return partition;
1823}
1824
1825/*
1826 find virtual partition in inherent table.
1827*/
1828int find_virtual_partition_by_name (char const *name, struct partitions *partition)
1829{
1830 int ret = 0;
1831 ulong offset;
1832 struct virtual_partition *vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
1833 if (NULL == partition)
1834 return -1;
1835
1836 offset = _get_inherent_offset(MMC_RESERVED_NAME);
1837 if (-1 == offset) {
1838 apt_err("can't find %s in inherent\n", MMC_RESERVED_NAME);
1839 return -1;
1840 }
1841
1842 if (!strcmp(name, "dtb")) {
1843 strncpy(partition->name, name, sizeof(partition->name) - 1);
1844 partition->name[sizeof(partition->name) - 1] = '\0';
1845 partition->offset = offset + vpart->offset;
1846 partition->size = (vpart->size * DTB_COPIES);
1847 }
1848
1849 return ret;
1850}
1851
1852int find_dev_num_by_partition_name (char const *name)
1853{
1854 int dev = -1;
1855
1856 /* card */
1857 if (!strcmp(name, MMC_CARD_PARTITION_NAME)) {
1858 dev = 0;
1859 } else { /* eMMC OR TSD */
1860 /* partition name is valid */
1861 if (find_mmc_partition_by_name(name)) {
1862 dev = 1;
1863 }
1864 }
1865 return dev;
1866}
1867
1868static inline uint64_t get_part_size(struct partitions *part, int num)
1869{
1870 return part[num].size;
1871}
1872
1873static inline uint64_t get_part_offset(struct partitions *part, int num)
1874{
1875 return part[num].offset;
1876}
1877
1878static inline char * get_part_name(struct partitions *part, int num)
1879{
1880 return (char *)part[num].name;
1881}
1882
1883int get_part_info_from_tbl(struct blk_desc *dev_desc,
1884 int num, disk_partition_t *info)
1885{
1886 int ret = 0;
1887 struct partitions *part;
1888
1889 if (NULL == p_iptbl_ept)
1890 return -1;
1891 if (num > (p_iptbl_ept->count-1))
1892 return -1;
1893 part = p_iptbl_ept->partitions;
1894
1895 /*get partition info by index! */
1896 info->start = (lbaint_t)(get_part_offset(part, num)/dev_desc->blksz);
1897 info->size = (lbaint_t)(get_part_size(part, num)/dev_desc->blksz);
1898 info->blksz = dev_desc->blksz;
1899 strcpy((char *)info->name, get_part_name(part, num));
1900
1901 return ret;
1902}
1903#if (CONFIG_MPT_DEBUG)
1904void show_partition_info(disk_partition_t *info)
1905{
1906 printf("----------%s----------\n", __func__);
1907 printf("name %10s\n", info->name);
1908 printf("blksz " LBAFU "\n", info->blksz);
1909 printf("sart %ld\n", info->start);
1910 printf("size %ld\n", info->size);
1911 printf("----------end----------\n");
1912}
1913#endif
1914
1915struct partitions *aml_get_partition_by_name(const char *name)
1916{
1917 struct partitions *partition = NULL;
1918 partition = _find_partition_by_name(emmc_partition_table,
1919 get_emmc_partition_arraysize(), name);
1920 if (partition == NULL)
1921 apt_wrn("do not find match in inherent table %s\n", name);
1922 return partition;
1923}
1924
1925struct virtual_partition *aml_get_virtual_partition_by_name(const char *name)
1926{
1927 int i = 0, cnt;
1928 struct virtual_partition *part = NULL;
1929 cnt = get_emmc_virtual_partition_arraysize();
1930 while (i < cnt) {
1931
1932 part = &virtual_partition_table[i];
1933 if (!strcmp(name, part->name)) {
1934 apt_info("find %10s @ tbl[%d]\n", name, i);
1935 break;
1936 }
1937 i++;
1938 };
1939 if (i == cnt) {
1940 part = NULL;
1941 apt_wrn("do not find match in table %10s\n", name);
1942 }
1943 return part;
1944}
1945
1946int get_part_info_by_name(struct blk_desc *dev_desc,
1947 const char *name, disk_partition_t *info)
1948{
1949 struct partitions *partition = NULL;
1950 struct partitions virtual;
1951 int ret = 0;
1952 cpu_id_t cpu_id = get_cpu_id();
1953
1954 partition = find_mmc_partition_by_name((char *)name);
1955 if (partition) {
1956 info->start = (lbaint_t)(partition->offset/dev_desc->blksz);
1957 info->size = (lbaint_t)(partition->size/dev_desc->blksz);
1958 info->blksz = dev_desc->blksz;
1959 strcpy((char *)info->name, partition->name);
1960 } else if (!find_virtual_partition_by_name((char *)name, &virtual)) {
1961 /* try virtual partitions */
1962 apt_wrn("Got %s in virtual table\n", name);
1963 info->start = (lbaint_t)(virtual.offset/dev_desc->blksz);
1964 info->size = (lbaint_t)(virtual.size/dev_desc->blksz);
1965 info->blksz = dev_desc->blksz;
1966 strcpy((char *)info->name, virtual.name);
1967 } else {
1968 /* all partitions were tried, fail */
1969 ret = -1;
1970 goto _out;
1971 }
1972 /* for bootloader */
1973 if ((0 == info->start) && (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL)) {
1974 info->start = 1;
1975 info->size -= 1;
1976 }
1977
1978#if (CONFIG_MPT_DEBUG)
1979 show_partition_info(info);
1980#endif
1981_out:
1982 return ret;
1983}
1984
1985
1986/*
1987 * get the partition number by name
1988 * return value
1989 * < 0 means no partition found
1990 * >= 0 means valid partition
1991 */
1992__weak int get_partition_num_by_name(char const *name)
1993{
1994 int ret = -1;
1995 struct partitions *partition = NULL;
1996
1997 if (NULL == p_iptbl_ept)
1998 goto _out;
1999 partition = p_iptbl_ept->partitions;
2000 ret = _get_part_index_by_name(partition,
2001 p_iptbl_ept->count, name);
2002_out:
2003 return ret;
2004}
2005
2006/*
2007 * get the partition info by number
2008 * return value
2009 * < 0 means no partition found
2010 * >= 0 means valid partition
2011 */
2012__weak struct partitions *get_partition_info_by_num(const int num)
2013{
2014 struct partitions *partition = NULL;
2015
2016 if ((NULL == p_iptbl_ept)
2017 || (num >= p_iptbl_ept->count))
2018 goto _out;
2019 partition = &p_iptbl_ept->partitions[num];
2020
2021_out:
2022 return partition;
2023}
ruixuan.li554d4e92023-02-28 17:11:25 +08002024
2025int check_gpt_part(struct blk_desc *dev_desc, void *buf)
2026{
ruixuan.li554d4e92023-02-28 17:11:25 +08002027 gpt_header *gpt_h;
2028 gpt_entry *gpt_e;
2029 u32 calc_crc32;
2030 int i;
2031 u32 entries_num;
2032#if (ADD_LAST_PARTITION)
2033 ulong gap = GPT_GAP;
2034#endif
2035 u64 offset_old, size_old;
2036 u64 offset_new, size_new;
2037 int ret = 0;
2038 bool alternate_flag = false;
jinbiao8794b482023-12-26 12:40:24 +00002039 lbaint_t last_usable_lba, last_ending_lba;
ruixuan.li554d4e92023-02-28 17:11:25 +08002040
2041 /* determine start of GPT Header in the buffer */
2042 gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
2043 dev_desc->blksz);
2044
2045 /* determine start of GPT Entries in the buffer */
2046 gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
2047 dev_desc->blksz);
2048 entries_num = le32_to_cpu(gpt_h->num_partition_entries);
2049
jinbiao8794b482023-12-26 12:40:24 +00002050 if (le64_to_cpu(gpt_h->alternate_lba) != (dev_desc->lba - 1)) {
ruixuan.li554d4e92023-02-28 17:11:25 +08002051 printf("GPT: alternate_lba: %llX, " LBAF ", reset it\n",
2052 le64_to_cpu(gpt_h->alternate_lba), dev_desc->lba);
2053 gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
2054 alternate_flag = true;
2055 }
2056
jinbiao8794b482023-12-26 12:40:24 +00002057 if (alternate_flag) {
2058 last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
jinbiao4cdaa182024-10-15 11:14:44 +00002059 last_ending_lba = ((last_usable_lba >> 12) << 12) - 1;
jinbiao8794b482023-12-26 12:40:24 +00002060 } else {
2061 last_usable_lba = cpu_to_le64(dev_desc->lba - 1);
2062 last_ending_lba = last_usable_lba;
2063 }
2064
2065 if (le64_to_cpu(gpt_h->last_usable_lba) != last_usable_lba) {
2066 printf("GPT: last_usable_lba incorrect: %llX != " LBAF ", reset it\n",
2067 le64_to_cpu(gpt_h->last_usable_lba), last_usable_lba);
2068 gpt_h->last_usable_lba = last_usable_lba;
ruixuan.li554d4e92023-02-28 17:11:25 +08002069 }
2070
2071 for (i = 0; i < entries_num; i++) {
2072#if (ADD_LAST_PARTITION)
2073 if (i == entries_num - 1) {
2074 gpt_e[i - 1].ending_lba -= gpt_e[i].ending_lba + le64_to_cpu(gap) + 1;
2075 gpt_e[i].starting_lba = gpt_e[i - 1].ending_lba + le64_to_cpu(gap) + 1;
jinbiao8794b482023-12-26 12:40:24 +00002076 gpt_e[i].ending_lba = last_ending_lba;
ruixuan.li554d4e92023-02-28 17:11:25 +08002077 }
2078
2079#endif
jinbiaoc6b040f2023-11-27 02:46:06 +00002080 if (le64_to_cpu(gpt_e[i].starting_lba) > gpt_h->last_usable_lba) {
2081 printf("gpt_e[%d].starting_lba: %llX > %llX, writing failed\n", i,
2082 le64_to_cpu(gpt_e[i].starting_lba),
2083 le64_to_cpu(gpt_h->last_usable_lba));
2084 return 1;
2085 }
jinbiao8794b482023-12-26 12:40:24 +00002086 if ((le64_to_cpu(gpt_e[i].ending_lba) > last_ending_lba) ||
2087 ((i == entries_num - 1) &&
2088 le64_to_cpu(gpt_e[i].ending_lba) != last_ending_lba)) {
2089 printf("gpt_e[%d].ending_lba: %llX, last_ending_lba: %lX, reset it\n",
2090 i, le64_to_cpu(gpt_e[i].ending_lba), last_ending_lba);
2091 gpt_e[i].ending_lba = last_ending_lba;
ruixuan.li554d4e92023-02-28 17:11:25 +08002092 printf("gpt_e[%d].ending_lba: %llX\n", i, gpt_e[i].ending_lba);
2093 }
Xindong Xu7f58de92024-03-01 14:21:52 +08002094 if (le64_to_cpu(gpt_h->alternate_lba) > le64_to_cpu(gpt_e[i].starting_lba) &&
2095 le64_to_cpu(gpt_h->alternate_lba) < le64_to_cpu(gpt_e[i].ending_lba)) {
2096 printf("%s: alternate_lba: %llX during part %d, invalid, reset it\n",
2097 __func__, le64_to_cpu(gpt_h->alternate_lba), i);
2098 gpt_h->alternate_lba = gpt_e[1].starting_lba - 1;
2099 }
ruixuan.li554d4e92023-02-28 17:11:25 +08002100 }
2101
2102 calc_crc32 = crc32(0, (const unsigned char *)gpt_e,
2103 entries_num * le32_to_cpu(gpt_h->sizeof_partition_entry));
2104 gpt_h->partition_entry_array_crc32 = calc_crc32;
2105 gpt_h->header_crc32 = 0;
2106 calc_crc32 = crc32(0, (const unsigned char *)gpt_h,
2107 le32_to_cpu(gpt_h->header_size));
2108 gpt_h->header_crc32 = calc_crc32;
2109
2110 for (i = 0; i < le32_to_cpu(gpt_h->num_partition_entries); i++) {
Ruixuan.li05acd9b2023-08-04 09:44:36 +08002111 if (!is_pte_valid(&gpt_e[i]))
ruixuan.li554d4e92023-02-28 17:11:25 +08002112 break;
2113
Ruixuan.li05acd9b2023-08-04 09:44:36 +08002114 offset_old = le64_to_cpu(gpt_e[i].starting_lba << 9ULL);
2115 size_old = ((le64_to_cpu(gpt_e[i].ending_lba) + 1) -
2116 le64_to_cpu(gpt_e[i].starting_lba)) << 9ULL;
ruixuan.li554d4e92023-02-28 17:11:25 +08002117
2118 offset_new = le64_to_cpu(gpt_e[i].starting_lba << 9ULL);
2119 size_new = ((le64_to_cpu(gpt_e[i].ending_lba) + 1) -
2120 le64_to_cpu(gpt_e[i].starting_lba)) << 9ULL;
2121
2122 if (offset_old != offset_new || size_old != size_new) {
2123 printf("old %02d %10ls %016llx %016llx\n",
Ruixuan.li05acd9b2023-08-04 09:44:36 +08002124 i, gpt_e[i].partition_name,
ruixuan.li554d4e92023-02-28 17:11:25 +08002125 offset_old, size_old);
2126 printf("new %02d %10ls %016llx %016llx\n",
2127 i, gpt_e[i].partition_name,
2128 offset_new, size_new);
2129 ret = 1;
2130 printf("partition changes, erase\n");
2131 goto _out;
2132 }
2133 }
2134
2135_out:
ruixuan.li554d4e92023-02-28 17:11:25 +08002136 return ret;
2137}
Ruixuan.lifd943de2024-01-19 15:48:40 +08002138
2139/* unifykey backup distribution */
2140
2141/*--------------------------------------------------------
2142 * offset | 0x12020 | 0x12220 | 0x12420 | 0x12421 |
2143 *--------------------------------------------------------
2144 * size | 200 block | 200 block | 1 block | 1 block |
2145 *--------------------------------------------------------
2146 *content | key1 | key2 | checksum1 | checksum2 |
2147 *--------------------------------------------------------
2148 */
2149static u64 _calc_key_checksum(void *addr, int size)
2150{
2151 int i = 0;
2152 u32 *buffer;
2153 u64 checksum = 0;
2154
2155 if ((u64)addr % 4 != 0)
2156 BUG();
2157
2158 buffer = (u32 *)addr;
2159 size = size >> 2;
2160 while (i < size)
2161 checksum += buffer[i++];
2162
2163 return checksum;
2164}
2165
2166static int _key_read(struct mmc *mmc, u64 blk, u64 cnt, void * addr)
2167{
2168 int dev = EMMC_DTB_DEV;
2169 u64 n;
2170 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
2171 if (n != cnt) {
2172 printf("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
2173 __func__, dev, blk, cnt);
2174 }
2175
2176 return (n != cnt);
2177}
2178
jinbiao0cd57162024-04-09 08:23:25 +00002179static int _verify_key_checksum(struct mmc *mmc, void *addr, int cpy, unsigned int size)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002180{
2181 u64 checksum;
2182 int ret = 0;
2183 u64 blk, key_glb_offset;
2184 struct partitions * part = NULL;
2185 struct virtual_partition *vpart = NULL;
2186 char checksum_info[512] = {0};
2187
2188 vpart = aml_get_virtual_partition_by_name(MMC_KEY_NAME);
2189 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
2190 key_glb_offset = part->offset + vpart->offset;
2191
2192 blk = (key_glb_offset + 2 * (vpart->size)) / MMC_BLOCK_SIZE + cpy;
2193 ret = _key_read(mmc, blk, 1, (void *)checksum_info);
2194 if (ret)
2195 return -1;
2196
2197 memcpy(&key_infos[cpy], checksum_info, sizeof(struct aml_key_info));
2198
jinbiao0cd57162024-04-09 08:23:25 +00002199 checksum = _calc_key_checksum(addr, size);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002200 printf("calc %llx, store %llx\n", checksum, key_infos[cpy].checksum);
2201
2202 return !(checksum == key_infos[cpy].checksum);
2203}
2204
jinbiao0cd57162024-04-09 08:23:25 +00002205static int update_key_info(struct mmc *mmc, unsigned char *addr, unsigned int size)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002206{
2207 int ret = 0;
2208 u64 blk, cnt, key_glb_offset;
2209 int cpy = 1;
2210 struct partitions * part = NULL;
2211 struct virtual_partition *vpart = NULL;
2212 int valid_flag = 0;
2213
2214 vpart = aml_get_virtual_partition_by_name(MMC_KEY_NAME);
2215 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
2216 key_glb_offset = part->offset + vpart->offset;
2217
2218 while (cpy >= 0) {
2219 blk = (key_glb_offset + cpy * (vpart->size)) / MMC_BLOCK_SIZE;
jinbiao0cd57162024-04-09 08:23:25 +00002220 cnt = size / mmc->read_bl_len;
Ruixuan.lifd943de2024-01-19 15:48:40 +08002221 ret = _key_read(mmc, blk, cnt, addr);
2222 if (ret) {
2223 printf("%s: block # %#llx, cnt # %#llx ERROR!\n",
2224 __func__, blk, cnt);
2225 return -1;
2226 }
2227
jinbiao0cd57162024-04-09 08:23:25 +00002228 ret = _verify_key_checksum(mmc, addr, cpy, size);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002229 if (!ret && key_infos[cpy].magic != 0)
2230 valid_flag += cpy + 1;
2231 else
2232 printf("cpy %d is not valid\n", cpy);
2233 cpy--;
2234 }
2235
2236 if (key_infos[0].stamp > key_infos[1].stamp)
2237 mmc->key_stamp = key_infos[0].stamp;
2238 else
2239 mmc->key_stamp = key_infos[1].stamp;
2240
2241 return valid_flag;
2242}
2243
2244static int _key_write(struct mmc *mmc, u64 blk, u64 cnt, void *addr)
2245{
2246 int dev = STORAGE_EMMC;
2247 u32 n;
2248 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
2249 if (n != cnt) {
2250 printf("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
2251 __func__, dev, blk, cnt);
2252 }
2253
2254 return (n != cnt);
2255}
2256
jinbiao0cd57162024-04-09 08:23:25 +00002257static int write_invalid_key(struct mmc *mmc, void *addr, unsigned int size, int valid_flag)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002258{
2259 u64 blk, cnt, key_glb_offset;
2260 int ret;
2261 struct partitions * part = NULL;
2262 struct virtual_partition *vpart = NULL;
2263 char checksum_info[512] = {0};
2264
2265 if (valid_flag > 2 || valid_flag < 1)
2266 return 1;
2267
2268 vpart = aml_get_virtual_partition_by_name(MMC_KEY_NAME);
2269 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
2270 key_glb_offset = part->offset + vpart->offset;
2271
2272 blk = (key_glb_offset + (valid_flag - 1) * (vpart->size)) / MMC_BLOCK_SIZE;
jinbiao0cd57162024-04-09 08:23:25 +00002273 cnt = size / mmc->read_bl_len;
Ruixuan.lifd943de2024-01-19 15:48:40 +08002274
2275 if (_key_read(mmc, blk, cnt, addr)) {
jinbiao0cd57162024-04-09 08:23:25 +00002276 printf("%s: block # %#llx,cnt # %#llx ERROR!\n", __func__, blk, cnt);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002277 ret = -2;
2278 }
2279 /* fixme, update the invalid one - key1 */
2280 blk = (key_glb_offset + (valid_flag % 2) * vpart->size) / MMC_BLOCK_SIZE;
2281 if (_key_write(mmc, blk, cnt, addr)) {
jinbiao0cd57162024-04-09 08:23:25 +00002282 printf("%s: block # %#llx,cnt # %#llx ERROR!\n", __func__, blk, cnt);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002283 ret = -4;
2284 }
2285
2286 memcpy(checksum_info, &key_infos[valid_flag - 1], sizeof(struct aml_key_info));
2287 blk = (key_glb_offset + 2 * (vpart->size)) / MMC_BLOCK_SIZE + valid_flag % 2;
2288 if (_key_write(mmc, blk, 1, checksum_info)) {
jinbiao0cd57162024-04-09 08:23:25 +00002289 printf("%s: block # %#llx,cnt # %#llx ERROR!\n", __func__, blk, cnt);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002290 ret = -4;
2291 }
2292
2293 return ret;
2294}
2295
jinbiao0cd57162024-04-09 08:23:25 +00002296static int update_invalid_key(struct mmc *mmc, void *addr, unsigned int size, int valid_flag)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002297{
jinbiao0cd57162024-04-09 08:23:25 +00002298 int ret = 0;
Ruixuan.lifd943de2024-01-19 15:48:40 +08002299
jinbiao0cd57162024-04-09 08:23:25 +00002300 printf("update key%d\n", (valid_flag == 2) ? 1 : 2);
2301 ret = write_invalid_key(mmc, addr, size, valid_flag);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002302
Ruixuan.lifd943de2024-01-19 15:48:40 +08002303 return ret;
2304}
2305
jinbiao0cd57162024-04-09 08:23:25 +00002306int update_old_key(struct mmc *mmc, void *addr, unsigned int size)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002307{
2308 int ret = 0;
2309 int valid_flag;
2310
2311 if (stamp_after(key_infos[1].stamp, key_infos[0].stamp)) {
2312 memcpy(&key_infos[1], &key_infos[0], sizeof(struct aml_key_info));
2313 valid_flag = 2;
2314 } else if (stamp_after(key_infos[0].stamp, key_infos[1].stamp)) {
2315 memcpy(&key_infos[0], &key_infos[1], sizeof(struct aml_key_info));
2316 valid_flag = 1;
2317 } else {
2318 printf("do nothing\n");
2319 return ret;
2320 }
2321
jinbiao0cd57162024-04-09 08:23:25 +00002322 ret = write_invalid_key(mmc, addr, size, valid_flag);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002323 /*update key*/
2324 if (ret)
2325 ret = -3;
2326 mmc->key_stamp = key_infos[0].stamp;
2327 return ret;
2328}
2329
2330static struct mmc *_rsv_init(void)
2331{
2332 struct mmc *mmc = find_mmc_device(STORAGE_EMMC);
2333 if (!mmc) {
2334 printf("not find mmc\n");
2335 return NULL;
2336 }
2337
2338 if (mmc_init(mmc)) {
2339 printf("mmc init failed\n");
2340 return NULL;
2341 }
2342
2343 return mmc;
2344}
2345
jinbiao0cd57162024-04-09 08:23:25 +00002346int mmc_key_write_backup(const char *name, unsigned char *addr, unsigned int size)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002347{
2348 int ret = 0;
2349 u64 blk, cnt, key_glb_offset;
2350 int cpy;
2351 struct mmc * mmc;
2352 struct partitions * part = NULL;
2353 struct virtual_partition *vpart = NULL;
2354 char checksum_info[512] = {0};
2355
2356 vpart = aml_get_virtual_partition_by_name(MMC_KEY_NAME);
2357 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
2358 key_glb_offset = part->offset + vpart->offset;
2359
2360 mmc = _rsv_init();
2361 if (mmc == NULL)
2362 return -10;
2363
2364 key_infos[0].stamp = mmc->key_stamp + 1;
2365 key_infos[0].magic = 9;
jinbiao0cd57162024-04-09 08:23:25 +00002366 key_infos[0].checksum = _calc_key_checksum(addr, size);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002367 printf("new stamp %d, checksum 0x%llx, magic %d\n",
2368 key_infos[0].stamp, key_infos[0].checksum, key_infos[0].magic);
2369
2370 memcpy(checksum_info, &key_infos[0], sizeof(struct aml_key_info));
2371
2372 for (cpy = 0; cpy < KEY_COPIES; cpy++) {
2373 blk = (key_glb_offset + cpy * (vpart->size)) / MMC_BLOCK_SIZE;
jinbiao0cd57162024-04-09 08:23:25 +00002374 cnt = size / mmc->read_bl_len;
Ruixuan.lifd943de2024-01-19 15:48:40 +08002375 ret |= _key_write(mmc, blk, cnt, addr);
2376
2377 blk = (key_glb_offset + 2 * (vpart->size)) / MMC_BLOCK_SIZE + cpy;
2378 ret |= _key_write(mmc, blk, 1, checksum_info);
2379 }
2380
2381 if (ret) {
2382 printf("%s() %d: emmc init %d\n", __func__, __LINE__, ret);
2383 ret = -2;
2384 }
2385
2386 return ret;
2387}
2388
jinbiao0cd57162024-04-09 08:23:25 +00002389int mmc_key_read_backup(const char *name, unsigned char *addr, unsigned int size)
Ruixuan.lifd943de2024-01-19 15:48:40 +08002390{
2391 int valid = 0;
2392 struct mmc *mmc;
2393
2394 mmc = _rsv_init();
2395 if (mmc == NULL)
2396 return -10;
2397
2398 /* check valid key flag , addr save the first key content */
jinbiao0cd57162024-04-09 08:23:25 +00002399 valid = update_key_info(mmc, addr, size);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002400 switch (valid) {
2401 /* none is valid, using the 1st one for compatibility*/
2402 case 0:
2403 goto _out;
2404 break;
2405 /* only first is valid, using the first update the second */
2406 case 1:
jinbiao0cd57162024-04-09 08:23:25 +00002407 update_invalid_key(mmc, addr, size, 1);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002408 break;
2409 /* only second is valid, using the second */
2410 case 2:
jinbiao0cd57162024-04-09 08:23:25 +00002411 update_invalid_key(mmc, addr, size, 2);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002412 break;
2413 case 3:
2414 /*update the old key */
jinbiao0cd57162024-04-09 08:23:25 +00002415 update_old_key(mmc, addr, size);
Ruixuan.lifd943de2024-01-19 15:48:40 +08002416 break;
2417 default:
2418 printf("impossible valid values.\n");
2419 BUG();
2420 break;
2421 }
2422_out:
2423 return 0;
2424}
2425