blob: fdfac02a4cba58dfbbfe4ebabdb421d27f26a07a [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 <linux/kernel.h>
9#include <amlogic/aml_efuse.h>
10#include <amlogic/cpu_id.h>
11#include <amlogic/storage.h>
12#include <amlogic/partition_table.h>
13#include <fastboot.h>
14#include <amlogic/emmc_partitions.h>
15#include <asm/amlogic/arch/efuse.h>
16#include <android_image.h>
17#include <amlogic/android_vab.h>
Mingyen Hung6e468002023-01-04 23:43:04 -080018#include <amlogic/aml_rollback.h>
Xindong Xu22e8daf2024-03-12 18:08:41 +080019#include <cli.h>
Zhigang Yua69e3f92024-06-18 03:13:38 +000020#include <amlogic/store_wrapper.h>
21
Bo Lv72d0e902023-01-02 14:27:34 +000022
23#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
24extern efuse_obj_field_t efuse_field;
25#endif//#ifdef CONFIG_EFUSE_OBJ_API
26
Bo Lv72d0e902023-01-02 14:27:34 +000027int __attribute__((weak)) store_logic_read(const char *name, loff_t off, size_t size, void *buf)
28{ return store_read(name, off, size, buf);}
29
Bo Lv72d0e902023-01-02 14:27:34 +000030#define debugP(fmt...) //printf("[DbgBootSta]L%d:", __LINE__),printf(fmt)
31#define errorP(fmt...) printf("ErrBootSta(L%d):", __LINE__),printf(fmt)
32#define wrnP(fmt...) printf("wrn:"fmt)
33#define MsgP(fmt...) printf("[BootSta]"fmt)
34
35#define BOOTLOADER_OFFSET 512
36#define BOOTLOADER_MAX_SIZE (4 * 1024 * 1024)
Zhigang Yude5719e2024-03-08 09:14:23 +000037#define MIB_SIZE (1024 * 1024)
38
Bo Lv72d0e902023-01-02 14:27:34 +000039
40//check SWPL-31296 for details
41static int do_get_bootloader_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
42{
43 bool printStat = false;
44 bool saveenv = false;
45 debugP("Initial value for argc=%d\n", argc);
46 while (argc > 1 && **(argv + 1) == '-') {
47 char *arg = *++argv;
48
49 --argc;
50 while (*++arg) {
51 switch (*arg) {
52 case 'p': /* print */
53 printStat = true;
54 break;
55 case 's': /* saveenv */
56 saveenv = true;
57 break;
58 default:
59 return CMD_RET_USAGE;
60 }
61 }
62 }
63 debugP("Final value for argc=%d\n", argc);
64 //1,forUpgrade_socType, cpu familyId
65 const cpu_id_t cpuid = get_cpu_id();
66 const int familyId = cpuid.family_id;
67 env_set_hex("forUpgrade_socType", familyId);
68
69 //2,forUpgrade_secureBoot
70 const bool secureboot = IS_FEAT_BOOT_VERIFY();
71 env_set("forUpgrade_secureBoot", secureboot ? "true" : "false");
72
73 //3,forUpgrade_robustOta
74 bool supportRobustOta = false;
75 switch (familyId) {
76 case 0x32://sc2
77 case 0x36://t7
78 case 0x37://s4
79 case 0x38://t3
80 case 0x3A://s4d
81 supportRobustOta = true;
82 break;
83 default:
84 {
85 if (familyId > 0x3A) {
86 supportRobustOta = true;
87 }
88 }
89 break;
90 }
91 env_set("forUpgrade_robustOta", supportRobustOta ? "true" : "false");
92
93 //4,forUpgrade_flashType
94 const char* BootDevices[] = {
95 "BOOT_EMMC", "BOOT_SD",
96 "BOOT_NAND_NFTL", "BOOT_NAND_MTD",
97 "BOOT_SNAND", "BOOT_SNOR",
98 };
99 const char* bootDevice = "BOOT_NONE";
100 enum boot_type_e bootType = store_get_type();
101 int i = 0;
102 for (; i < ARRAY_SIZE(BootDevices); ++i) {
103 if ((1<<i) != bootType) continue;
104 bootDevice = BootDevices[i];
105 break;
106 }
107 env_set("forUpgrade_flashType", bootDevice);
108
109 //5,forUpgrade_bootloaderCopies, how many copies supported
110 int bootCopies = 1;
111 switch (bootType) {
112 case BOOT_EMMC: bootCopies = 3; break;
113 default:break;
114 }
115 env_set_ulong("forUpgrade_bootloaderCopies", bootCopies);
116
117 //6,forUpgrade_bootloaderIndex
118 //for emmc, 0/1/2 is user/boot0/boot1
119 const int bootCpyIndex = store_bootup_bootidx("bootloader");
120 env_set_ulong("forUpgrade_bootloaderIndex", bootCpyIndex);
121
122 //7,get first boot index, for defendkey
123 const int firstBootCpyIndex = store_boot_copy_start();
124 env_set_ulong("forUpgrade_1stBootIndex", firstBootCpyIndex);
125
126 if (printStat) run_command("printenv forUpgrade_socType forUpgrade_secureBoot "
127 " forUpgrade_robustOta forUpgrade_flashType forUpgrade_bootloaderCopies "
128 " forUpgrade_bootloaderIndex forUpgrade_1stBootIndex", 0);
129
Sam Wuefee52f2024-04-29 12:03:12 +0800130 //8,production mode for ver4 boot.img bootconfig
131 env_set_ulong("production_mode", CONFIG_IS_ENABLED(AML_PRODUCT_MODE));
132 if (printStat)
133 run_command("printenv production_mode", 0);
134
Sam Wu6f3d40e2023-04-22 01:10:27 +0800135 if (saveenv) {
136 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
137 run_command("update_env_part -p forUpgrade_robustOta "\
138 "forUpgrade_bootloaderIndex", 0);
139 else
140 run_command("saveenv", 0);
141 }
142
Bo Lv72d0e902023-01-02 14:27:34 +0000143
144 return CMD_RET_SUCCESS;
145}
146
147static void run_recovery_from_flash(void) {
148 env_set("dolby_status","0");
149 run_command("run init_display", 0);
150 run_command("run storeargs", 0);
151 run_command("get_rebootmode", 0);
152 run_command("if test ${reboot_mode} = quiescent; then "\
153 "setenv bootconfig ${bootconfig} androidboot.quiescent=1; fi;", 0);
154 run_command("if test ${reboot_mode} = recovery_quiescent; then "\
155 "setenv bootconfig ${bootconfig} androidboot.quiescent=1; fi;", 0);
156 run_command("run recovery_from_flash", 0);
157}
158
Bo Lv72d0e902023-01-02 14:27:34 +0000159int write_bootloader_back(const char* bootloaderindex, int dstindex) {
160 int iRet = 0;
161 int copy = 0;
162 int ret = -1;
163 unsigned char* buffer = NULL;
164 int capacity_boot = 0;
165
166 if (strcmp(bootloaderindex, "1") == 0) {
167 copy = 1;
168 } else if (strcmp(bootloaderindex, "2") == 0) {
169 copy = 2;
170 } else if (strcmp(bootloaderindex, "0") == 0) {
171 copy = 0;
172 }
173
174#ifdef CONFIG_MMC_MESON_GX
175 struct mmc *mmc = NULL;
176
177 if (store_get_type() == BOOT_EMMC)
178 mmc = find_mmc_device(1);
179
180 if (mmc)
181 capacity_boot = mmc->capacity_boot;
182#endif
183
184 printf("write_bootloader_back_capacity_boot: %x\n", capacity_boot);
185
186 buffer = (unsigned char *)malloc(capacity_boot);
187 if (!buffer)
188 {
189 printf("ERROR! fail to allocate memory ...\n");
190 goto exit;
191 }
192 memset(buffer, 0, capacity_boot);
193 iRet = store_boot_read("bootloader", copy, 0, buffer);
194 if (iRet) {
195 errorP("Fail read bootloader from rsv with sz\n");
196 goto exit;
197 }
198 iRet = store_boot_write("bootloader", dstindex, 0, buffer);
199 if (iRet) {
200 printf("Failed to write bootloader\n");
201 goto exit;
202 } else {
203 ret = 0;
204 }
205
206exit:
207 if (buffer)
208 {
209 free(buffer);
210 //buffer = NULL;
211 }
212 return ret;
213}
214
215//bootloader write protect
216static void bootloader_wp(void)
217{
218#ifdef CONFIG_MMC_MESON_GX
219 if (store_get_type() == BOOT_EMMC) {//emmc device
220 if (IS_FEAT_BOOT_VERIFY()) { //secure boot enable
221 if (BOOTLOADER_MODE_ADVANCE_INIT) { //new arch chip
222 env_set("bootloader_wp", "1");
223 }
224 }
225 }
226#endif
227}
228
229static void aml_recovery(void) {
230 char *mode = NULL;
231 char command[32];
232 char miscbuf[4096] = {0};
233
234 run_command("get_rebootmode", 0);
235
236 //get reboot_mode
237 mode = env_get("reboot_mode");
238 if (mode == NULL) {
239 wrnP("can not get reboot mode, so skip recovery check\n");
240 } else {
241 if ((!strcmp(mode, "factory_reset")) || (!strcmp(mode, "update"))) {
242 env_set("dolby_status","0");
243 }
244 }
245
246#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
247 int ret = 0;
248 extern int boot_info_open_partition(char *miscbuf);
249 ret = boot_info_open_partition(miscbuf);
250 if (ret != 0) {
251 wrnP("open misc partition failed, so skip recovery check");
252 return;
253 }
254#endif
255
256 //if run recovery, need disable dolby
257 memcpy(command, miscbuf, 32);
258 if (!memcmp(command, "boot-recovery", strlen("boot-recovery"))) {
259 env_set("dolby_status","0");
260 return;
261 }
262}
263
264void update_rollback(void)
265{
266 char *slot = NULL;
267 int ret = -1;
268 int gpt_flag = -1;
269
270#ifdef CONFIG_MMC_MESON_GX
271 struct mmc *mmc = NULL;
272
273 if (store_get_type() == BOOT_EMMC)
274 mmc = find_mmc_device(1);
275
276 if (mmc)
277 gpt_flag = aml_gpt_valid(mmc);
278#endif
279 if (gpt_flag == 0)
280 ret = 0;
281
282#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
283 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
284
285 //dis_user_flag = run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
286 if (*efuse_field.data == 1)
287 ret = 0;
288#endif//#ifdef CONFIG_EFUSE_OBJ_API
289
290 slot = env_get("slot-suffixes");
291 if (!slot) {
292 run_command("get_valid_slot", 0);
293 slot = env_get("slot-suffixes");
294 }
295 if (strcmp(slot, "0") == 0) {
296 if (ret != 0) {
297 wrnP("normal mode\n");
298 write_bootloader_back("2", 0);
299 env_set("expect_index", "0");
300 } else {
301 wrnP("gpt or disable user bootloader mode\n");
302 write_bootloader_back("2", 1);
303 env_set("expect_index", "1");
304 }
305 wrnP("back to slot b\n");
306 run_command("set_roll_flag 1", 0);
307 run_command("set_active_slot b", 0);
308 } else if (strcmp(slot, "1") == 0) {
309 if (ret != 0) {
310 wrnP("normal mode\n");
311 write_bootloader_back("1", 0);
312 env_set("expect_index", "0");
313 } else {
314 wrnP("gpt or disable user bootloader mode\n");
315 write_bootloader_back("2", 1);
316 env_set("expect_index", "1");
317 }
318 wrnP("back to slot a\n");
319 run_command("set_roll_flag 1", 0);
320 run_command("set_active_slot a", 0);
321 }
322 env_set("update_env", "1");
323 env_set("reboot_status", "reboot_next");
324}
325
Zhigang Yude5719e2024-03-08 09:14:23 +0000326static int write_bootloader(int i)
Bo Lv72d0e902023-01-02 14:27:34 +0000327{
328 unsigned char *buffer = NULL;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800329 int capacity_boot = 0x2000 * 512;
Zhigang Yu6852d932024-02-26 11:32:53 +0000330 int iret = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000331 char partname[32] = {0};
332 char *slot_name = NULL;
333
334#ifdef CONFIG_MMC_MESON_GX
335 struct mmc *mmc = NULL;
336
337 if (store_get_type() == BOOT_EMMC)
338 mmc = find_mmc_device(1);
339
340 if (mmc)
341 capacity_boot = mmc->capacity_boot;
342#endif
343 printf("capacity_boot: 0x%x\n", capacity_boot);
344 buffer = (unsigned char *)malloc(capacity_boot);
345 if (!buffer) {
346 printf("ERROR! fail to allocate memory ...\n");
347 return -1;
348 }
349 memset(buffer, 0, capacity_boot);
350
351 slot_name = env_get("active_slot");
352 if (slot_name && (strcmp(slot_name, "_a") == 0))
353 strcpy((char *)partname, "bootloader_a");
354 else if (slot_name && (strcmp(slot_name, "_b") == 0))
355 strcpy((char *)partname, "bootloader_b");
Zhigang Yude5719e2024-03-08 09:14:23 +0000356 else
357 strcpy((char *)partname, "bootloader_up");
Bo Lv72d0e902023-01-02 14:27:34 +0000358
Zhigang Yu6852d932024-02-26 11:32:53 +0000359 iret = store_logic_read(partname, 0, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
360 if (iret) {
Bo Lv72d0e902023-01-02 14:27:34 +0000361 errorP("Fail to read 0x%xB from part[%s] at offset 0\n",
362 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, partname);
Sam Wu6f3d40e2023-04-22 01:10:27 +0800363 free(buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000364 return -1;
365 }
366
Zhigang Yua69e3f92024-06-18 03:13:38 +0000367 iret = update_boot_hdr_4_s7d_reva(buffer, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, 0);
368 if (iret) {
369 printf("Failed to write s7d reva boot0\n");
370 free(buffer);
371 return -1;
372 }
373
Zhigang Yude5719e2024-03-08 09:14:23 +0000374 iret = store_boot_write("bootloader", i, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
Zhigang Yu6852d932024-02-26 11:32:53 +0000375 if (iret) {
Bo Lv72d0e902023-01-02 14:27:34 +0000376 printf("Failed to write boot0\n");
Sam Wu6f3d40e2023-04-22 01:10:27 +0800377 free(buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000378 return -1;
379 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800380
381 free(buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000382 return 0;
383}
384
385/**
386 *set merge status
387*/
388int set_mergestatus_cancel(struct misc_virtual_ab_message *message)
389{
390 char *partition = "misc";
391 char vab_buf[1024] = {0};
392
393 if (store_read((const char *)partition,
394 SYSTEM_SPACE_OFFSET_IN_MISC, 1024, (unsigned char *)vab_buf) < 0) {
395 printf("failed to store read %s.\n", partition);
396 return -1;
397 }
398
399 memcpy(message, vab_buf, sizeof(struct misc_virtual_ab_message));
400 printf("message.merge_status: %d\n", message->merge_status);
401 if (message->merge_status == SNAPSHOTTED || message->merge_status == MERGING) {
402 message->merge_status = CANCELLED;
403 printf("set message.merge_status CANCELLED\n");
404 }
405 store_write((const char *)partition, SYSTEM_SPACE_OFFSET_IN_MISC, 1024, (unsigned char *)vab_buf);
406 return 0;
407}
408
hao.qi4c4dc762024-03-11 10:38:23 +0800409// according to the value of the board,
410// reset the product to set the serial
411// to distinguish different products.
412void set_product(void)
413{
414 char *board = env_get("board");
415 char *str = NULL;
416 char *dup_str = NULL;
417
418 str = strstr(board, "_");
hao.qi952f6d92024-06-03 20:56:42 +0800419 if (!str) {
420 env_set("product", board);
421 return;
422 }
hao.qi4c4dc762024-03-11 10:38:23 +0800423 dup_str = strdup(str);
424 if (!(strstr(dup_str, "_")))
425 env_set("product", str + 1);
426 else
427 env_set("product", strtok(str, "_"));
428 free(dup_str);
hao.qi952f6d92024-06-03 20:56:42 +0800429 return;
hao.qi4c4dc762024-03-11 10:38:23 +0800430}
431
Zhigang Yude5719e2024-03-08 09:14:23 +0000432void fastboot_step_check(char *rebootmode, int gpt_flag)
433{
434 char *bootloaderindex = NULL;
435 struct mmc *mmc = NULL;
436
437 if (store_get_type() == BOOT_EMMC)
438 mmc = find_mmc_device(1);
439
440 //get bootloader index
441 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
442 if (!bootloaderindex) {
443 wrnP("can not get bootloader index, so skip fastboot step check\n");
444 return;
445 }
446
447 char *fastboot_step = env_get("fastboot_step");
448
449 if (mmc && fastboot_step && (strcmp(fastboot_step, "1") == 0)) {
450 printf("reboot to new bootloader burned by fastboot\n");
451 env_set("update_env", "1");
452 env_set("fastboot_step", "2");
453 run_command("saveenv", 0);
454 if (rebootmode && (strcmp(rebootmode, "fastboot") == 0))
455 run_command("reboot next,bootloader", 0);
456 else
457 run_command("reboot next", 0);
458 }
459 if (mmc && fastboot_step && (strcmp(fastboot_step, "2") == 0)) {
460 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
461
462 if (dev_desc && ((gpt_flag == 1 && !strcmp(bootloaderindex, "1")) ||
463 (gpt_flag == 0 && !strcmp(bootloaderindex, "0")))) {
464 printf("new bootloader error, please fastboot to another one\n");
465 env_set("fastboot_step", "0");
466 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
467 run_command("update_env_part -p fastboot_step;", 0);
468 else
469 run_command("defenv_reserve;setenv fastboot_step 0;saveenv;", 0);
470 cli_init();
471 cli_loop();
472 }
473 }
474}
475
Xindong Xu15e83fa2024-03-15 08:56:00 +0800476static int update_gpt(int flag)
477{
478 int ret = 0;
479#ifdef CONFIG_MMC_MESON_GX
480 unsigned char *buffer = NULL;
481 int capacity_boot = 0x2000 * 512;
482 int iRet = 0;
483 struct mmc *mmc = NULL;
484 struct blk_desc *dev_desc;
485
486 if (store_get_type() == BOOT_EMMC)
487 mmc = find_mmc_device(1);
488
489 if (mmc)
490 capacity_boot = mmc->capacity_boot;
491
492 printf("capacity_boot: 0x%x\n", capacity_boot);
493 buffer = (unsigned char *)malloc(capacity_boot);
494 if (!buffer) {
495 printf("ERROR! fail to allocate memory ...\n");
496 return -1;
497 }
498 memset(buffer, 0, capacity_boot);
499
500 if (flag == 0) {
501 iRet = store_boot_read("bootloader", 1, 0, buffer);
502 if (iRet) {
503 printf("Failed to read boot0\n");
504 ret = -1;
505 goto exit;
506 }
507 } else if (flag == 1 || flag == 2) {
508 iRet = store_boot_read("bootloader", 0, 0, buffer);
509 if (iRet) {
510 printf("Failed to read bootloader\n");
511 ret = -1;
512 goto exit;
513 }
514 } else if (flag == 3) {
515 printf("null ab mode\n");
516 iRet = store_logic_read("bootloader_up", 0,
517 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
518 if (iRet) {
519 printf("Fail to read 0x%xB from bootloader_up\n",
520 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET);
521 ret = -1;
522 goto exit;
523 }
524 }
525
526 if (mmc) {
527 printf("try to read gpt data from bootloader.img\n");
528 int erase_flag = 0;
529
530 dev_desc = blk_get_dev("mmc", 1);
531 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
532 printf("invalid mmc device\n");
533 ret = -1;
534 goto exit;
535 }
536
537 if (is_valid_gpt_buf(dev_desc, buffer + 0x3DFE00)) {
538 printf("printf normal bootloader.img, no gpt partition table\n");
539 ret = -1;
540 goto exit;
541 } else {
542 erase_flag = check_gpt_change(dev_desc, buffer + 0x3DFE00);
543
544 if (erase_flag == 4 && has_boot_slot == 0) {
545 printf("null ab critical partition change, refused to upgrade\n");
546 ret = -1;
547 goto exit;
548 } else if (has_boot_slot == 1 && (erase_flag == 3 || erase_flag == 4)) {
549 printf("Important partition changes, refused to upgrade\n");
550 ret = 1;
551 goto exit;
552 } else if (erase_flag == 0) {
553 printf("partition doesn't change, needn't update\n");
554 ret = -1;
555 goto exit;
556 }
557
558 if (flag == 1 || flag == 2) {
559 printf("update from dts to gpt, erase first\n");
560 erase_gpt_part_table(dev_desc);
561 }
562
563 if (flag == 2) {
564#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
565 env_set("dts_to_gpt", "1");
566 run_command("update_env_part -p dts_to_gpt;", 0);
567#else
568 run_command("defenv_reserve;setenv dts_to_gpt 1;saveenv;", 0);
569#endif
570 }
571
572 if (write_mbr_and_gpt_partitions(dev_desc, buffer + 0x3DFE00)) {
573 printf("%s: writing GPT partitions failed\n", __func__);
574 ret = 1;
575 goto exit;
576 }
577
578 if (mmc_device_init(mmc) != 0) {
579 printf(" update gpt partition table fail\n");
580 ret = 2;
581 goto exit;
582 }
583 printf("%s: writing GPT partitions ok\n", __func__);
584 }
585 }
586
587 if (has_boot_slot == 1 && (flag == 1 || flag == 2)) {
588 printf("update from dts to gpt, backup old bootloader\n");
589 char *slot = NULL;
590
591 slot = env_get("slot-suffixes");
592 if (!slot) {
593 run_command("get_valid_slot", 0);
594 slot = env_get("slot-suffixes");
595 }
596 if (strcmp(slot, "0") == 0) {
597 printf("active is a, b is old, don't need backup\n");
598 } else if (strcmp(slot, "1") == 0) {
599 printf("active is b, a is old, backup boot0 to boot1\n");
600 iRet = write_bootloader_back("1", 2);
601 if (iRet != 0) {
602 printf("Failed to write boot1\n");
603 ret = 3;
604 goto exit;
605 }
606 }
607 iRet = store_boot_write("bootloader", 1, 0, buffer);
608 if (iRet) {
609 printf("Failed to write boot0\n");
610 ret = 4;
611 goto exit;
612 }
613 }
614
615exit:
616 if (buffer)
617 free(buffer);
618
619 if (mmc)
620 run_command("mmc dev 1 0;", 0);
621
622 if (mmc && ret > 0) {
623 if (ret == 1 || ret == 2 || ret == 3) {
624 printf("rollback\n");
625 update_rollback();
626 } else if (ret == 4) {
627 printf("write back boot0, rollback\n");
628 write_bootloader_back("2", 1);
629 update_rollback();
630 }
631 }
632#endif
633 return ret;
634}
635
Zhigang Yude5719e2024-03-08 09:14:23 +0000636int recovery_update(void)
637{
638 if (IS_ENABLED(CONFIG_MMC_MESON_GX)) {
639 char bufcmd[64];
640 unsigned long long size = 0;
641 char *recovery_need_update = NULL;
642 struct partitions *partition = NULL;
643 //"ANDROID!"
644 const unsigned char imghead[] = { 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x21 };
645
646 if (store_get_type() != BOOT_EMMC)
647 return 0;
648
649 //check recoverybak partition exist
650 partition = find_mmc_partition_by_name("recoverybak");
651 if (!partition) {
652 printf("can not find recoverybak, skip\n");
653 return 0;
654 }
655
656 //check if need update recovery from recoverybak
657 recovery_need_update = env_get("recovery_need_update");
658 if (!recovery_need_update || strcmp(recovery_need_update, "1"))
659 return 0;
660
661 //read recoverybak header data for check
662 sprintf(bufcmd, "store read $loadaddr recoverybak 0 0x%x", 16);
663 run_command(bufcmd, 0);
664
665 unsigned char *loadaddr = NULL;
666
667 loadaddr = (unsigned char *)simple_strtoul(env_get("loadaddr"), NULL, 16);
668
669 //check recoverybak head is start "ANDROID!"
670 if (memcmp((void *)imghead, loadaddr, 8)) {
671 printf("not valid recovery image, skip update recovery\n");
672 return 0;
673 }
674
675 //write recoverybak data to recovery
676 while (size < partition->size) {
677 unsigned long long write_size = 0;
678 unsigned long long left_size = partition->size - size;
679
680 if (left_size > 10 * MIB_SIZE)
681 write_size = 10 * MIB_SIZE;
682 else
683 write_size = partition->size - size;
684
685 sprintf(bufcmd, "store read $loadaddr recoverybak 0x%llx 0x%llx",
686 size, write_size);
687 run_command(bufcmd, 0);
688 sprintf(bufcmd, "store write $loadaddr recovery 0x%llx 0x%llx",
689 size, write_size);
690 run_command(bufcmd, 0);
691 size += write_size;
692 }
693
694 //clean recovery_need_update to 0
695 env_set("recovery_need_update", "0");
696 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
697 run_command("update_env_part -p recovery_need_update;", 0);
698 else
699 run_command("saveenv", 0);
700 }
701 return 0;
702}
703
704//add non ab recovery update flow here
705int non_ab_update(char *rebootmode)
706{
Bo Lv72d0e902023-01-02 14:27:34 +0000707 int match_flag = 0;
708 char *rebootstatus = NULL;
709 char *checkresult = NULL;
710 char *bootloaderindex = NULL;
711 char *expect_index = NULL;
712 char *robustota = NULL;
Bo Lv72d0e902023-01-02 14:27:34 +0000713
714 char *write_boot = env_get("write_boot");
715
Zhigang Yude5719e2024-03-08 09:14:23 +0000716 if (write_boot && (!strcmp(write_boot, "1"))) {
717 printf("non ab for kernel 5.15 update bootloader\n");
718 write_bootloader(1);
719 write_bootloader(2);
720 env_set("write_boot", "0");
721 env_set("upgrade_step", "1");
722 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800723 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
724 run_command("reboot quiescent", 0);
725 else
726 run_command("reboot", 0);
Zhigang Yude5719e2024-03-08 09:14:23 +0000727 }
728
729 recovery_update();
730
731 //check_result init
732 checkresult = env_get("check_result");
733 if (!checkresult)
734 env_set("check_result", "succ");
735
736 //reboot_status init
737 rebootstatus = env_get("reboot_status");
738 if (!rebootstatus) {
739 env_set("reboot_status", "reboot_init");
740 rebootstatus = env_get("reboot_status");
741 }
742
743 if (!rebootstatus) {
744 printf("rebootstatus is NULL, skip check\n");
745 return -1;
746 }
747
748 //check reboot_end
749 if (!strcmp(rebootstatus, "reboot_end")) {
750 env_set("reboot_status", "reboot_init");
751 run_command("saveenv", 0);
752 }
753
754 //get forUpgrade_robustOta and check if support robustota
755 robustota = env_get("forUpgrade_robustOta");
756 if (!robustota || !strcmp(robustota, "false"))
757 return -1;
758
759 //no secure check need
760 if (!strcmp(rebootstatus, "reboot_init")) {
761 printf("rebootstatus is reboot_init, skip check\n");
762 return -1;
763 }
764
765 //get bootloader index
766 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
767 if (!bootloaderindex) {
768 wrnP("can not get bootloader index, so skip secure check\n");
769 return -1;
770 }
771
772 //get expect index
773 expect_index = env_get("expect_index");
774 if (!expect_index) {
775 wrnP("can not get expect index, so skip secure check\n");
776 return -1;
777 }
778
779 wrnP("expect_index is : %s\n", expect_index);
780
781 match_flag = strcmp(bootloaderindex, expect_index);
782
783 //ignore reboot next check if power off during reboot next to finish
784 if (rebootmode && (strcmp(rebootmode, "cold_boot") == 0)) {
785 if (!strcmp(rebootstatus, "reboot_finish"))
786 match_flag = 0;
787 }
788
789 if (!strcmp(rebootstatus, "reboot_next")) {
790 env_set("reboot_status", "reboot_finish");
791 run_command("saveenv", 0);
792 run_command("get_rebootmode", 0);
793 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
794 run_command("reboot next,quiescent", 0);
795 else
796 run_command("reboot next", 0);
797 } else if (!strcmp(rebootstatus, "reboot_finish")) {
798 wrnP("--secure check reboot_finish---\n");
799 env_set("reboot_status", "reboot_end");
800 run_command("saveenv", 0);
801 if (match_flag == 0) {
802 wrnP("reboot next succ, bootloader secure check pass......\n");
803 } else {
804 //bootloader check failed, run recovery show error
805 wrnP("reboot next fail, bootloader secure check fail(curr:%s, expect:%s)\n",
806 bootloaderindex, expect_index);
807 env_set("check_result", "bootloader_fail");
808 run_command("saveenv", 0);
809 }
810 run_recovery_from_flash();
811 return 0;
812 } else {
813 env_set("check_result", "succ");
814 }
815 return 0;
816}
817
818//add ab update and ab rollback flow here
819int ab_update_rollback(char *rebootmode, int gpt_flag)
820{
821 int match_flag = 0;
822 char *rebootstatus = NULL;
823 char *bootloaderindex = NULL;
824 char *expect_index = NULL;
825
826 //update bootloader_a/b/up to boot0
827 char *write_boot = env_get("write_boot");
828
829 if (write_boot && !strcmp(write_boot, "1")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000830 printf("need to write boot0\n");
Zhigang Yude5719e2024-03-08 09:14:23 +0000831 if (write_bootloader(1)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000832 printf("write boot0 fail, need to rollback!\n");
833 update_rollback();
834 } else {
Xindong Xu15e83fa2024-03-15 08:56:00 +0800835 update_gpt(0);
Bo Lv72d0e902023-01-02 14:27:34 +0000836 printf("write boot0 success, need to reset!\n");
837 }
838
839 env_set("write_boot", "0");
840 env_set("reboot_status", "reboot_next");
841 env_set("expect_index", "1");
842 env_set("update_env", "1");
843 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800844 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
845 run_command("reboot quiescent", 0);
846 else
847 run_command("reboot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000848 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000849
850 //check rescueparty and rollback
Bo Lv72d0e902023-01-02 14:27:34 +0000851 if (rebootmode && (strcmp(rebootmode, "rescueparty") == 0)) {
852 printf("rebootmode is rescueparty, need rollback\n");
853 char *slot;
854
Bo Lv72d0e902023-01-02 14:27:34 +0000855#ifdef CONFIG_FASTBOOT
856 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000857 set_mergestatus_cancel(&message);
858#endif
859
860 slot = env_get("slot-suffixes");
861 if (!slot) {
862 run_command("get_valid_slot", 0);
863 slot = env_get("slot-suffixes");
864 }
865 if (strcmp(slot, "0") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000866 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000867 wrnP("normal mode\n");
868 write_bootloader_back("2", 0);
869 env_set("expect_index", "0");
870 } else {
871 wrnP("gpt or disable user bootloader mode\n");
872 write_bootloader_back("2", 1);
873 env_set("expect_index", "1");
874 }
875 wrnP("back to slot b\n");
876 run_command("set_roll_flag 1", 0);
877 run_command("set_active_slot b", 0);
878 } else if (strcmp(slot, "1") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000879 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000880 wrnP("normal mode\n");
881 write_bootloader_back("1", 0);
882 env_set("expect_index", "0");
883 } else {
884 wrnP("gpt or disable user bootloader mode\n");
885 write_bootloader_back("2", 1);
886 env_set("expect_index", "1");
887 }
888 wrnP("back to slot a\n");
889 run_command("set_roll_flag 1", 0);
890 run_command("set_active_slot a", 0);
891 }
892
893 env_set("update_env", "1");
894 env_set("reboot_status", "reboot_next");
895 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800896 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
897 run_command("reboot quiescent", 0);
898 else
899 run_command("reboot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000900 }
901
Bo Lv72d0e902023-01-02 14:27:34 +0000902 //get bootloader index
903 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
904 if (bootloaderindex == NULL) {
905 wrnP("can not get bootloader index, so skip secure check\n");
906 return -1;
907 }
Xindong Xu22e8daf2024-03-12 18:08:41 +0800908
Bo Lv72d0e902023-01-02 14:27:34 +0000909 //get expect index
910 expect_index = env_get("expect_index");
911 if (expect_index == NULL) {
912 wrnP("can not get expect index, so skip secure check\n");
913 return -1;
914 }
915
916 wrnP("expect_index is : %s\n", expect_index);
917
918 match_flag = strcmp(bootloaderindex, expect_index);
919
Zhigang Yude5719e2024-03-08 09:14:23 +0000920 rebootstatus = env_get("reboot_status");
Bo Lv72d0e902023-01-02 14:27:34 +0000921
Zhigang Yude5719e2024-03-08 09:14:23 +0000922 //if reboot next need check bootloader rollback
923 if (rebootstatus && !strcmp(rebootstatus, "reboot_next")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000924 wrnP("--secure check reboot_next---\n");
925 //bootloader index, expect == current, no need reboot next
Zhigang Yude5719e2024-03-08 09:14:23 +0000926 if (match_flag != 0) {
927 wrnP("bootloader wrong, start rollback\n");
928 if (gpt_flag == 1) {
929 wrnP("gpt or disable user bootloader mode, write boot1 to boot0\n");
930 write_bootloader_back("2", 1);
Bo Lv72d0e902023-01-02 14:27:34 +0000931#ifdef CONFIG_FASTBOOT
Zhigang Yude5719e2024-03-08 09:14:23 +0000932 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000933
Zhigang Yude5719e2024-03-08 09:14:23 +0000934 set_mergestatus_cancel(&message);
Bo Lv72d0e902023-01-02 14:27:34 +0000935#endif
Zhigang Yude5719e2024-03-08 09:14:23 +0000936 char *slot;
Bo Lv72d0e902023-01-02 14:27:34 +0000937
Zhigang Yude5719e2024-03-08 09:14:23 +0000938 slot = env_get("slot-suffixes");
939 if (!slot) {
940 run_command("get_valid_slot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000941 slot = env_get("slot-suffixes");
Bo Lv72d0e902023-01-02 14:27:34 +0000942 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000943 if (strcmp(slot, "0") == 0) {
944 wrnP("back to slot b\n");
945 run_command("set_roll_flag 1", 0);
946 run_command("set_active_slot b", 0);
947 } else if (strcmp(slot, "1") == 0) {
948 wrnP("back to slot a\n");
949 run_command("set_roll_flag 1", 0);
950 run_command("set_active_slot a", 0);
951 }
952 env_set("expect_index", "1");
Bo Lv72d0e902023-01-02 14:27:34 +0000953 } else {
Zhigang Yude5719e2024-03-08 09:14:23 +0000954 write_bootloader_back(bootloaderindex, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000955#ifdef CONFIG_FASTBOOT
956 struct misc_virtual_ab_message message;
957 set_mergestatus_cancel(&message);
958#endif
959 if (strcmp(bootloaderindex, "1") == 0) {
960 wrnP("back to slot a\n");
961 run_command("set_roll_flag 1", 0);
962 run_command("set_active_slot a", 0);
963 } else if (strcmp(bootloaderindex, "2") == 0) {
964 wrnP("back to slot b\n");
965 run_command("set_roll_flag 1", 0);
966 run_command("set_active_slot b", 0);
967 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000968 env_set("expect_index", "0");
Bo Lv72d0e902023-01-02 14:27:34 +0000969 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000970
971 env_set("update_env", "1");
972 env_set("reboot_status", "reboot_next");
Bo Lv72d0e902023-01-02 14:27:34 +0000973 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800974 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
975 run_command("reboot quiescent", 0);
976 else
977 run_command("reboot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000978 return 0;
hao.qi5fa394b2024-07-18 14:54:45 +0800979 }else {
980 wrnP("current index is expect, no need reboot next, set reboot_status reboot_init\n");
981 env_set("reboot_status", "reboot_init");
982#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
983 run_command("update_env_part -p reboot_status;", 0);
984#else
985 run_command("saveenv", 0);
986#endif
Zhigang Yude5719e2024-03-08 09:14:23 +0000987 }
Bo Lv72d0e902023-01-02 14:27:34 +0000988 }
989
990 return 0;
991}
992
Zhigang Yude5719e2024-03-08 09:14:23 +0000993static int do_secureboot_check(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
994{
995 char *rebootmode = NULL;
996 int gpt_flag = 0;
997 int ret = -1;
998
999 // set product first to set serial.
1000 set_product();
1001
1002#ifdef CONFIG_MMC_MESON_GX
1003 struct mmc *mmc = NULL;
1004 //int capacity_boot = 0;
1005
1006 if (store_get_type() == BOOT_EMMC) {
1007 mmc = find_mmc_device(1);
1008 if (mmc)
1009 ret = aml_gpt_valid(mmc);
1010 }
1011#endif
1012
1013 //check is gpt mode
1014 if (ret == 0)
1015 gpt_flag = 1;
1016
1017 //unsupport update dt in boothal, update dt in uboot
1018 run_command("update_dt;", 0);
1019
1020 bootloader_wp();
1021
1022 //set default env before check
1023 env_set("recovery_mode", "false");
1024
1025 //if recovery mode, need disable dv, if factoryreset, need default uboot env
1026 aml_recovery();
1027
1028#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
1029 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
1030
1031 if (*efuse_field.data == 1) {
1032 wrnP("efuse_field.data == 1\n");
1033 env_set("nocs_mode", "true");
1034 gpt_flag = 1;
1035 } else {
1036 wrnP("efuse_field.data != 1\n");
1037 env_set("nocs_mode", "false");
1038 }
1039#endif//#ifdef CONFIG_EFUSE_OBJ_API
1040
1041
1042 run_command("get_rebootmode", 0);
1043 rebootmode = env_get("reboot_mode");
1044 if (!rebootmode) {
1045 wrnP("can not get reboot mode, so skip secure check\n");
1046 return -1;
1047 }
1048 printf("rebootmode is %s\n", rebootmode);
1049
1050 //get boot status
1051 run_command("amlbootsta -p -s", 0);
1052
1053 if (IS_ENABLED(CONFIG_MMC_MESON_GX))
1054 fastboot_step_check(rebootmode, gpt_flag);
1055
1056 if (has_boot_slot == 1)
1057 ab_update_rollback(rebootmode, gpt_flag);
1058 else
1059 non_ab_update(rebootmode);
1060
1061 return 0;
1062}
1063
1064
1065static int do_update_uboot_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1066{
1067 const int write_boot = env_get_ulong("write_boot", 10, 0);
1068 const int update_dts_gpt = env_get_ulong("update_dts_gpt", 10, 0);
1069
1070 //skip update env if need update bootloader
1071 if (write_boot || update_dts_gpt) {
1072 run_command("echo write_boot ${write_boot}, update_dts_gpt ${update_dts_gpt}", 0);
1073 return 0;
1074 }
1075
1076 //default uboot env need before anyone use it
1077 //after factory reset
1078 if (env_get("default_env")) {
1079 printf("factory reset, need default all uboot env.\n");
1080 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1081 }
1082
1083 //after ab update
1084 char *update_env = env_get("update_env");
1085
1086 if (update_env && (strcmp(update_env, "1") == 0)) {
1087 printf("ab mode, default all uboot env\n");
1088 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1089 }
1090
1091 //after recovery update
1092 char *upgrade_step = env_get("upgrade_step");
1093
1094 if (upgrade_step && (strcmp(upgrade_step, "1") == 0)) {
1095 printf("after recovery update, need update uboot env\n");
1096 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1097 }
1098
1099 return 0;
1100}
Bo Lv72d0e902023-01-02 14:27:34 +00001101
1102U_BOOT_CMD_COMPLETE(
1103 amlbootsta, 3, 0, do_get_bootloader_status,
1104 "get bootloader status in env",
1105 "[-p] print bootloader status\n"
1106 "[-s] saveenv after generate bootloader status\n",
1107 var_complete
1108);
1109
1110U_BOOT_CMD_COMPLETE(
1111 amlsecurecheck, 1, 0, do_secureboot_check,
1112 "try bootloader/dtb/recovery secure check",
1113 ""
1114 "",
1115 var_complete
1116);
1117
Zhigang Yude5719e2024-03-08 09:14:23 +00001118U_BOOT_CMD(aml_update_env, 1, 0, do_update_uboot_env,
1119 "aml_update_env",
1120 "\nThis command will update uboot env\n"
1121 "So you can execute command: aml_update_env"
1122);
1123
Bo Lv72d0e902023-01-02 14:27:34 +00001124