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