blob: e1a267c5e51357d4fcc53015c81b55d1ea4a6eee [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);
723 run_command("reset", 0);
724 }
725
726 recovery_update();
727
728 //check_result init
729 checkresult = env_get("check_result");
730 if (!checkresult)
731 env_set("check_result", "succ");
732
733 //reboot_status init
734 rebootstatus = env_get("reboot_status");
735 if (!rebootstatus) {
736 env_set("reboot_status", "reboot_init");
737 rebootstatus = env_get("reboot_status");
738 }
739
740 if (!rebootstatus) {
741 printf("rebootstatus is NULL, skip check\n");
742 return -1;
743 }
744
745 //check reboot_end
746 if (!strcmp(rebootstatus, "reboot_end")) {
747 env_set("reboot_status", "reboot_init");
748 run_command("saveenv", 0);
749 }
750
751 //get forUpgrade_robustOta and check if support robustota
752 robustota = env_get("forUpgrade_robustOta");
753 if (!robustota || !strcmp(robustota, "false"))
754 return -1;
755
756 //no secure check need
757 if (!strcmp(rebootstatus, "reboot_init")) {
758 printf("rebootstatus is reboot_init, skip check\n");
759 return -1;
760 }
761
762 //get bootloader index
763 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
764 if (!bootloaderindex) {
765 wrnP("can not get bootloader index, so skip secure check\n");
766 return -1;
767 }
768
769 //get expect index
770 expect_index = env_get("expect_index");
771 if (!expect_index) {
772 wrnP("can not get expect index, so skip secure check\n");
773 return -1;
774 }
775
776 wrnP("expect_index is : %s\n", expect_index);
777
778 match_flag = strcmp(bootloaderindex, expect_index);
779
780 //ignore reboot next check if power off during reboot next to finish
781 if (rebootmode && (strcmp(rebootmode, "cold_boot") == 0)) {
782 if (!strcmp(rebootstatus, "reboot_finish"))
783 match_flag = 0;
784 }
785
786 if (!strcmp(rebootstatus, "reboot_next")) {
787 env_set("reboot_status", "reboot_finish");
788 run_command("saveenv", 0);
789 run_command("get_rebootmode", 0);
790 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
791 run_command("reboot next,quiescent", 0);
792 else
793 run_command("reboot next", 0);
794 } else if (!strcmp(rebootstatus, "reboot_finish")) {
795 wrnP("--secure check reboot_finish---\n");
796 env_set("reboot_status", "reboot_end");
797 run_command("saveenv", 0);
798 if (match_flag == 0) {
799 wrnP("reboot next succ, bootloader secure check pass......\n");
800 } else {
801 //bootloader check failed, run recovery show error
802 wrnP("reboot next fail, bootloader secure check fail(curr:%s, expect:%s)\n",
803 bootloaderindex, expect_index);
804 env_set("check_result", "bootloader_fail");
805 run_command("saveenv", 0);
806 }
807 run_recovery_from_flash();
808 return 0;
809 } else {
810 env_set("check_result", "succ");
811 }
812 return 0;
813}
814
815//add ab update and ab rollback flow here
816int ab_update_rollback(char *rebootmode, int gpt_flag)
817{
818 int match_flag = 0;
819 char *rebootstatus = NULL;
820 char *bootloaderindex = NULL;
821 char *expect_index = NULL;
822
823 //update bootloader_a/b/up to boot0
824 char *write_boot = env_get("write_boot");
825
826 if (write_boot && !strcmp(write_boot, "1")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000827 printf("need to write boot0\n");
Zhigang Yude5719e2024-03-08 09:14:23 +0000828 if (write_bootloader(1)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000829 printf("write boot0 fail, need to rollback!\n");
830 update_rollback();
831 } else {
Xindong Xu15e83fa2024-03-15 08:56:00 +0800832 update_gpt(0);
Bo Lv72d0e902023-01-02 14:27:34 +0000833 printf("write boot0 success, need to reset!\n");
834 }
835
836 env_set("write_boot", "0");
837 env_set("reboot_status", "reboot_next");
838 env_set("expect_index", "1");
839 env_set("update_env", "1");
840 run_command("saveenv", 0);
841 run_command("reset", 0);
842 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000843
844 //check rescueparty and rollback
Bo Lv72d0e902023-01-02 14:27:34 +0000845 if (rebootmode && (strcmp(rebootmode, "rescueparty") == 0)) {
846 printf("rebootmode is rescueparty, need rollback\n");
847 char *slot;
848
Bo Lv72d0e902023-01-02 14:27:34 +0000849#ifdef CONFIG_FASTBOOT
850 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000851 set_mergestatus_cancel(&message);
852#endif
853
854 slot = env_get("slot-suffixes");
855 if (!slot) {
856 run_command("get_valid_slot", 0);
857 slot = env_get("slot-suffixes");
858 }
859 if (strcmp(slot, "0") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000860 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000861 wrnP("normal mode\n");
862 write_bootloader_back("2", 0);
863 env_set("expect_index", "0");
864 } else {
865 wrnP("gpt or disable user bootloader mode\n");
866 write_bootloader_back("2", 1);
867 env_set("expect_index", "1");
868 }
869 wrnP("back to slot b\n");
870 run_command("set_roll_flag 1", 0);
871 run_command("set_active_slot b", 0);
872 } else if (strcmp(slot, "1") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000873 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000874 wrnP("normal mode\n");
875 write_bootloader_back("1", 0);
876 env_set("expect_index", "0");
877 } else {
878 wrnP("gpt or disable user bootloader mode\n");
879 write_bootloader_back("2", 1);
880 env_set("expect_index", "1");
881 }
882 wrnP("back to slot a\n");
883 run_command("set_roll_flag 1", 0);
884 run_command("set_active_slot a", 0);
885 }
886
887 env_set("update_env", "1");
888 env_set("reboot_status", "reboot_next");
889 run_command("saveenv", 0);
890 run_command("reset", 0);
891 }
892
Bo Lv72d0e902023-01-02 14:27:34 +0000893 //get bootloader index
894 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
895 if (bootloaderindex == NULL) {
896 wrnP("can not get bootloader index, so skip secure check\n");
897 return -1;
898 }
Xindong Xu22e8daf2024-03-12 18:08:41 +0800899
Bo Lv72d0e902023-01-02 14:27:34 +0000900 //get expect index
901 expect_index = env_get("expect_index");
902 if (expect_index == NULL) {
903 wrnP("can not get expect index, so skip secure check\n");
904 return -1;
905 }
906
907 wrnP("expect_index is : %s\n", expect_index);
908
909 match_flag = strcmp(bootloaderindex, expect_index);
910
Zhigang Yude5719e2024-03-08 09:14:23 +0000911 rebootstatus = env_get("reboot_status");
Bo Lv72d0e902023-01-02 14:27:34 +0000912
Zhigang Yude5719e2024-03-08 09:14:23 +0000913 //if reboot next need check bootloader rollback
914 if (rebootstatus && !strcmp(rebootstatus, "reboot_next")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000915 wrnP("--secure check reboot_next---\n");
916 //bootloader index, expect == current, no need reboot next
Zhigang Yude5719e2024-03-08 09:14:23 +0000917 if (match_flag != 0) {
918 wrnP("bootloader wrong, start rollback\n");
919 if (gpt_flag == 1) {
920 wrnP("gpt or disable user bootloader mode, write boot1 to boot0\n");
921 write_bootloader_back("2", 1);
Bo Lv72d0e902023-01-02 14:27:34 +0000922#ifdef CONFIG_FASTBOOT
Zhigang Yude5719e2024-03-08 09:14:23 +0000923 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000924
Zhigang Yude5719e2024-03-08 09:14:23 +0000925 set_mergestatus_cancel(&message);
Bo Lv72d0e902023-01-02 14:27:34 +0000926#endif
Zhigang Yude5719e2024-03-08 09:14:23 +0000927 char *slot;
Bo Lv72d0e902023-01-02 14:27:34 +0000928
Zhigang Yude5719e2024-03-08 09:14:23 +0000929 slot = env_get("slot-suffixes");
930 if (!slot) {
931 run_command("get_valid_slot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000932 slot = env_get("slot-suffixes");
Bo Lv72d0e902023-01-02 14:27:34 +0000933 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000934 if (strcmp(slot, "0") == 0) {
935 wrnP("back to slot b\n");
936 run_command("set_roll_flag 1", 0);
937 run_command("set_active_slot b", 0);
938 } else if (strcmp(slot, "1") == 0) {
939 wrnP("back to slot a\n");
940 run_command("set_roll_flag 1", 0);
941 run_command("set_active_slot a", 0);
942 }
943 env_set("expect_index", "1");
Bo Lv72d0e902023-01-02 14:27:34 +0000944 } else {
Zhigang Yude5719e2024-03-08 09:14:23 +0000945 write_bootloader_back(bootloaderindex, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000946#ifdef CONFIG_FASTBOOT
947 struct misc_virtual_ab_message message;
948 set_mergestatus_cancel(&message);
949#endif
950 if (strcmp(bootloaderindex, "1") == 0) {
951 wrnP("back to slot a\n");
952 run_command("set_roll_flag 1", 0);
953 run_command("set_active_slot a", 0);
954 } else if (strcmp(bootloaderindex, "2") == 0) {
955 wrnP("back to slot b\n");
956 run_command("set_roll_flag 1", 0);
957 run_command("set_active_slot b", 0);
958 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000959 env_set("expect_index", "0");
Bo Lv72d0e902023-01-02 14:27:34 +0000960 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000961
962 env_set("update_env", "1");
963 env_set("reboot_status", "reboot_next");
Bo Lv72d0e902023-01-02 14:27:34 +0000964 run_command("saveenv", 0);
Zhigang Yude5719e2024-03-08 09:14:23 +0000965 run_command("reset", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000966 return 0;
Zhigang Yude5719e2024-03-08 09:14:23 +0000967 }
Bo Lv72d0e902023-01-02 14:27:34 +0000968 }
969
970 return 0;
971}
972
Zhigang Yude5719e2024-03-08 09:14:23 +0000973static int do_secureboot_check(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
974{
975 char *rebootmode = NULL;
976 int gpt_flag = 0;
977 int ret = -1;
978
979 // set product first to set serial.
980 set_product();
981
982#ifdef CONFIG_MMC_MESON_GX
983 struct mmc *mmc = NULL;
984 //int capacity_boot = 0;
985
986 if (store_get_type() == BOOT_EMMC) {
987 mmc = find_mmc_device(1);
988 if (mmc)
989 ret = aml_gpt_valid(mmc);
990 }
991#endif
992
993 //check is gpt mode
994 if (ret == 0)
995 gpt_flag = 1;
996
997 //unsupport update dt in boothal, update dt in uboot
998 run_command("update_dt;", 0);
999
1000 bootloader_wp();
1001
1002 //set default env before check
1003 env_set("recovery_mode", "false");
1004
1005 //if recovery mode, need disable dv, if factoryreset, need default uboot env
1006 aml_recovery();
1007
1008#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
1009 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
1010
1011 if (*efuse_field.data == 1) {
1012 wrnP("efuse_field.data == 1\n");
1013 env_set("nocs_mode", "true");
1014 gpt_flag = 1;
1015 } else {
1016 wrnP("efuse_field.data != 1\n");
1017 env_set("nocs_mode", "false");
1018 }
1019#endif//#ifdef CONFIG_EFUSE_OBJ_API
1020
1021
1022 run_command("get_rebootmode", 0);
1023 rebootmode = env_get("reboot_mode");
1024 if (!rebootmode) {
1025 wrnP("can not get reboot mode, so skip secure check\n");
1026 return -1;
1027 }
1028 printf("rebootmode is %s\n", rebootmode);
1029
1030 //get boot status
1031 run_command("amlbootsta -p -s", 0);
1032
1033 if (IS_ENABLED(CONFIG_MMC_MESON_GX))
1034 fastboot_step_check(rebootmode, gpt_flag);
1035
1036 if (has_boot_slot == 1)
1037 ab_update_rollback(rebootmode, gpt_flag);
1038 else
1039 non_ab_update(rebootmode);
1040
1041 return 0;
1042}
1043
1044
1045static int do_update_uboot_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1046{
1047 const int write_boot = env_get_ulong("write_boot", 10, 0);
1048 const int update_dts_gpt = env_get_ulong("update_dts_gpt", 10, 0);
1049
1050 //skip update env if need update bootloader
1051 if (write_boot || update_dts_gpt) {
1052 run_command("echo write_boot ${write_boot}, update_dts_gpt ${update_dts_gpt}", 0);
1053 return 0;
1054 }
1055
1056 //default uboot env need before anyone use it
1057 //after factory reset
1058 if (env_get("default_env")) {
1059 printf("factory reset, need default all uboot env.\n");
1060 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1061 }
1062
1063 //after ab update
1064 char *update_env = env_get("update_env");
1065
1066 if (update_env && (strcmp(update_env, "1") == 0)) {
1067 printf("ab mode, default all uboot env\n");
1068 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1069 }
1070
1071 //after recovery update
1072 char *upgrade_step = env_get("upgrade_step");
1073
1074 if (upgrade_step && (strcmp(upgrade_step, "1") == 0)) {
1075 printf("after recovery update, need update uboot env\n");
1076 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1077 }
1078
1079 return 0;
1080}
Bo Lv72d0e902023-01-02 14:27:34 +00001081
1082U_BOOT_CMD_COMPLETE(
1083 amlbootsta, 3, 0, do_get_bootloader_status,
1084 "get bootloader status in env",
1085 "[-p] print bootloader status\n"
1086 "[-s] saveenv after generate bootloader status\n",
1087 var_complete
1088);
1089
1090U_BOOT_CMD_COMPLETE(
1091 amlsecurecheck, 1, 0, do_secureboot_check,
1092 "try bootloader/dtb/recovery secure check",
1093 ""
1094 "",
1095 var_complete
1096);
1097
Zhigang Yude5719e2024-03-08 09:14:23 +00001098U_BOOT_CMD(aml_update_env, 1, 0, do_update_uboot_env,
1099 "aml_update_env",
1100 "\nThis command will update uboot env\n"
1101 "So you can execute command: aml_update_env"
1102);
1103
Bo Lv72d0e902023-01-02 14:27:34 +00001104