blob: e89d16c79d050373ea2817585885ea755347c5d4 [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
yihui wu7935bce2024-12-17 01:17:08 +0800367#ifdef CONFIG_MESON_S7D
Dongjin Kimddfb7182025-02-24 16:50:49 +0900368#ifdef CONFIG_AML_V3_FACTORY_BURN
Zhigang Yua69e3f92024-06-18 03:13:38 +0000369 iret = update_boot_hdr_4_s7d_reva(buffer, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, 0);
370 if (iret) {
371 printf("Failed to write s7d reva boot0\n");
372 free(buffer);
373 return -1;
374 }
Dongjin Kimddfb7182025-02-24 16:50:49 +0900375#endif
yihui wu7935bce2024-12-17 01:17:08 +0800376#endif//#ifdef CONFIG_MESON_S7D
Zhigang Yua69e3f92024-06-18 03:13:38 +0000377
Zhigang Yude5719e2024-03-08 09:14:23 +0000378 iret = store_boot_write("bootloader", i, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
Zhigang Yu6852d932024-02-26 11:32:53 +0000379 if (iret) {
Bo Lv72d0e902023-01-02 14:27:34 +0000380 printf("Failed to write boot0\n");
Sam Wu6f3d40e2023-04-22 01:10:27 +0800381 free(buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000382 return -1;
383 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800384
385 free(buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000386 return 0;
387}
388
389/**
390 *set merge status
391*/
392int set_mergestatus_cancel(struct misc_virtual_ab_message *message)
393{
394 char *partition = "misc";
395 char vab_buf[1024] = {0};
396
397 if (store_read((const char *)partition,
398 SYSTEM_SPACE_OFFSET_IN_MISC, 1024, (unsigned char *)vab_buf) < 0) {
399 printf("failed to store read %s.\n", partition);
400 return -1;
401 }
402
403 memcpy(message, vab_buf, sizeof(struct misc_virtual_ab_message));
404 printf("message.merge_status: %d\n", message->merge_status);
405 if (message->merge_status == SNAPSHOTTED || message->merge_status == MERGING) {
406 message->merge_status = CANCELLED;
407 printf("set message.merge_status CANCELLED\n");
408 }
409 store_write((const char *)partition, SYSTEM_SPACE_OFFSET_IN_MISC, 1024, (unsigned char *)vab_buf);
410 return 0;
411}
412
hao.qi4c4dc762024-03-11 10:38:23 +0800413// according to the value of the board,
414// reset the product to set the serial
415// to distinguish different products.
416void set_product(void)
417{
418 char *board = env_get("board");
419 char *str = NULL;
420 char *dup_str = NULL;
421
422 str = strstr(board, "_");
hao.qi952f6d92024-06-03 20:56:42 +0800423 if (!str) {
424 env_set("product", board);
425 return;
426 }
hao.qi4c4dc762024-03-11 10:38:23 +0800427 dup_str = strdup(str);
428 if (!(strstr(dup_str, "_")))
429 env_set("product", str + 1);
430 else
431 env_set("product", strtok(str, "_"));
432 free(dup_str);
hao.qi952f6d92024-06-03 20:56:42 +0800433 return;
hao.qi4c4dc762024-03-11 10:38:23 +0800434}
435
Zhigang Yude5719e2024-03-08 09:14:23 +0000436void fastboot_step_check(char *rebootmode, int gpt_flag)
437{
438 char *bootloaderindex = NULL;
439 struct mmc *mmc = NULL;
440
441 if (store_get_type() == BOOT_EMMC)
442 mmc = find_mmc_device(1);
443
444 //get bootloader index
445 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
446 if (!bootloaderindex) {
447 wrnP("can not get bootloader index, so skip fastboot step check\n");
448 return;
449 }
450
451 char *fastboot_step = env_get("fastboot_step");
452
453 if (mmc && fastboot_step && (strcmp(fastboot_step, "1") == 0)) {
454 printf("reboot to new bootloader burned by fastboot\n");
455 env_set("update_env", "1");
456 env_set("fastboot_step", "2");
457 run_command("saveenv", 0);
458 if (rebootmode && (strcmp(rebootmode, "fastboot") == 0))
459 run_command("reboot next,bootloader", 0);
460 else
461 run_command("reboot next", 0);
462 }
463 if (mmc && fastboot_step && (strcmp(fastboot_step, "2") == 0)) {
464 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
465
466 if (dev_desc && ((gpt_flag == 1 && !strcmp(bootloaderindex, "1")) ||
467 (gpt_flag == 0 && !strcmp(bootloaderindex, "0")))) {
468 printf("new bootloader error, please fastboot to another one\n");
469 env_set("fastboot_step", "0");
470 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
471 run_command("update_env_part -p fastboot_step;", 0);
472 else
473 run_command("defenv_reserve;setenv fastboot_step 0;saveenv;", 0);
474 cli_init();
475 cli_loop();
476 }
477 }
478}
479
Xindong Xu15e83fa2024-03-15 08:56:00 +0800480static int update_gpt(int flag)
481{
482 int ret = 0;
483#ifdef CONFIG_MMC_MESON_GX
484 unsigned char *buffer = NULL;
485 int capacity_boot = 0x2000 * 512;
486 int iRet = 0;
487 struct mmc *mmc = NULL;
488 struct blk_desc *dev_desc;
489
490 if (store_get_type() == BOOT_EMMC)
491 mmc = find_mmc_device(1);
492
493 if (mmc)
494 capacity_boot = mmc->capacity_boot;
495
496 printf("capacity_boot: 0x%x\n", capacity_boot);
497 buffer = (unsigned char *)malloc(capacity_boot);
498 if (!buffer) {
499 printf("ERROR! fail to allocate memory ...\n");
500 return -1;
501 }
502 memset(buffer, 0, capacity_boot);
503
504 if (flag == 0) {
505 iRet = store_boot_read("bootloader", 1, 0, buffer);
506 if (iRet) {
507 printf("Failed to read boot0\n");
508 ret = -1;
509 goto exit;
510 }
511 } else if (flag == 1 || flag == 2) {
512 iRet = store_boot_read("bootloader", 0, 0, buffer);
513 if (iRet) {
514 printf("Failed to read bootloader\n");
515 ret = -1;
516 goto exit;
517 }
518 } else if (flag == 3) {
519 printf("null ab mode\n");
520 iRet = store_logic_read("bootloader_up", 0,
521 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
522 if (iRet) {
523 printf("Fail to read 0x%xB from bootloader_up\n",
524 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET);
525 ret = -1;
526 goto exit;
527 }
528 }
529
530 if (mmc) {
531 printf("try to read gpt data from bootloader.img\n");
532 int erase_flag = 0;
533
534 dev_desc = blk_get_dev("mmc", 1);
535 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
536 printf("invalid mmc device\n");
537 ret = -1;
538 goto exit;
539 }
540
541 if (is_valid_gpt_buf(dev_desc, buffer + 0x3DFE00)) {
542 printf("printf normal bootloader.img, no gpt partition table\n");
543 ret = -1;
544 goto exit;
545 } else {
546 erase_flag = check_gpt_change(dev_desc, buffer + 0x3DFE00);
547
548 if (erase_flag == 4 && has_boot_slot == 0) {
549 printf("null ab critical partition change, refused to upgrade\n");
550 ret = -1;
551 goto exit;
552 } else if (has_boot_slot == 1 && (erase_flag == 3 || erase_flag == 4)) {
553 printf("Important partition changes, refused to upgrade\n");
554 ret = 1;
555 goto exit;
556 } else if (erase_flag == 0) {
557 printf("partition doesn't change, needn't update\n");
558 ret = -1;
559 goto exit;
560 }
561
562 if (flag == 1 || flag == 2) {
563 printf("update from dts to gpt, erase first\n");
564 erase_gpt_part_table(dev_desc);
565 }
566
567 if (flag == 2) {
568#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
569 env_set("dts_to_gpt", "1");
570 run_command("update_env_part -p dts_to_gpt;", 0);
571#else
572 run_command("defenv_reserve;setenv dts_to_gpt 1;saveenv;", 0);
573#endif
574 }
575
576 if (write_mbr_and_gpt_partitions(dev_desc, buffer + 0x3DFE00)) {
577 printf("%s: writing GPT partitions failed\n", __func__);
578 ret = 1;
579 goto exit;
580 }
581
582 if (mmc_device_init(mmc) != 0) {
583 printf(" update gpt partition table fail\n");
584 ret = 2;
585 goto exit;
586 }
587 printf("%s: writing GPT partitions ok\n", __func__);
588 }
589 }
590
591 if (has_boot_slot == 1 && (flag == 1 || flag == 2)) {
592 printf("update from dts to gpt, backup old bootloader\n");
593 char *slot = NULL;
594
595 slot = env_get("slot-suffixes");
596 if (!slot) {
597 run_command("get_valid_slot", 0);
598 slot = env_get("slot-suffixes");
599 }
600 if (strcmp(slot, "0") == 0) {
601 printf("active is a, b is old, don't need backup\n");
602 } else if (strcmp(slot, "1") == 0) {
603 printf("active is b, a is old, backup boot0 to boot1\n");
604 iRet = write_bootloader_back("1", 2);
605 if (iRet != 0) {
606 printf("Failed to write boot1\n");
607 ret = 3;
608 goto exit;
609 }
610 }
611 iRet = store_boot_write("bootloader", 1, 0, buffer);
612 if (iRet) {
613 printf("Failed to write boot0\n");
614 ret = 4;
615 goto exit;
616 }
617 }
618
619exit:
620 if (buffer)
621 free(buffer);
622
623 if (mmc)
624 run_command("mmc dev 1 0;", 0);
625
626 if (mmc && ret > 0) {
627 if (ret == 1 || ret == 2 || ret == 3) {
628 printf("rollback\n");
629 update_rollback();
630 } else if (ret == 4) {
631 printf("write back boot0, rollback\n");
632 write_bootloader_back("2", 1);
633 update_rollback();
634 }
635 }
636#endif
637 return ret;
638}
639
Zhigang Yude5719e2024-03-08 09:14:23 +0000640int recovery_update(void)
641{
642 if (IS_ENABLED(CONFIG_MMC_MESON_GX)) {
643 char bufcmd[64];
644 unsigned long long size = 0;
645 char *recovery_need_update = NULL;
646 struct partitions *partition = NULL;
647 //"ANDROID!"
648 const unsigned char imghead[] = { 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x21 };
649
650 if (store_get_type() != BOOT_EMMC)
651 return 0;
652
653 //check recoverybak partition exist
654 partition = find_mmc_partition_by_name("recoverybak");
655 if (!partition) {
656 printf("can not find recoverybak, skip\n");
657 return 0;
658 }
659
660 //check if need update recovery from recoverybak
661 recovery_need_update = env_get("recovery_need_update");
662 if (!recovery_need_update || strcmp(recovery_need_update, "1"))
663 return 0;
664
665 //read recoverybak header data for check
666 sprintf(bufcmd, "store read $loadaddr recoverybak 0 0x%x", 16);
667 run_command(bufcmd, 0);
668
669 unsigned char *loadaddr = NULL;
670
671 loadaddr = (unsigned char *)simple_strtoul(env_get("loadaddr"), NULL, 16);
672
673 //check recoverybak head is start "ANDROID!"
674 if (memcmp((void *)imghead, loadaddr, 8)) {
675 printf("not valid recovery image, skip update recovery\n");
676 return 0;
677 }
678
679 //write recoverybak data to recovery
680 while (size < partition->size) {
681 unsigned long long write_size = 0;
682 unsigned long long left_size = partition->size - size;
683
684 if (left_size > 10 * MIB_SIZE)
685 write_size = 10 * MIB_SIZE;
686 else
687 write_size = partition->size - size;
688
689 sprintf(bufcmd, "store read $loadaddr recoverybak 0x%llx 0x%llx",
690 size, write_size);
691 run_command(bufcmd, 0);
692 sprintf(bufcmd, "store write $loadaddr recovery 0x%llx 0x%llx",
693 size, write_size);
694 run_command(bufcmd, 0);
695 size += write_size;
696 }
697
698 //clean recovery_need_update to 0
699 env_set("recovery_need_update", "0");
700 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
701 run_command("update_env_part -p recovery_need_update;", 0);
702 else
703 run_command("saveenv", 0);
704 }
705 return 0;
706}
707
708//add non ab recovery update flow here
709int non_ab_update(char *rebootmode)
710{
Bo Lv72d0e902023-01-02 14:27:34 +0000711 int match_flag = 0;
712 char *rebootstatus = NULL;
713 char *checkresult = NULL;
714 char *bootloaderindex = NULL;
715 char *expect_index = NULL;
716 char *robustota = NULL;
Bo Lv72d0e902023-01-02 14:27:34 +0000717
718 char *write_boot = env_get("write_boot");
719
Zhigang Yude5719e2024-03-08 09:14:23 +0000720 if (write_boot && (!strcmp(write_boot, "1"))) {
721 printf("non ab for kernel 5.15 update bootloader\n");
722 write_bootloader(1);
723 write_bootloader(2);
724 env_set("write_boot", "0");
725 env_set("upgrade_step", "1");
726 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800727 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
728 run_command("reboot quiescent", 0);
729 else
730 run_command("reboot", 0);
Zhigang Yude5719e2024-03-08 09:14:23 +0000731 }
732
733 recovery_update();
734
735 //check_result init
736 checkresult = env_get("check_result");
737 if (!checkresult)
738 env_set("check_result", "succ");
739
740 //reboot_status init
741 rebootstatus = env_get("reboot_status");
742 if (!rebootstatus) {
743 env_set("reboot_status", "reboot_init");
744 rebootstatus = env_get("reboot_status");
745 }
746
747 if (!rebootstatus) {
748 printf("rebootstatus is NULL, skip check\n");
749 return -1;
750 }
751
752 //check reboot_end
753 if (!strcmp(rebootstatus, "reboot_end")) {
754 env_set("reboot_status", "reboot_init");
755 run_command("saveenv", 0);
756 }
757
758 //get forUpgrade_robustOta and check if support robustota
759 robustota = env_get("forUpgrade_robustOta");
760 if (!robustota || !strcmp(robustota, "false"))
761 return -1;
762
763 //no secure check need
764 if (!strcmp(rebootstatus, "reboot_init")) {
765 printf("rebootstatus is reboot_init, skip check\n");
766 return -1;
767 }
768
769 //get bootloader index
770 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
771 if (!bootloaderindex) {
772 wrnP("can not get bootloader index, so skip secure check\n");
773 return -1;
774 }
775
776 //get expect index
777 expect_index = env_get("expect_index");
778 if (!expect_index) {
779 wrnP("can not get expect index, so skip secure check\n");
780 return -1;
781 }
782
783 wrnP("expect_index is : %s\n", expect_index);
784
785 match_flag = strcmp(bootloaderindex, expect_index);
786
787 //ignore reboot next check if power off during reboot next to finish
788 if (rebootmode && (strcmp(rebootmode, "cold_boot") == 0)) {
789 if (!strcmp(rebootstatus, "reboot_finish"))
790 match_flag = 0;
791 }
792
793 if (!strcmp(rebootstatus, "reboot_next")) {
794 env_set("reboot_status", "reboot_finish");
795 run_command("saveenv", 0);
796 run_command("get_rebootmode", 0);
797 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
798 run_command("reboot next,quiescent", 0);
799 else
800 run_command("reboot next", 0);
801 } else if (!strcmp(rebootstatus, "reboot_finish")) {
802 wrnP("--secure check reboot_finish---\n");
803 env_set("reboot_status", "reboot_end");
804 run_command("saveenv", 0);
805 if (match_flag == 0) {
806 wrnP("reboot next succ, bootloader secure check pass......\n");
807 } else {
808 //bootloader check failed, run recovery show error
809 wrnP("reboot next fail, bootloader secure check fail(curr:%s, expect:%s)\n",
810 bootloaderindex, expect_index);
811 env_set("check_result", "bootloader_fail");
812 run_command("saveenv", 0);
813 }
814 run_recovery_from_flash();
815 return 0;
816 } else {
817 env_set("check_result", "succ");
818 }
819 return 0;
820}
821
822//add ab update and ab rollback flow here
823int ab_update_rollback(char *rebootmode, int gpt_flag)
824{
825 int match_flag = 0;
826 char *rebootstatus = NULL;
827 char *bootloaderindex = NULL;
828 char *expect_index = NULL;
829
830 //update bootloader_a/b/up to boot0
831 char *write_boot = env_get("write_boot");
832
833 if (write_boot && !strcmp(write_boot, "1")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000834 printf("need to write boot0\n");
Zhigang Yude5719e2024-03-08 09:14:23 +0000835 if (write_bootloader(1)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000836 printf("write boot0 fail, need to rollback!\n");
837 update_rollback();
838 } else {
Xindong Xu15e83fa2024-03-15 08:56:00 +0800839 update_gpt(0);
Bo Lv72d0e902023-01-02 14:27:34 +0000840 printf("write boot0 success, need to reset!\n");
841 }
842
843 env_set("write_boot", "0");
844 env_set("reboot_status", "reboot_next");
845 env_set("expect_index", "1");
846 env_set("update_env", "1");
847 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800848 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
849 run_command("reboot quiescent", 0);
850 else
851 run_command("reboot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000852 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000853
854 //check rescueparty and rollback
Bo Lv72d0e902023-01-02 14:27:34 +0000855 if (rebootmode && (strcmp(rebootmode, "rescueparty") == 0)) {
856 printf("rebootmode is rescueparty, need rollback\n");
857 char *slot;
858
Bo Lv72d0e902023-01-02 14:27:34 +0000859#ifdef CONFIG_FASTBOOT
860 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000861 set_mergestatus_cancel(&message);
862#endif
863
864 slot = env_get("slot-suffixes");
865 if (!slot) {
866 run_command("get_valid_slot", 0);
867 slot = env_get("slot-suffixes");
868 }
869 if (strcmp(slot, "0") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000870 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000871 wrnP("normal mode\n");
872 write_bootloader_back("2", 0);
873 env_set("expect_index", "0");
874 } else {
875 wrnP("gpt or disable user bootloader mode\n");
876 write_bootloader_back("2", 1);
877 env_set("expect_index", "1");
878 }
879 wrnP("back to slot b\n");
880 run_command("set_roll_flag 1", 0);
881 run_command("set_active_slot b", 0);
882 } else if (strcmp(slot, "1") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000883 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000884 wrnP("normal mode\n");
885 write_bootloader_back("1", 0);
886 env_set("expect_index", "0");
887 } else {
888 wrnP("gpt or disable user bootloader mode\n");
889 write_bootloader_back("2", 1);
890 env_set("expect_index", "1");
891 }
892 wrnP("back to slot a\n");
893 run_command("set_roll_flag 1", 0);
894 run_command("set_active_slot a", 0);
895 }
896
897 env_set("update_env", "1");
898 env_set("reboot_status", "reboot_next");
899 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800900 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
901 run_command("reboot quiescent", 0);
902 else
903 run_command("reboot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000904 }
905
Bo Lv72d0e902023-01-02 14:27:34 +0000906 //get bootloader index
907 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
908 if (bootloaderindex == NULL) {
909 wrnP("can not get bootloader index, so skip secure check\n");
910 return -1;
911 }
Xindong Xu22e8daf2024-03-12 18:08:41 +0800912
Bo Lv72d0e902023-01-02 14:27:34 +0000913 //get expect index
914 expect_index = env_get("expect_index");
915 if (expect_index == NULL) {
916 wrnP("can not get expect index, so skip secure check\n");
917 return -1;
918 }
919
920 wrnP("expect_index is : %s\n", expect_index);
921
922 match_flag = strcmp(bootloaderindex, expect_index);
923
Zhigang Yude5719e2024-03-08 09:14:23 +0000924 rebootstatus = env_get("reboot_status");
Bo Lv72d0e902023-01-02 14:27:34 +0000925
Zhigang Yude5719e2024-03-08 09:14:23 +0000926 //if reboot next need check bootloader rollback
927 if (rebootstatus && !strcmp(rebootstatus, "reboot_next")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000928 wrnP("--secure check reboot_next---\n");
929 //bootloader index, expect == current, no need reboot next
Zhigang Yude5719e2024-03-08 09:14:23 +0000930 if (match_flag != 0) {
931 wrnP("bootloader wrong, start rollback\n");
932 if (gpt_flag == 1) {
933 wrnP("gpt or disable user bootloader mode, write boot1 to boot0\n");
934 write_bootloader_back("2", 1);
Bo Lv72d0e902023-01-02 14:27:34 +0000935#ifdef CONFIG_FASTBOOT
Zhigang Yude5719e2024-03-08 09:14:23 +0000936 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000937
Zhigang Yude5719e2024-03-08 09:14:23 +0000938 set_mergestatus_cancel(&message);
Bo Lv72d0e902023-01-02 14:27:34 +0000939#endif
Zhigang Yude5719e2024-03-08 09:14:23 +0000940 char *slot;
Bo Lv72d0e902023-01-02 14:27:34 +0000941
Zhigang Yude5719e2024-03-08 09:14:23 +0000942 slot = env_get("slot-suffixes");
943 if (!slot) {
944 run_command("get_valid_slot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000945 slot = env_get("slot-suffixes");
Bo Lv72d0e902023-01-02 14:27:34 +0000946 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000947 if (strcmp(slot, "0") == 0) {
948 wrnP("back to slot b\n");
949 run_command("set_roll_flag 1", 0);
950 run_command("set_active_slot b", 0);
951 } else if (strcmp(slot, "1") == 0) {
952 wrnP("back to slot a\n");
953 run_command("set_roll_flag 1", 0);
954 run_command("set_active_slot a", 0);
955 }
956 env_set("expect_index", "1");
Bo Lv72d0e902023-01-02 14:27:34 +0000957 } else {
Zhigang Yude5719e2024-03-08 09:14:23 +0000958 write_bootloader_back(bootloaderindex, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000959#ifdef CONFIG_FASTBOOT
960 struct misc_virtual_ab_message message;
961 set_mergestatus_cancel(&message);
962#endif
963 if (strcmp(bootloaderindex, "1") == 0) {
964 wrnP("back to slot a\n");
965 run_command("set_roll_flag 1", 0);
966 run_command("set_active_slot a", 0);
967 } else if (strcmp(bootloaderindex, "2") == 0) {
968 wrnP("back to slot b\n");
969 run_command("set_roll_flag 1", 0);
970 run_command("set_active_slot b", 0);
971 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000972 env_set("expect_index", "0");
Bo Lv72d0e902023-01-02 14:27:34 +0000973 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000974
975 env_set("update_env", "1");
976 env_set("reboot_status", "reboot_next");
Bo Lv72d0e902023-01-02 14:27:34 +0000977 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800978 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
979 run_command("reboot quiescent", 0);
980 else
981 run_command("reboot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000982 return 0;
hao.qi5fa394b2024-07-18 14:54:45 +0800983 }else {
984 wrnP("current index is expect, no need reboot next, set reboot_status reboot_init\n");
985 env_set("reboot_status", "reboot_init");
986#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
987 run_command("update_env_part -p reboot_status;", 0);
988#else
989 run_command("saveenv", 0);
990#endif
Zhigang Yude5719e2024-03-08 09:14:23 +0000991 }
Bo Lv72d0e902023-01-02 14:27:34 +0000992 }
993
994 return 0;
995}
996
Zhigang Yude5719e2024-03-08 09:14:23 +0000997static int do_secureboot_check(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
998{
999 char *rebootmode = NULL;
1000 int gpt_flag = 0;
1001 int ret = -1;
1002
1003 // set product first to set serial.
1004 set_product();
1005
1006#ifdef CONFIG_MMC_MESON_GX
1007 struct mmc *mmc = NULL;
1008 //int capacity_boot = 0;
1009
1010 if (store_get_type() == BOOT_EMMC) {
1011 mmc = find_mmc_device(1);
1012 if (mmc)
1013 ret = aml_gpt_valid(mmc);
1014 }
1015#endif
1016
1017 //check is gpt mode
1018 if (ret == 0)
1019 gpt_flag = 1;
1020
1021 //unsupport update dt in boothal, update dt in uboot
1022 run_command("update_dt;", 0);
1023
1024 bootloader_wp();
1025
1026 //set default env before check
1027 env_set("recovery_mode", "false");
1028
1029 //if recovery mode, need disable dv, if factoryreset, need default uboot env
1030 aml_recovery();
1031
1032#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
1033 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
1034
1035 if (*efuse_field.data == 1) {
1036 wrnP("efuse_field.data == 1\n");
1037 env_set("nocs_mode", "true");
1038 gpt_flag = 1;
1039 } else {
1040 wrnP("efuse_field.data != 1\n");
1041 env_set("nocs_mode", "false");
1042 }
1043#endif//#ifdef CONFIG_EFUSE_OBJ_API
1044
1045
1046 run_command("get_rebootmode", 0);
1047 rebootmode = env_get("reboot_mode");
1048 if (!rebootmode) {
1049 wrnP("can not get reboot mode, so skip secure check\n");
1050 return -1;
1051 }
1052 printf("rebootmode is %s\n", rebootmode);
1053
1054 //get boot status
1055 run_command("amlbootsta -p -s", 0);
1056
1057 if (IS_ENABLED(CONFIG_MMC_MESON_GX))
1058 fastboot_step_check(rebootmode, gpt_flag);
1059
1060 if (has_boot_slot == 1)
1061 ab_update_rollback(rebootmode, gpt_flag);
1062 else
1063 non_ab_update(rebootmode);
1064
1065 return 0;
1066}
1067
1068
1069static int do_update_uboot_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1070{
1071 const int write_boot = env_get_ulong("write_boot", 10, 0);
1072 const int update_dts_gpt = env_get_ulong("update_dts_gpt", 10, 0);
1073
1074 //skip update env if need update bootloader
1075 if (write_boot || update_dts_gpt) {
1076 run_command("echo write_boot ${write_boot}, update_dts_gpt ${update_dts_gpt}", 0);
1077 return 0;
1078 }
1079
1080 //default uboot env need before anyone use it
1081 //after factory reset
1082 if (env_get("default_env")) {
1083 printf("factory reset, need default all uboot env.\n");
1084 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1085 }
1086
1087 //after ab update
1088 char *update_env = env_get("update_env");
1089
1090 if (update_env && (strcmp(update_env, "1") == 0)) {
1091 printf("ab mode, default all uboot env\n");
1092 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1093 }
1094
1095 //after recovery update
1096 char *upgrade_step = env_get("upgrade_step");
1097
1098 if (upgrade_step && (strcmp(upgrade_step, "1") == 0)) {
1099 printf("after recovery update, need update uboot env\n");
1100 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1101 }
1102
1103 return 0;
1104}
Bo Lv72d0e902023-01-02 14:27:34 +00001105
1106U_BOOT_CMD_COMPLETE(
1107 amlbootsta, 3, 0, do_get_bootloader_status,
1108 "get bootloader status in env",
1109 "[-p] print bootloader status\n"
1110 "[-s] saveenv after generate bootloader status\n",
1111 var_complete
1112);
1113
1114U_BOOT_CMD_COMPLETE(
1115 amlsecurecheck, 1, 0, do_secureboot_check,
1116 "try bootloader/dtb/recovery secure check",
1117 ""
1118 "",
1119 var_complete
1120);
1121
Zhigang Yude5719e2024-03-08 09:14:23 +00001122U_BOOT_CMD(aml_update_env, 1, 0, do_update_uboot_env,
1123 "aml_update_env",
1124 "\nThis command will update uboot env\n"
1125 "So you can execute command: aml_update_env"
1126);
1127
Bo Lv72d0e902023-01-02 14:27:34 +00001128