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