blob: 4b4815548423d3534394dc25f3ad4e9592582220 [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, "_");
hao.qi952f6d92024-06-03 20:56:42 +0800410 if (!str) {
411 env_set("product", board);
412 return;
413 }
hao.qi4c4dc762024-03-11 10:38:23 +0800414 dup_str = strdup(str);
415 if (!(strstr(dup_str, "_")))
416 env_set("product", str + 1);
417 else
418 env_set("product", strtok(str, "_"));
419 free(dup_str);
hao.qi952f6d92024-06-03 20:56:42 +0800420 return;
hao.qi4c4dc762024-03-11 10:38:23 +0800421}
422
Zhigang Yude5719e2024-03-08 09:14:23 +0000423void fastboot_step_check(char *rebootmode, int gpt_flag)
424{
425 char *bootloaderindex = NULL;
426 struct mmc *mmc = NULL;
427
428 if (store_get_type() == BOOT_EMMC)
429 mmc = find_mmc_device(1);
430
431 //get bootloader index
432 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
433 if (!bootloaderindex) {
434 wrnP("can not get bootloader index, so skip fastboot step check\n");
435 return;
436 }
437
438 char *fastboot_step = env_get("fastboot_step");
439
440 if (mmc && fastboot_step && (strcmp(fastboot_step, "1") == 0)) {
441 printf("reboot to new bootloader burned by fastboot\n");
442 env_set("update_env", "1");
443 env_set("fastboot_step", "2");
444 run_command("saveenv", 0);
445 if (rebootmode && (strcmp(rebootmode, "fastboot") == 0))
446 run_command("reboot next,bootloader", 0);
447 else
448 run_command("reboot next", 0);
449 }
450 if (mmc && fastboot_step && (strcmp(fastboot_step, "2") == 0)) {
451 struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
452
453 if (dev_desc && ((gpt_flag == 1 && !strcmp(bootloaderindex, "1")) ||
454 (gpt_flag == 0 && !strcmp(bootloaderindex, "0")))) {
455 printf("new bootloader error, please fastboot to another one\n");
456 env_set("fastboot_step", "0");
457 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
458 run_command("update_env_part -p fastboot_step;", 0);
459 else
460 run_command("defenv_reserve;setenv fastboot_step 0;saveenv;", 0);
461 cli_init();
462 cli_loop();
463 }
464 }
465}
466
Xindong Xu15e83fa2024-03-15 08:56:00 +0800467static int update_gpt(int flag)
468{
469 int ret = 0;
470#ifdef CONFIG_MMC_MESON_GX
471 unsigned char *buffer = NULL;
472 int capacity_boot = 0x2000 * 512;
473 int iRet = 0;
474 struct mmc *mmc = NULL;
475 struct blk_desc *dev_desc;
476
477 if (store_get_type() == BOOT_EMMC)
478 mmc = find_mmc_device(1);
479
480 if (mmc)
481 capacity_boot = mmc->capacity_boot;
482
483 printf("capacity_boot: 0x%x\n", capacity_boot);
484 buffer = (unsigned char *)malloc(capacity_boot);
485 if (!buffer) {
486 printf("ERROR! fail to allocate memory ...\n");
487 return -1;
488 }
489 memset(buffer, 0, capacity_boot);
490
491 if (flag == 0) {
492 iRet = store_boot_read("bootloader", 1, 0, buffer);
493 if (iRet) {
494 printf("Failed to read boot0\n");
495 ret = -1;
496 goto exit;
497 }
498 } else if (flag == 1 || flag == 2) {
499 iRet = store_boot_read("bootloader", 0, 0, buffer);
500 if (iRet) {
501 printf("Failed to read bootloader\n");
502 ret = -1;
503 goto exit;
504 }
505 } else if (flag == 3) {
506 printf("null ab mode\n");
507 iRet = store_logic_read("bootloader_up", 0,
508 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
509 if (iRet) {
510 printf("Fail to read 0x%xB from bootloader_up\n",
511 BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET);
512 ret = -1;
513 goto exit;
514 }
515 }
516
517 if (mmc) {
518 printf("try to read gpt data from bootloader.img\n");
519 int erase_flag = 0;
520
521 dev_desc = blk_get_dev("mmc", 1);
522 if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
523 printf("invalid mmc device\n");
524 ret = -1;
525 goto exit;
526 }
527
528 if (is_valid_gpt_buf(dev_desc, buffer + 0x3DFE00)) {
529 printf("printf normal bootloader.img, no gpt partition table\n");
530 ret = -1;
531 goto exit;
532 } else {
533 erase_flag = check_gpt_change(dev_desc, buffer + 0x3DFE00);
534
535 if (erase_flag == 4 && has_boot_slot == 0) {
536 printf("null ab critical partition change, refused to upgrade\n");
537 ret = -1;
538 goto exit;
539 } else if (has_boot_slot == 1 && (erase_flag == 3 || erase_flag == 4)) {
540 printf("Important partition changes, refused to upgrade\n");
541 ret = 1;
542 goto exit;
543 } else if (erase_flag == 0) {
544 printf("partition doesn't change, needn't update\n");
545 ret = -1;
546 goto exit;
547 }
548
549 if (flag == 1 || flag == 2) {
550 printf("update from dts to gpt, erase first\n");
551 erase_gpt_part_table(dev_desc);
552 }
553
554 if (flag == 2) {
555#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
556 env_set("dts_to_gpt", "1");
557 run_command("update_env_part -p dts_to_gpt;", 0);
558#else
559 run_command("defenv_reserve;setenv dts_to_gpt 1;saveenv;", 0);
560#endif
561 }
562
563 if (write_mbr_and_gpt_partitions(dev_desc, buffer + 0x3DFE00)) {
564 printf("%s: writing GPT partitions failed\n", __func__);
565 ret = 1;
566 goto exit;
567 }
568
569 if (mmc_device_init(mmc) != 0) {
570 printf(" update gpt partition table fail\n");
571 ret = 2;
572 goto exit;
573 }
574 printf("%s: writing GPT partitions ok\n", __func__);
575 }
576 }
577
578 if (has_boot_slot == 1 && (flag == 1 || flag == 2)) {
579 printf("update from dts to gpt, backup old bootloader\n");
580 char *slot = NULL;
581
582 slot = env_get("slot-suffixes");
583 if (!slot) {
584 run_command("get_valid_slot", 0);
585 slot = env_get("slot-suffixes");
586 }
587 if (strcmp(slot, "0") == 0) {
588 printf("active is a, b is old, don't need backup\n");
589 } else if (strcmp(slot, "1") == 0) {
590 printf("active is b, a is old, backup boot0 to boot1\n");
591 iRet = write_bootloader_back("1", 2);
592 if (iRet != 0) {
593 printf("Failed to write boot1\n");
594 ret = 3;
595 goto exit;
596 }
597 }
598 iRet = store_boot_write("bootloader", 1, 0, buffer);
599 if (iRet) {
600 printf("Failed to write boot0\n");
601 ret = 4;
602 goto exit;
603 }
604 }
605
606exit:
607 if (buffer)
608 free(buffer);
609
610 if (mmc)
611 run_command("mmc dev 1 0;", 0);
612
613 if (mmc && ret > 0) {
614 if (ret == 1 || ret == 2 || ret == 3) {
615 printf("rollback\n");
616 update_rollback();
617 } else if (ret == 4) {
618 printf("write back boot0, rollback\n");
619 write_bootloader_back("2", 1);
620 update_rollback();
621 }
622 }
623#endif
624 return ret;
625}
626
Zhigang Yude5719e2024-03-08 09:14:23 +0000627int recovery_update(void)
628{
629 if (IS_ENABLED(CONFIG_MMC_MESON_GX)) {
630 char bufcmd[64];
631 unsigned long long size = 0;
632 char *recovery_need_update = NULL;
633 struct partitions *partition = NULL;
634 //"ANDROID!"
635 const unsigned char imghead[] = { 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x21 };
636
637 if (store_get_type() != BOOT_EMMC)
638 return 0;
639
640 //check recoverybak partition exist
641 partition = find_mmc_partition_by_name("recoverybak");
642 if (!partition) {
643 printf("can not find recoverybak, skip\n");
644 return 0;
645 }
646
647 //check if need update recovery from recoverybak
648 recovery_need_update = env_get("recovery_need_update");
649 if (!recovery_need_update || strcmp(recovery_need_update, "1"))
650 return 0;
651
652 //read recoverybak header data for check
653 sprintf(bufcmd, "store read $loadaddr recoverybak 0 0x%x", 16);
654 run_command(bufcmd, 0);
655
656 unsigned char *loadaddr = NULL;
657
658 loadaddr = (unsigned char *)simple_strtoul(env_get("loadaddr"), NULL, 16);
659
660 //check recoverybak head is start "ANDROID!"
661 if (memcmp((void *)imghead, loadaddr, 8)) {
662 printf("not valid recovery image, skip update recovery\n");
663 return 0;
664 }
665
666 //write recoverybak data to recovery
667 while (size < partition->size) {
668 unsigned long long write_size = 0;
669 unsigned long long left_size = partition->size - size;
670
671 if (left_size > 10 * MIB_SIZE)
672 write_size = 10 * MIB_SIZE;
673 else
674 write_size = partition->size - size;
675
676 sprintf(bufcmd, "store read $loadaddr recoverybak 0x%llx 0x%llx",
677 size, write_size);
678 run_command(bufcmd, 0);
679 sprintf(bufcmd, "store write $loadaddr recovery 0x%llx 0x%llx",
680 size, write_size);
681 run_command(bufcmd, 0);
682 size += write_size;
683 }
684
685 //clean recovery_need_update to 0
686 env_set("recovery_need_update", "0");
687 if (CONFIG_IS_ENABLED(AML_UPDATE_ENV))
688 run_command("update_env_part -p recovery_need_update;", 0);
689 else
690 run_command("saveenv", 0);
691 }
692 return 0;
693}
694
695//add non ab recovery update flow here
696int non_ab_update(char *rebootmode)
697{
Bo Lv72d0e902023-01-02 14:27:34 +0000698 int match_flag = 0;
699 char *rebootstatus = NULL;
700 char *checkresult = NULL;
701 char *bootloaderindex = NULL;
702 char *expect_index = NULL;
703 char *robustota = NULL;
Bo Lv72d0e902023-01-02 14:27:34 +0000704
705 char *write_boot = env_get("write_boot");
706
Zhigang Yude5719e2024-03-08 09:14:23 +0000707 if (write_boot && (!strcmp(write_boot, "1"))) {
708 printf("non ab for kernel 5.15 update bootloader\n");
709 write_bootloader(1);
710 write_bootloader(2);
711 env_set("write_boot", "0");
712 env_set("upgrade_step", "1");
713 run_command("saveenv", 0);
714 run_command("reset", 0);
715 }
716
717 recovery_update();
718
719 //check_result init
720 checkresult = env_get("check_result");
721 if (!checkresult)
722 env_set("check_result", "succ");
723
724 //reboot_status init
725 rebootstatus = env_get("reboot_status");
726 if (!rebootstatus) {
727 env_set("reboot_status", "reboot_init");
728 rebootstatus = env_get("reboot_status");
729 }
730
731 if (!rebootstatus) {
732 printf("rebootstatus is NULL, skip check\n");
733 return -1;
734 }
735
736 //check reboot_end
737 if (!strcmp(rebootstatus, "reboot_end")) {
738 env_set("reboot_status", "reboot_init");
739 run_command("saveenv", 0);
740 }
741
742 //get forUpgrade_robustOta and check if support robustota
743 robustota = env_get("forUpgrade_robustOta");
744 if (!robustota || !strcmp(robustota, "false"))
745 return -1;
746
747 //no secure check need
748 if (!strcmp(rebootstatus, "reboot_init")) {
749 printf("rebootstatus is reboot_init, skip check\n");
750 return -1;
751 }
752
753 //get bootloader index
754 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
755 if (!bootloaderindex) {
756 wrnP("can not get bootloader index, so skip secure check\n");
757 return -1;
758 }
759
760 //get expect index
761 expect_index = env_get("expect_index");
762 if (!expect_index) {
763 wrnP("can not get expect index, so skip secure check\n");
764 return -1;
765 }
766
767 wrnP("expect_index is : %s\n", expect_index);
768
769 match_flag = strcmp(bootloaderindex, expect_index);
770
771 //ignore reboot next check if power off during reboot next to finish
772 if (rebootmode && (strcmp(rebootmode, "cold_boot") == 0)) {
773 if (!strcmp(rebootstatus, "reboot_finish"))
774 match_flag = 0;
775 }
776
777 if (!strcmp(rebootstatus, "reboot_next")) {
778 env_set("reboot_status", "reboot_finish");
779 run_command("saveenv", 0);
780 run_command("get_rebootmode", 0);
781 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
782 run_command("reboot next,quiescent", 0);
783 else
784 run_command("reboot next", 0);
785 } else if (!strcmp(rebootstatus, "reboot_finish")) {
786 wrnP("--secure check reboot_finish---\n");
787 env_set("reboot_status", "reboot_end");
788 run_command("saveenv", 0);
789 if (match_flag == 0) {
790 wrnP("reboot next succ, bootloader secure check pass......\n");
791 } else {
792 //bootloader check failed, run recovery show error
793 wrnP("reboot next fail, bootloader secure check fail(curr:%s, expect:%s)\n",
794 bootloaderindex, expect_index);
795 env_set("check_result", "bootloader_fail");
796 run_command("saveenv", 0);
797 }
798 run_recovery_from_flash();
799 return 0;
800 } else {
801 env_set("check_result", "succ");
802 }
803 return 0;
804}
805
806//add ab update and ab rollback flow here
807int ab_update_rollback(char *rebootmode, int gpt_flag)
808{
809 int match_flag = 0;
810 char *rebootstatus = NULL;
811 char *bootloaderindex = NULL;
812 char *expect_index = NULL;
813
814 //update bootloader_a/b/up to boot0
815 char *write_boot = env_get("write_boot");
816
817 if (write_boot && !strcmp(write_boot, "1")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000818 printf("need to write boot0\n");
Zhigang Yude5719e2024-03-08 09:14:23 +0000819 if (write_bootloader(1)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000820 printf("write boot0 fail, need to rollback!\n");
821 update_rollback();
822 } else {
Xindong Xu15e83fa2024-03-15 08:56:00 +0800823 update_gpt(0);
Bo Lv72d0e902023-01-02 14:27:34 +0000824 printf("write boot0 success, need to reset!\n");
825 }
826
827 env_set("write_boot", "0");
828 env_set("reboot_status", "reboot_next");
829 env_set("expect_index", "1");
830 env_set("update_env", "1");
831 run_command("saveenv", 0);
832 run_command("reset", 0);
833 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000834
835 //check rescueparty and rollback
Bo Lv72d0e902023-01-02 14:27:34 +0000836 if (rebootmode && (strcmp(rebootmode, "rescueparty") == 0)) {
837 printf("rebootmode is rescueparty, need rollback\n");
838 char *slot;
839
Bo Lv72d0e902023-01-02 14:27:34 +0000840#ifdef CONFIG_FASTBOOT
841 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000842 set_mergestatus_cancel(&message);
843#endif
844
845 slot = env_get("slot-suffixes");
846 if (!slot) {
847 run_command("get_valid_slot", 0);
848 slot = env_get("slot-suffixes");
849 }
850 if (strcmp(slot, "0") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000851 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000852 wrnP("normal mode\n");
853 write_bootloader_back("2", 0);
854 env_set("expect_index", "0");
855 } else {
856 wrnP("gpt or disable user bootloader mode\n");
857 write_bootloader_back("2", 1);
858 env_set("expect_index", "1");
859 }
860 wrnP("back to slot b\n");
861 run_command("set_roll_flag 1", 0);
862 run_command("set_active_slot b", 0);
863 } else if (strcmp(slot, "1") == 0) {
Zhigang Yude5719e2024-03-08 09:14:23 +0000864 if (gpt_flag == 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000865 wrnP("normal mode\n");
866 write_bootloader_back("1", 0);
867 env_set("expect_index", "0");
868 } else {
869 wrnP("gpt or disable user bootloader mode\n");
870 write_bootloader_back("2", 1);
871 env_set("expect_index", "1");
872 }
873 wrnP("back to slot a\n");
874 run_command("set_roll_flag 1", 0);
875 run_command("set_active_slot a", 0);
876 }
877
878 env_set("update_env", "1");
879 env_set("reboot_status", "reboot_next");
880 run_command("saveenv", 0);
881 run_command("reset", 0);
882 }
883
Bo Lv72d0e902023-01-02 14:27:34 +0000884 //get bootloader index
885 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
886 if (bootloaderindex == NULL) {
887 wrnP("can not get bootloader index, so skip secure check\n");
888 return -1;
889 }
Xindong Xu22e8daf2024-03-12 18:08:41 +0800890
Bo Lv72d0e902023-01-02 14:27:34 +0000891 //get expect index
892 expect_index = env_get("expect_index");
893 if (expect_index == NULL) {
894 wrnP("can not get expect index, so skip secure check\n");
895 return -1;
896 }
897
898 wrnP("expect_index is : %s\n", expect_index);
899
900 match_flag = strcmp(bootloaderindex, expect_index);
901
Zhigang Yude5719e2024-03-08 09:14:23 +0000902 rebootstatus = env_get("reboot_status");
Bo Lv72d0e902023-01-02 14:27:34 +0000903
Zhigang Yude5719e2024-03-08 09:14:23 +0000904 //if reboot next need check bootloader rollback
905 if (rebootstatus && !strcmp(rebootstatus, "reboot_next")) {
Bo Lv72d0e902023-01-02 14:27:34 +0000906 wrnP("--secure check reboot_next---\n");
907 //bootloader index, expect == current, no need reboot next
Zhigang Yude5719e2024-03-08 09:14:23 +0000908 if (match_flag != 0) {
909 wrnP("bootloader wrong, start rollback\n");
910 if (gpt_flag == 1) {
911 wrnP("gpt or disable user bootloader mode, write boot1 to boot0\n");
912 write_bootloader_back("2", 1);
Bo Lv72d0e902023-01-02 14:27:34 +0000913#ifdef CONFIG_FASTBOOT
Zhigang Yude5719e2024-03-08 09:14:23 +0000914 struct misc_virtual_ab_message message;
Bo Lv72d0e902023-01-02 14:27:34 +0000915
Zhigang Yude5719e2024-03-08 09:14:23 +0000916 set_mergestatus_cancel(&message);
Bo Lv72d0e902023-01-02 14:27:34 +0000917#endif
Zhigang Yude5719e2024-03-08 09:14:23 +0000918 char *slot;
Bo Lv72d0e902023-01-02 14:27:34 +0000919
Zhigang Yude5719e2024-03-08 09:14:23 +0000920 slot = env_get("slot-suffixes");
921 if (!slot) {
922 run_command("get_valid_slot", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000923 slot = env_get("slot-suffixes");
Bo Lv72d0e902023-01-02 14:27:34 +0000924 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000925 if (strcmp(slot, "0") == 0) {
926 wrnP("back to slot b\n");
927 run_command("set_roll_flag 1", 0);
928 run_command("set_active_slot b", 0);
929 } else if (strcmp(slot, "1") == 0) {
930 wrnP("back to slot a\n");
931 run_command("set_roll_flag 1", 0);
932 run_command("set_active_slot a", 0);
933 }
934 env_set("expect_index", "1");
Bo Lv72d0e902023-01-02 14:27:34 +0000935 } else {
Zhigang Yude5719e2024-03-08 09:14:23 +0000936 write_bootloader_back(bootloaderindex, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000937#ifdef CONFIG_FASTBOOT
938 struct misc_virtual_ab_message message;
939 set_mergestatus_cancel(&message);
940#endif
941 if (strcmp(bootloaderindex, "1") == 0) {
942 wrnP("back to slot a\n");
943 run_command("set_roll_flag 1", 0);
944 run_command("set_active_slot a", 0);
945 } else if (strcmp(bootloaderindex, "2") == 0) {
946 wrnP("back to slot b\n");
947 run_command("set_roll_flag 1", 0);
948 run_command("set_active_slot b", 0);
949 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000950 env_set("expect_index", "0");
Bo Lv72d0e902023-01-02 14:27:34 +0000951 }
Zhigang Yude5719e2024-03-08 09:14:23 +0000952
953 env_set("update_env", "1");
954 env_set("reboot_status", "reboot_next");
Bo Lv72d0e902023-01-02 14:27:34 +0000955 run_command("saveenv", 0);
Zhigang Yude5719e2024-03-08 09:14:23 +0000956 run_command("reset", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000957 return 0;
Zhigang Yude5719e2024-03-08 09:14:23 +0000958 }
Bo Lv72d0e902023-01-02 14:27:34 +0000959 }
960
961 return 0;
962}
963
Zhigang Yude5719e2024-03-08 09:14:23 +0000964static int do_secureboot_check(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
965{
966 char *rebootmode = NULL;
967 int gpt_flag = 0;
968 int ret = -1;
969
970 // set product first to set serial.
971 set_product();
972
973#ifdef CONFIG_MMC_MESON_GX
974 struct mmc *mmc = NULL;
975 //int capacity_boot = 0;
976
977 if (store_get_type() == BOOT_EMMC) {
978 mmc = find_mmc_device(1);
979 if (mmc)
980 ret = aml_gpt_valid(mmc);
981 }
982#endif
983
984 //check is gpt mode
985 if (ret == 0)
986 gpt_flag = 1;
987
988 //unsupport update dt in boothal, update dt in uboot
989 run_command("update_dt;", 0);
990
991 bootloader_wp();
992
993 //set default env before check
994 env_set("recovery_mode", "false");
995
996 //if recovery mode, need disable dv, if factoryreset, need default uboot env
997 aml_recovery();
998
999#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
1000 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
1001
1002 if (*efuse_field.data == 1) {
1003 wrnP("efuse_field.data == 1\n");
1004 env_set("nocs_mode", "true");
1005 gpt_flag = 1;
1006 } else {
1007 wrnP("efuse_field.data != 1\n");
1008 env_set("nocs_mode", "false");
1009 }
1010#endif//#ifdef CONFIG_EFUSE_OBJ_API
1011
1012
1013 run_command("get_rebootmode", 0);
1014 rebootmode = env_get("reboot_mode");
1015 if (!rebootmode) {
1016 wrnP("can not get reboot mode, so skip secure check\n");
1017 return -1;
1018 }
1019 printf("rebootmode is %s\n", rebootmode);
1020
1021 //get boot status
1022 run_command("amlbootsta -p -s", 0);
1023
1024 if (IS_ENABLED(CONFIG_MMC_MESON_GX))
1025 fastboot_step_check(rebootmode, gpt_flag);
1026
1027 if (has_boot_slot == 1)
1028 ab_update_rollback(rebootmode, gpt_flag);
1029 else
1030 non_ab_update(rebootmode);
1031
1032 return 0;
1033}
1034
1035
1036static int do_update_uboot_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1037{
1038 const int write_boot = env_get_ulong("write_boot", 10, 0);
1039 const int update_dts_gpt = env_get_ulong("update_dts_gpt", 10, 0);
1040
1041 //skip update env if need update bootloader
1042 if (write_boot || update_dts_gpt) {
1043 run_command("echo write_boot ${write_boot}, update_dts_gpt ${update_dts_gpt}", 0);
1044 return 0;
1045 }
1046
1047 //default uboot env need before anyone use it
1048 //after factory reset
1049 if (env_get("default_env")) {
1050 printf("factory reset, need default all uboot env.\n");
1051 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1052 }
1053
1054 //after ab update
1055 char *update_env = env_get("update_env");
1056
1057 if (update_env && (strcmp(update_env, "1") == 0)) {
1058 printf("ab mode, default all uboot env\n");
1059 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1060 }
1061
1062 //after recovery update
1063 char *upgrade_step = env_get("upgrade_step");
1064
1065 if (upgrade_step && (strcmp(upgrade_step, "1") == 0)) {
1066 printf("after recovery update, need update uboot env\n");
1067 run_command("defenv_reserv; setenv upgrade_step 2; saveenv;", 0);
1068 }
1069
1070 return 0;
1071}
Bo Lv72d0e902023-01-02 14:27:34 +00001072
1073U_BOOT_CMD_COMPLETE(
1074 amlbootsta, 3, 0, do_get_bootloader_status,
1075 "get bootloader status in env",
1076 "[-p] print bootloader status\n"
1077 "[-s] saveenv after generate bootloader status\n",
1078 var_complete
1079);
1080
1081U_BOOT_CMD_COMPLETE(
1082 amlsecurecheck, 1, 0, do_secureboot_check,
1083 "try bootloader/dtb/recovery secure check",
1084 ""
1085 "",
1086 var_complete
1087);
1088
Zhigang Yude5719e2024-03-08 09:14:23 +00001089U_BOOT_CMD(aml_update_env, 1, 0, do_update_uboot_env,
1090 "aml_update_env",
1091 "\nThis command will update uboot env\n"
1092 "So you can execute command: aml_update_env"
1093);
1094
Bo Lv72d0e902023-01-02 14:27:34 +00001095