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