bl33: uboot 2023 bringup [1/1]

PD#SWPL-105943

Problem:
uboot 2023 bringup on s4

Solution:
add s4 environment of uboot 2023

Verify:
compile pass on s4_ap222

Change-Id: I9f53a8413551bacf9dddf27e75224728c22cf1e7
Signed-off-by: Bo Lv <bo.lv@amlogic.com>
diff --git a/cmd/amlogic/bootloader_status.c b/cmd/amlogic/bootloader_status.c
new file mode 100644
index 0000000..1f1ca8c
--- /dev/null
+++ b/cmd/amlogic/bootloader_status.c
@@ -0,0 +1,865 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <linux/kernel.h>
+#include <amlogic/aml_efuse.h>
+#include <amlogic/cpu_id.h>
+#include <amlogic/storage.h>
+#include <amlogic/partition_table.h>
+#include <fastboot.h>
+#include <amlogic/emmc_partitions.h>
+#include <asm/amlogic/arch/efuse.h>
+#include <android_image.h>
+#include <amlogic/android_vab.h>
+
+#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
+extern efuse_obj_field_t efuse_field;
+#endif//#ifdef CONFIG_EFUSE_OBJ_API
+
+#ifndef IS_FEAT_BOOT_VERIFY
+#define IS_FEAT_BOOT_VERIFY() 0
+#endif// #ifndef IS_FEAT_BOOT_VERIFY
+int __attribute__((weak)) store_logic_read(const char *name, loff_t off, size_t size, void *buf)
+{ return store_read(name, off, size, buf);}
+
+typedef boot_img_hdr_t boot_img_hdr;
+
+#define debugP(fmt...) //printf("[DbgBootSta]L%d:", __LINE__),printf(fmt)
+#define errorP(fmt...) printf("ErrBootSta(L%d):", __LINE__),printf(fmt)
+#define wrnP(fmt...)   printf("wrn:"fmt)
+#define MsgP(fmt...)   printf("[BootSta]"fmt)
+
+#define BOOTLOADER_OFFSET		512
+#define BOOTLOADER_MAX_SIZE		(4 * 1024 * 1024)
+
+//check SWPL-31296 for details
+static int do_get_bootloader_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	bool printStat = false;
+	bool saveenv   = false;
+	debugP("Initial value for argc=%d\n", argc);
+	while (argc > 1 && **(argv + 1) == '-') {
+		char *arg = *++argv;
+
+		--argc;
+		while (*++arg) {
+			switch (*arg) {
+				case 'p':		/* print */
+					printStat = true;
+					break;
+				case 's':		/* saveenv */
+					saveenv = true;
+					break;
+				default:
+					return CMD_RET_USAGE;
+			}
+		}
+	}
+	debugP("Final value for argc=%d\n", argc);
+	//1,forUpgrade_socType, cpu familyId
+	const cpu_id_t cpuid = get_cpu_id();
+	const int familyId	 = cpuid.family_id;
+	env_set_hex("forUpgrade_socType", familyId);
+
+	//2,forUpgrade_secureBoot
+	const bool secureboot = IS_FEAT_BOOT_VERIFY();
+	env_set("forUpgrade_secureBoot", secureboot ? "true" : "false");
+
+	//3,forUpgrade_robustOta
+	bool supportRobustOta = false;
+	switch (familyId) {
+		case 0x32://sc2
+		case 0x36://t7
+		case 0x37://s4
+		case 0x38://t3
+		case 0x3A://s4d
+			supportRobustOta = true;
+			break;
+		default:
+		{
+			if (familyId > 0x3A) {
+				supportRobustOta = true;
+			}
+		}
+		break;
+	}
+	env_set("forUpgrade_robustOta", supportRobustOta ? "true" : "false");
+
+	//4,forUpgrade_flashType
+	const char* BootDevices[] = {
+		"BOOT_EMMC",		"BOOT_SD",
+		"BOOT_NAND_NFTL",	"BOOT_NAND_MTD",
+		"BOOT_SNAND",		"BOOT_SNOR",
+	};
+	const char* bootDevice = "BOOT_NONE";
+	enum boot_type_e  bootType = store_get_type();
+	int i = 0;
+	for (; i < ARRAY_SIZE(BootDevices); ++i) {
+		if ((1<<i) != bootType) continue;
+		bootDevice = BootDevices[i];
+		break;
+	}
+	env_set("forUpgrade_flashType", bootDevice);
+
+	//5,forUpgrade_bootloaderCopies, how many copies supported
+	int bootCopies = 1;
+	switch (bootType) {
+		case BOOT_EMMC: bootCopies = 3; break;
+		default:break;
+	}
+	env_set_ulong("forUpgrade_bootloaderCopies", bootCopies);
+
+	//6,forUpgrade_bootloaderIndex
+	//for emmc, 0/1/2 is user/boot0/boot1
+	const int bootCpyIndex = store_bootup_bootidx("bootloader");
+	env_set_ulong("forUpgrade_bootloaderIndex", bootCpyIndex);
+
+	//7,get first boot index, for defendkey
+	const int firstBootCpyIndex = store_boot_copy_start();
+	env_set_ulong("forUpgrade_1stBootIndex", firstBootCpyIndex);
+
+	if (printStat) run_command("printenv forUpgrade_socType forUpgrade_secureBoot "
+			" forUpgrade_robustOta forUpgrade_flashType forUpgrade_bootloaderCopies "
+			" forUpgrade_bootloaderIndex forUpgrade_1stBootIndex", 0);
+
+	if (saveenv) run_command("saveenv", 0);
+
+	return CMD_RET_SUCCESS;
+}
+
+static void run_recovery_from_flash(void) {
+	env_set("dolby_status","0");
+	run_command("run init_display", 0);
+	run_command("run storeargs", 0);
+	run_command("get_rebootmode", 0);
+	run_command("if test ${reboot_mode} = quiescent; then "\
+		"setenv bootconfig ${bootconfig} androidboot.quiescent=1; fi;", 0);
+	run_command("if test ${reboot_mode} = recovery_quiescent; then "\
+		"setenv bootconfig ${bootconfig} androidboot.quiescent=1; fi;", 0);
+	run_command("run recovery_from_flash", 0);
+}
+
+static void run_recovery_from_cache(void) {
+
+	char *loadaddr_kernel = env_get("loadaddr_kernel");
+	if (loadaddr_kernel != NULL) {
+		env_set("loadaddr",loadaddr_kernel);
+	} else {
+		env_set("loadaddr","0x01080000");
+	}
+	env_set("dolby_status","0");
+	run_command("run bcb_cmd;", 0);
+	run_command("run init_display", 0);
+	run_command("run storeargs", 0);
+	run_command("get_rebootmode", 0);
+
+	run_command("if test ${reboot_mode} = quiescent; then "\
+		"setenv bootconfig ${bootconfig} androidboot.quiescent=1; fi;", 0);
+	run_command("if test ${reboot_mode} = recovery_quiescent; then "\
+		"setenv bootconfig ${bootconfig} androidboot.quiescent=1; fi;", 0);
+	run_command("if ext4load mmc 1:2 ${dtb_mem_addr} /recovery/dtb.img; then echo cache dtb.img loaded; fi;", 0);
+
+	run_command("if test ${reboot_vendor_boot} = true; then "\
+		"setenv vendor_boot_mode true; fi;", 0);
+
+	run_command("if test ${vendor_boot_mode} = true; then "\
+		"setenv bootargs ${bootargs} ${fs_type} aml_dt=${aml_dt} recovery_part=${recovery_part} recovery_offset=${recovery_offset};"\
+		"imgread kernel ${recovery_part} ${loadaddr} ${recovery_offset};"\
+		"else "\
+		"if ext4load mmc 1:2 ${loadaddr} /recovery/recovery.img; then echo cache recovery.img loaded; fi;"\
+		"fi;", 0);
+
+	env_set("check_result","recovery_succ");
+	env_set("recovery_mode", "true");
+	run_command("bootm ${loadaddr}", 0);
+	env_set("check_result","recovery_fail");
+	env_set("reboot_status","reboot_recovery");
+	run_command("saveenv", 0);
+	run_command("reboot", 0);//need reboot old bootloader
+}
+
+int write_bootloader_back(const char* bootloaderindex, int dstindex) {
+	int iRet = 0;
+	int copy = 0;
+	int ret = -1;
+	unsigned char* buffer = NULL;
+	int capacity_boot = 0;
+
+	if (strcmp(bootloaderindex, "1") == 0) {
+		copy = 1;
+	} else if (strcmp(bootloaderindex, "2") == 0) {
+		copy = 2;
+	} else if (strcmp(bootloaderindex, "0") == 0) {
+		copy = 0;
+	}
+
+#ifdef CONFIG_MMC_MESON_GX
+	struct mmc *mmc = NULL;
+
+	if (store_get_type() == BOOT_EMMC)
+		mmc = find_mmc_device(1);
+
+	if (mmc)
+		capacity_boot = mmc->capacity_boot;
+#endif
+
+	printf("write_bootloader_back_capacity_boot: %x\n", capacity_boot);
+
+	buffer = (unsigned char *)malloc(capacity_boot);
+	if (!buffer)
+	{
+		printf("ERROR! fail to allocate memory ...\n");
+		goto exit;
+	}
+	memset(buffer, 0, capacity_boot);
+	iRet = store_boot_read("bootloader", copy, 0, buffer);
+	if (iRet) {
+		errorP("Fail read bootloader from rsv with sz\n");
+		goto exit;
+	}
+	iRet = store_boot_write("bootloader", dstindex, 0, buffer);
+	if (iRet) {
+		printf("Failed to write bootloader\n");
+		goto exit;
+	} else {
+		ret = 0;
+	}
+
+exit:
+	if (buffer)
+	{
+		free(buffer);
+		//buffer = NULL;
+	}
+	return ret;
+}
+
+//bootloader write protect
+static void bootloader_wp(void)
+{
+#ifdef CONFIG_MMC_MESON_GX
+	if (store_get_type() == BOOT_EMMC) {//emmc device
+		if (IS_FEAT_BOOT_VERIFY()) { //secure boot enable
+			if (BOOTLOADER_MODE_ADVANCE_INIT) { //new arch chip
+				env_set("bootloader_wp", "1");
+			}
+		}
+	}
+#endif
+}
+
+static void aml_recovery(void) {
+	char *mode = NULL;
+	char command[32];
+	char miscbuf[4096] = {0};
+
+	run_command("get_rebootmode", 0);
+
+	//get reboot_mode
+	mode = env_get("reboot_mode");
+	if (mode == NULL) {
+		wrnP("can not get reboot mode, so skip recovery check\n");
+	} else {
+		if ((!strcmp(mode, "factory_reset")) || (!strcmp(mode, "update"))) {
+			env_set("dolby_status","0");
+		}
+	}
+
+#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
+	int ret = 0;
+	extern int boot_info_open_partition(char *miscbuf);
+	ret = boot_info_open_partition(miscbuf);
+	if (ret != 0) {
+		wrnP("open misc partition failed, so skip recovery check");
+		return;
+	}
+#endif
+
+	//if run recovery, need disable dolby
+	memcpy(command, miscbuf, 32);
+	if (!memcmp(command, "boot-recovery", strlen("boot-recovery"))) {
+		env_set("dolby_status","0");
+		return;
+	}
+}
+
+void update_rollback(void)
+{
+	char *slot = NULL;
+	int ret = -1;
+	int gpt_flag = -1;
+
+#ifdef CONFIG_MMC_MESON_GX
+	struct mmc *mmc = NULL;
+
+	if (store_get_type() == BOOT_EMMC)
+		mmc = find_mmc_device(1);
+
+	if (mmc)
+		gpt_flag = aml_gpt_valid(mmc);
+#endif
+	if (gpt_flag == 0)
+		ret = 0;
+
+#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
+	run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+
+	//dis_user_flag = run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+	if (*efuse_field.data == 1)
+		ret = 0;
+#endif//#ifdef CONFIG_EFUSE_OBJ_API
+
+	slot = env_get("slot-suffixes");
+	if (!slot) {
+		run_command("get_valid_slot", 0);
+		slot = env_get("slot-suffixes");
+	}
+	if (strcmp(slot, "0") == 0) {
+		if (ret != 0) {
+			wrnP("normal mode\n");
+			write_bootloader_back("2", 0);
+			env_set("expect_index", "0");
+		} else {
+			wrnP("gpt or disable user bootloader mode\n");
+			write_bootloader_back("2", 1);
+			env_set("expect_index", "1");
+		}
+		wrnP("back to slot b\n");
+		run_command("set_roll_flag 1", 0);
+		run_command("set_active_slot b", 0);
+	} else if (strcmp(slot, "1") == 0) {
+		if (ret != 0) {
+			wrnP("normal mode\n");
+			write_bootloader_back("1", 0);
+			env_set("expect_index", "0");
+		} else {
+			wrnP("gpt or disable user bootloader mode\n");
+			write_bootloader_back("2", 1);
+			env_set("expect_index", "1");
+		}
+		wrnP("back to slot a\n");
+		run_command("set_roll_flag 1", 0);
+		run_command("set_active_slot a", 0);
+	}
+	env_set("update_env", "1");
+	env_set("reboot_status", "reboot_next");
+}
+
+static int write_boot0(void)
+{
+	unsigned char *buffer = NULL;
+	int capacity_boot = 0;
+	int iRet = 0;
+	char partname[32] = {0};
+	char *slot_name = NULL;
+
+#ifdef CONFIG_MMC_MESON_GX
+	struct mmc *mmc = NULL;
+
+	if (store_get_type() == BOOT_EMMC)
+		mmc = find_mmc_device(1);
+
+	if (mmc)
+		capacity_boot = mmc->capacity_boot;
+#endif
+	printf("capacity_boot: 0x%x\n", capacity_boot);
+	buffer = (unsigned char *)malloc(capacity_boot);
+	if (!buffer) {
+		printf("ERROR! fail to allocate memory ...\n");
+		return -1;
+	}
+	memset(buffer, 0, capacity_boot);
+
+	slot_name = env_get("active_slot");
+	if (slot_name && (strcmp(slot_name, "_a") == 0))
+		strcpy((char *)partname, "bootloader_a");
+	else if (slot_name && (strcmp(slot_name, "_b") == 0))
+		strcpy((char *)partname, "bootloader_b");
+
+	iRet = store_logic_read(partname, 0, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
+	if (iRet) {
+		errorP("Fail to read 0x%xB from part[%s] at offset 0\n",
+					BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, partname);
+		return -1;
+	}
+
+	iRet = store_boot_write("bootloader", 0, BOOTLOADER_MAX_SIZE - BOOTLOADER_OFFSET, buffer);
+	if (iRet) {
+		printf("Failed to write boot0\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ *set merge status
+*/
+int set_mergestatus_cancel(struct misc_virtual_ab_message *message)
+{
+        char *partition = "misc";
+        char vab_buf[1024] = {0};
+
+        if (store_read((const char *)partition,
+                SYSTEM_SPACE_OFFSET_IN_MISC, 1024, (unsigned char *)vab_buf) < 0) {
+                printf("failed to store read %s.\n", partition);
+                return -1;
+        }
+
+        memcpy(message, vab_buf, sizeof(struct misc_virtual_ab_message));
+        printf("message.merge_status: %d\n", message->merge_status);
+        if (message->merge_status == SNAPSHOTTED || message->merge_status == MERGING) {
+                message->merge_status = CANCELLED;
+                printf("set message.merge_status CANCELLED\n");
+        }
+        store_write((const char *)partition, SYSTEM_SPACE_OFFSET_IN_MISC, 1024, (unsigned char *)vab_buf);
+        return 0;
+}
+
+static int do_secureboot_check(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
+	int match_flag = 0;
+	char *rebootstatus = NULL;
+	char *checkresult = NULL;
+	char *bootloaderindex = NULL;
+	char *expect_index = NULL;
+	char *robustota = NULL;
+	char *update_env = NULL;
+	char *rebootmode = NULL;
+	int gpt_flag = -1;
+	int ret = -1;
+
+#ifdef CONFIG_MMC_MESON_GX
+	struct mmc *mmc = NULL;
+	//int capacity_boot = 0;
+
+	if (store_get_type() == BOOT_EMMC)
+		mmc = find_mmc_device(1);
+#endif
+	//unsupport update dt in boothal, update dt in uboot
+	run_command("update_dt;", 0);
+
+	bootloader_wp();
+
+	//set default env before check
+	env_set("recovery_mode", "false");
+
+	//if recovery mode, need disable dv, if factoryreset, need default uboot env
+	aml_recovery();
+
+#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
+	run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+
+	if (*efuse_field.data == 1) {
+		wrnP("efuse_field.data == 1\n");
+		env_set("nocs_mode", "true");
+	} else {
+		wrnP("efuse_field.data != 1\n");
+		env_set("nocs_mode", "false");
+	}
+#endif//#ifdef CONFIG_EFUSE_OBJ_API
+
+	char *write_boot = env_get("write_boot");
+
+	if (!strcmp(write_boot, "1")) {
+		printf("need to write boot0\n");
+		if (write_boot0()) {
+			printf("write boot0 fail, need to rollback!\n");
+			update_rollback();
+		} else {
+			printf("write boot0 success, need to reset!\n");
+		}
+
+		env_set("write_boot", "0");
+		env_set("reboot_status", "reboot_next");
+		env_set("expect_index", "1");
+		env_set("update_env", "1");
+		run_command("saveenv", 0);
+		run_command("reset", 0);
+	}
+	run_command("get_rebootmode", 0);
+	rebootmode = env_get("reboot_mode");
+	if (!rebootmode) {
+		wrnP("can not get reboot mode, so skip secure check\n");
+		return -1;
+	}
+	printf("rebootmode is %s\n", rebootmode);
+	if (rebootmode && (strcmp(rebootmode, "rescueparty") == 0)) {
+		printf("rebootmode is rescueparty, need rollback\n");
+		char *slot;
+
+#ifdef CONFIG_MMC_MESON_GX
+		if (mmc)
+			gpt_flag = aml_gpt_valid(mmc);
+#endif
+		if (gpt_flag == 0)
+			ret = 0;
+
+#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
+		run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+
+		//dis_user_flag = run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+		if (*efuse_field.data == 1)
+			ret = 0;
+#endif//#ifdef CONFIG_EFUSE_OBJ_API
+
+#ifdef CONFIG_FASTBOOT
+		struct misc_virtual_ab_message message;
+
+		set_mergestatus_cancel(&message);
+#endif
+
+		slot = env_get("slot-suffixes");
+		if (!slot) {
+			run_command("get_valid_slot", 0);
+			slot = env_get("slot-suffixes");
+		}
+		if (strcmp(slot, "0") == 0) {
+			if (ret != 0) {
+				wrnP("normal mode\n");
+				write_bootloader_back("2", 0);
+				env_set("expect_index", "0");
+			} else {
+				wrnP("gpt or disable user bootloader mode\n");
+				write_bootloader_back("2", 1);
+				env_set("expect_index", "1");
+			}
+			wrnP("back to slot b\n");
+			run_command("set_roll_flag 1", 0);
+			run_command("set_active_slot b", 0);
+		} else if (strcmp(slot, "1") == 0) {
+			if (ret != 0) {
+				wrnP("normal mode\n");
+				write_bootloader_back("1", 0);
+				env_set("expect_index", "0");
+			} else {
+				wrnP("gpt or disable user bootloader mode\n");
+				write_bootloader_back("2", 1);
+				env_set("expect_index", "1");
+			}
+			wrnP("back to slot a\n");
+			run_command("set_roll_flag 1", 0);
+			run_command("set_active_slot a", 0);
+		}
+
+		env_set("update_env", "1");
+		env_set("reboot_status", "reboot_next");
+		run_command("saveenv", 0);
+		run_command("reset", 0);
+	}
+
+	//check_result init
+	checkresult = env_get("check_result");
+	if (checkresult == NULL) {
+		env_set("check_result","succ");
+	}
+
+	//reboot_status init
+	rebootstatus = env_get("reboot_status");
+	if (rebootstatus == NULL) {
+		env_set("reboot_status","reboot_init");
+		rebootstatus = env_get("reboot_status");
+	}
+
+	if (rebootstatus == NULL) {
+		printf("rebootstatus is NULL, skip check\n");
+		return -1;
+	}
+
+	//check reboot_end
+	if (!strcmp(rebootstatus, "reboot_end")) {
+		env_set("reboot_status","reboot_init");
+		run_command("saveenv", 0);
+	}
+
+	//get boot status
+	run_command("amlbootsta -p -s", 0);
+
+	//get forUpgrade_robustOta and check if support robustota
+	robustota = env_get("forUpgrade_robustOta");
+	if ((robustota == NULL) || !strcmp(robustota, "false")) {
+		return -1;
+	}
+
+	//get bootloader index
+	bootloaderindex = env_get("forUpgrade_bootloaderIndex");
+	if (bootloaderindex == NULL) {
+		wrnP("can not get bootloader index, so skip secure check\n");
+		return -1;
+	}
+/*
+#ifdef CONFIG_MMC_MESON_GX
+	if (mmc) {
+		struct blk_desc *dev_desc = mmc_get_blk_desc(mmc);
+
+		if (dev_desc && !strcmp(bootloaderindex, "0")) {
+			unsigned char *buffer = NULL;
+			capacity_boot = mmc->capacity_boot;
+
+			printf("do_secureboot_check_capacity_boot: %x\n", capacity_boot);
+
+			buffer = (unsigned char *)malloc(capacity_boot);
+			if (buffer) {
+				memset(buffer, 0, capacity_boot);
+				ret = store_boot_read("bootloader", 0, 0, buffer);
+				if (ret == 0) {
+					wrnP("--read bootloader ok, check valib gpt---\n");
+					if (is_valid_gpt_buf(dev_desc, buffer + 0x3DFE00)) {
+						printf("no gpt partition table\n");
+					} else {
+						printf("find gpt partition table, update it\n"
+							"and write bootloader to boot0/boot1\n");
+						ret = write_mbr_and_gpt_partitions(dev_desc,
+								buffer + 0x3DFE00);
+						if (ret == 0) {
+							printf("write gpt ok, reset\n");
+							write_bootloader_back(bootloaderindex, 1);
+							write_bootloader_back(bootloaderindex, 2);
+							run_command("reboot bootloader", 0);
+						}
+					}
+				}
+				free(buffer);
+			}
+		}
+	}
+#endif
+*/
+
+	//no secure check need
+	if (!strcmp(rebootstatus, "reboot_init")) {
+		printf("rebootstatus is reboot_init, skip check\n");
+		return -1;
+	}
+
+	//get expect index
+	expect_index = env_get("expect_index");
+	if (expect_index == NULL) {
+		wrnP("can not get expect index, so skip secure check\n");
+		return -1;
+	}
+
+	wrnP("expect_index is : %s\n", expect_index);
+
+	match_flag = strcmp(bootloaderindex, expect_index);
+
+	//ignore reboot next check if power off during reboot next to finish
+	if (rebootmode && (strcmp(rebootmode, "cold_boot") == 0)) {
+		if (!strcmp(rebootstatus, "reboot_finish")) {
+			match_flag = 0;
+		}
+	}
+
+
+	//first reboot, command from recovery, need reboot next
+	if (!strcmp(rebootstatus,"reboot_next")) {
+		wrnP("--secure check reboot_next---\n");
+		//bootloader index, expect == current, no need reboot next
+		if (match_flag == 0) {
+			wrnP("current index is expect, no need reboot next, run cache recovery\n");
+			if (has_boot_slot == 1) {
+				wrnP("ab mode\n");
+				update_env = env_get("update_env");
+				if (!update_env) {
+					errorP("can not get update_env\n");
+					return -1;
+				}
+				if (strcmp(update_env, "1") == 0) {
+					printf("ab mode, default all uboot env\n");
+					run_command("defenv_reserv;saveenv;", 0);
+					env_set("update_env","0");
+				}
+			} else {
+				run_recovery_from_cache();
+				return 0;
+			}
+		} else {
+			wrnP("now ready start reboot next\n");
+			if (has_boot_slot == 1) {
+#ifdef CONFIG_MMC_MESON_GX
+				if (mmc != NULL)
+					gpt_flag = aml_gpt_valid(mmc);
+#endif
+				if (gpt_flag == 0)
+					ret = 0;
+
+#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
+				run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+
+				if (*efuse_field.data == 1)
+					ret = 0;
+#endif//#ifdef CONFIG_EFUSE_OBJ_API
+				if (ret == 0) {
+					wrnP("gpt or disable user bootloader mode, write boot1 to boot0\n");
+					write_bootloader_back("2", 1);
+#ifdef CONFIG_FASTBOOT
+					struct misc_virtual_ab_message message;
+
+					set_mergestatus_cancel(&message);
+#endif
+					char *slot;
+
+					slot = env_get("slot-suffixes");
+					if (!slot) {
+						run_command("get_valid_slot", 0);
+						slot = env_get("slot-suffixes");
+					}
+					if (strcmp(slot, "0") == 0) {
+						wrnP("back to slot b\n");
+						run_command("set_roll_flag 1", 0);
+						run_command("set_active_slot b", 0);
+					} else if (strcmp(slot, "1") == 0) {
+						wrnP("back to slot a\n");
+						run_command("set_roll_flag 1", 0);
+						run_command("set_active_slot a", 0);
+					}
+					env_set("expect_index", "1");
+				} else {
+					write_bootloader_back(bootloaderindex, 0);
+#ifdef CONFIG_FASTBOOT
+					struct misc_virtual_ab_message message;
+					set_mergestatus_cancel(&message);
+#endif
+					if (strcmp(bootloaderindex, "1") == 0) {
+						wrnP("back to slot a\n");
+						run_command("set_roll_flag 1", 0);
+						run_command("set_active_slot a", 0);
+					} else if (strcmp(bootloaderindex, "2") == 0) {
+						wrnP("back to slot b\n");
+						run_command("set_roll_flag 1", 0);
+						run_command("set_active_slot b", 0);
+					}
+					env_set("expect_index", "0");
+				}
+
+				env_set("update_env", "1");
+				env_set("reboot_status", "reboot_next");
+				run_command("saveenv", 0);
+				run_command("reset", 0);
+			} else {
+				env_set("reboot_status","reboot_finish");
+				run_command("saveenv", 0);
+				run_command("get_rebootmode", 0);
+				run_command("if test ${reboot_mode} = quiescent; then reboot next,quiescent; else reboot next; fi;", 0);
+			}
+			return 0;
+		}
+	} else if (!strcmp(rebootstatus,"reboot_finish")) {//second reboot, reboot next from uboot
+		wrnP("--secure check reboot_finish---\n");
+		env_set("reboot_status","reboot_end");
+		run_command("saveenv", 0);
+
+		if (match_flag == 0) {
+			wrnP("reboot next succ, bootloader secure check pass......\n");
+			if (has_boot_slot == 1) {
+				printf("ab mode, default all uboot env\n");
+				update_env = env_get("update_env");
+				if (!update_env) {
+					errorP("can not get update_env\n");
+					return -1;
+				}
+				if (strcmp(update_env, "1") == 0) {
+					printf("ab mode, default all uboot env\n");
+					run_command("defenv_reserv;saveenv;", 0);
+					env_set("update_env","0");
+
+					if (strcmp(bootloaderindex, "2") == 0) {
+						wrnP("rom always boot as boot0--> boot1\n");
+						wrnP("So if boot1 is ok, write it to boot0\n");
+						run_command("copy_slot_bootable 2 1", 0);
+					}
+					run_command("saveenv", 0);
+				}
+			} else {
+				run_recovery_from_cache();
+				return 0;
+			}
+		} else {
+			//bootloader check failed, run recovery show error
+			wrnP("reboot next fail, bootloader secure check fail(curr:%s, expect:%s)......\n",bootloaderindex, expect_index);
+			env_set("check_result","bootloader_fail");
+			run_command("saveenv", 0);
+			if (has_boot_slot == 1) {
+				wrnP("ab mode\n");
+#ifdef CONFIG_FASTBOOT
+				struct misc_virtual_ab_message message;
+				set_mergestatus_cancel(&message);
+#endif
+				if (strcmp(bootloaderindex, "1") == 0) {
+					wrnP("back to slot a\n");
+					run_command("set_roll_flag 1", 0);
+					run_command("set_active_slot a", 0);
+				} else if (strcmp(bootloaderindex, "2") == 0) {
+					wrnP("back to slot b\n");
+					run_command("set_roll_flag 1", 0);
+					run_command("set_active_slot b", 0);
+				}
+
+#ifdef CONFIG_MMC_MESON_GX
+				if (mmc != NULL)
+					gpt_flag = aml_gpt_valid(mmc);
+#endif
+
+				if (gpt_flag == 0)
+					ret = 0;
+
+#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
+				run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
+
+				if (*efuse_field.data == 1)
+					ret = 0;
+#endif//#ifdef CONFIG_EFUSE_OBJ_API
+
+				if (ret == 0) {
+					wrnP("gpt or disable user bootloader mode\n");
+					env_set("update_env","0");
+					env_set("reboot_status","reboot_init");
+					run_command("saveenv", 0);
+				} else {
+					write_bootloader_back(bootloaderindex, 0);
+					env_set("update_env","1");
+					env_set("reboot_status","reboot_next");
+					env_set("expect_index","0");
+					run_command("saveenv", 0);
+					run_command("reset", 0);
+				}
+
+			} else {
+				run_recovery_from_flash();
+				return 0;
+			}
+		}
+	} else if (!strcmp(rebootstatus,"reboot_recovery")) {
+			//recovery check failed, run recovery show error
+			wrnP("--secure check reboot_recovery---\n");
+			env_set("reboot_status","reboot_end");
+			run_command("saveenv", 0);
+			run_recovery_from_flash();
+			return 0;
+	} else {
+		env_set("check_result","succ");
+	}
+
+	return 0;
+}
+
+
+U_BOOT_CMD_COMPLETE(
+	amlbootsta, 3, 0,	do_get_bootloader_status,
+	"get bootloader status in env",
+	"[-p] print bootloader status\n"
+	"[-s] saveenv after generate bootloader status\n",
+	var_complete
+);
+
+U_BOOT_CMD_COMPLETE(
+	amlsecurecheck, 1, 0,	do_secureboot_check,
+	"try bootloader/dtb/recovery secure check",
+	""
+	"",
+	var_complete
+);
+
+