MLK-18591-3 android: Add FSL android fastboot support
authorYe Li <ye.li@nxp.com>
Wed, 15 May 2019 05:49:31 +0000 (22:49 -0700)
committerYe Li <ye.li@nxp.com>
Thu, 29 Apr 2021 07:56:08 +0000 (00:56 -0700)
Porting the FSL android fastboot features from imx u-boot v2018.03 to
support all SoCs: imx6/imx7/imx7ulp/imx8/imx8m.

The UUU commands like UCmd and ACmd are also added. Users need set
CONFIG_FASTBOOT_UUU_SUPPORT=y to enable the feature.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
(cherry picked from commit 65120b06a7f750b9b1a6e0db3d2082cc7088d5a8)
(cherry picked from commit 9b149c2a28829fe7017f83981d634157bc31cc94)
(cherry picked from commit 9f99e9de1d37e9f6c02c1b27348ea3dcdab94569)
(cherry picked from commit 6ae1c043431a4987f563026b179b33945a5880ee)

46 files changed:
arch/arm/include/asm/arch-mx6/sys_proto.h
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/cpu.c
arch/arm/mach-imx/imx8m/soc.c
arch/arm/mach-imx/mx6/soc.c
arch/arm/mach-imx/mx7/soc.c
arch/arm/mach-imx/mx7ulp/soc.c
board/freescale/common/Makefile
board/freescale/common/recovery_keypad.c [new file with mode: 0644]
board/freescale/common/recovery_keypad.h [new file with mode: 0644]
board/freescale/mx6sabreauto/mx6sabreauto.c
board/freescale/mx6sabresd/mx6sabresd.c
cmd/fastboot.c
cmd/read.c
common/board_r.c
common/image-android.c
disk/part_efi.c
drivers/fastboot/Kconfig
drivers/fastboot/Makefile
drivers/fastboot/fb_common.c
drivers/fastboot/fb_fsl/Makefile [new file with mode: 0644]
drivers/fastboot/fb_fsl/bcb.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/bcb.h [new file with mode: 0644]
drivers/fastboot/fb_fsl/command.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fastboot_lock_unlock.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fastboot_lock_unlock.h [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_boot.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_command.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_common.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_common.h [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_dev.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_getvar.c [new file with mode: 0644]
drivers/fastboot/fb_fsl/fb_fsl_partitions.c [new file with mode: 0644]
drivers/usb/gadget/f_fastboot.c
include/android_image.h
include/command.h
include/fastboot.h
include/fb_fsl.h [new file with mode: 0644]
include/image.h
include/init.h
include/mmc.h
include/part.h
include/recovery.h [new file with mode: 0644]
lib/avb/fsl/fsl_avb.c
lib/avb/fsl/fsl_bootctl.c
scripts/config_whitelist.txt

index 688aabf..75ba387 100644 (file)
@@ -39,6 +39,7 @@ static inline void iomuxc_set_rgmii_io_voltage(int io_vol)
 }
 
 void set_wdog_reset(struct wdog_regs *wdog);
+enum boot_device get_boot_device(void);
 
 #ifdef CONFIG_LDO_BYPASS_CHECK
 int check_ldo_bypass(void);
index be95f1b..af6ef6e 100644 (file)
@@ -147,6 +147,12 @@ config NXP_BOARD_REVISION
          stored in the fuses. Select this option if you want to be able to
          retrieve the board revision information.
 
+config FLASH_MCUFIRMWARE_SUPPORT
+       bool "Enable mcu firmware flash support"
+       depends on ARCH_MX7ULP || ARCH_IMX8M
+       help
+         This enables the mcu firmware flash support for some SOCs.
+
 config DDRMC_VF610_CALIBRATION
        bool "Enable DDRMC (DDR3) on-chip calibration"
        depends on ARCH_VF610
index 08e9ca0..6c6ae78 100644 (file)
@@ -44,7 +44,10 @@ u32 get_imx_reset_cause(void)
        if (reset_cause == -1) {
                reset_cause = readl(&src_regs->srsr);
 /* preserve the value for U-Boot proper */
-#if !defined(CONFIG_SPL_BUILD)
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_ANDROID_BOOT_IMAGE)
+               /* We will read the ssrs states later for android so we don't
+                * clear the states here.
+                */
                writel(reset_cause, &src_regs->srsr);
 #endif
        }
@@ -95,6 +98,17 @@ static char *get_reset_cause(void)
                return "unknown reset";
        }
 }
+
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+void get_reboot_reason(char *ret)
+{
+       struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+
+       strcpy(ret, (const char *)get_reset_cause());
+       /* clear the srsr here, its state has been recorded in reset_cause */
+       writel(reset_cause, &src_regs->srsr);
+}
+#endif
 #endif
 
 #if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_SPL_BUILD)
index 01e65da..4b6715c 100644 (file)
 #include <imx_sip.h>
 #include <linux/arm-smccc.h>
 #include <linux/bitops.h>
+#include <asm/setup.h>
 #ifdef CONFIG_IMX_SEC_INIT
 #include <fsl_caam.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined(CONFIG_IMX_HAB)
+#if defined(CONFIG_IMX_HAB) || defined(CONFIG_AVB_ATX)
 struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
        .bank = 1,
        .word = 3,
@@ -493,6 +494,10 @@ int arch_cpu_init(void)
        /* Secure init function such RNG */
        imx_sec_init();
 #endif
+#if defined(CONFIG_ANDROID_SUPPORT)
+       /* Enable RTC */
+       writel(0x21, 0x30370038);
+#endif
 
        if (is_imx8mq()) {
                clock_enable(CCGR_OCOTP, 1);
@@ -555,6 +560,18 @@ bool is_usb_boot(void)
 {
        return get_boot_device() == USB_BOOT;
 }
+#ifdef CONFIG_SERIAL_TAG
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[0];
+       struct fuse_bank0_regs *fuse =
+               (struct fuse_bank0_regs *)bank->fuse_regs;
+
+       serialnr->low = fuse->uid_low;
+       serialnr->high = fuse->uid_high;
+}
+#endif
 
 #ifdef CONFIG_OF_SYSTEM_SETUP
 bool check_fdt_new_path(void *blob)
index 7e28a55..c0b2ece 100644 (file)
@@ -26,6 +26,7 @@
 #include <dm.h>
 #include <imx_thermal.h>
 #include <mmc.h>
+#include <asm/setup.h>
 #ifdef CONFIG_IMX_SEC_INIT
 #include <fsl_caam.h>
 #endif
@@ -854,6 +855,10 @@ void s_init(void)
        u32 mask528;
        u32 reg, periph1, periph2;
 
+#if defined(CONFIG_ANDROID_SUPPORT)
+        /* Enable RTC */
+        writel(0x21, 0x020cc038);
+#endif
        if (is_mx6sx() || is_mx6ul() || is_mx6ull() || is_mx6sll())
                return;
 
index 19e11e5..3e00de6 100644 (file)
@@ -130,7 +130,7 @@ static void isolate_resource(void)
 }
 #endif
 
-#if defined(CONFIG_IMX_HAB)
+#if defined(CONFIG_IMX_HAB) || defined(CONFIG_AVB_ATX)
 struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
        .bank = 1,
        .word = 3,
@@ -443,6 +443,10 @@ void s_init(void)
        /* clock configuration. */
        clock_init();
 
+#if defined(CONFIG_ANDROID_SUPPORT)
+        /* Enable RTC */
+        writel(0x21, 0x30370038);
+#endif
        return;
 }
 
index 253d8f2..63002e4 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/mach-imx/boot_mode.h>
 #include <asm/mach-imx/hab.h>
 #include <linux/bitops.h>
+#include <asm/setup.h>
 #ifdef CONFIG_IMX_SEC_INIT
 #include <fsl_caam.h>
 #endif
@@ -250,6 +251,11 @@ void s_init(void)
        if (soc_rev() < CHIP_REV_2_0) {
                /* enable dumb pmic */
                writel((readl(SNVS_LP_LPCR) | SNVS_LPCR_DPEN), SNVS_LP_LPCR);
+
+#if defined(CONFIG_ANDROID_SUPPORT)
+               /* Enable RTC */
+               writel((readl(SNVS_LP_LPCR) | SNVS_LPCR_SRTC_ENV), SNVS_LP_LPCR);
+#endif
        }
 
 #if defined(CONFIG_LDO_ENABLED_MODE)
@@ -343,7 +349,12 @@ static char *get_reset_cause(char *ret)
 
        srs = readl(reg_srs);
        cause1 = readl(reg_ssrs);
+#ifndef CONFIG_ANDROID_BOOT_IMAGE
+       /* We will read the ssrs states later for android so we don't
+        * clear the states here.
+        */
        writel(cause1, reg_ssrs);
+#endif
 
        reset_cause = cause1;
 
@@ -383,6 +394,17 @@ static char *get_reset_cause(char *ret)
        return ret;
 }
 
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+void get_reboot_reason(char *ret)
+{
+       u32 *reg_ssrs = (u32 *)(SRC_BASE_ADDR + 0x28);
+
+       get_reset_cause(ret);
+       /* clear the ssrs here, its state has been recorded in reset_cause */
+       writel(reset_cause, reg_ssrs);
+}
+#endif
+
 void arch_preboot_os(void)
 {
        scg_disable_pll_pfd(SCG_APLL_PFD1_CLK);
@@ -437,3 +459,18 @@ enum boot_device get_boot_device(void)
 
        return boot_dev;
 }
+
+#ifdef CONFIG_FSL_FASTBOOT
+#ifdef CONFIG_SERIAL_TAG
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[1];
+       struct fuse_bank1_regs *fuse =
+               (struct fuse_bank1_regs *)bank->fuse_regs;
+       serialnr->low = (fuse->cfg0 & 0xFFFF) + ((fuse->cfg1 & 0xFFFF) << 16);
+       serialnr->high = (fuse->cfg2 & 0xFFFF) + ((fuse->cfg3 & 0xFFFF) << 16);
+}
+#endif /*CONFIG_SERIAL_TAG*/
+#endif /*CONFIG_FSL_FASTBOOT*/
index 26085e5..a8efada 100644 (file)
@@ -63,6 +63,9 @@ obj-$(CONFIG_MXC_EPDC)                += epdc_setup.o
 ifneq (,$(filter $(SOC), mx25 mx31 mx35 mx5 mx6 mx7 mx7ulp imx8 imx8m vf610))
 obj-y                          += mmc.o
 endif
+ifdef CONFIG_FSL_FASTBOOT
+obj-${CONFIG_ANDROID_RECOVERY} += recovery_keypad.o
+endif
 
 obj-$(CONFIG_LS102XA_STREAM_ID)        += ls102xa_stream_id.o
 
diff --git a/board/freescale/common/recovery_keypad.c b/board/freescale/common/recovery_keypad.c
new file mode 100644 (file)
index 0000000..2f5a58a
--- /dev/null
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier:    GPL-2.0+
+/*
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ *
+ */
+#include <common.h>
+#include <malloc.h>
+#include <recovery.h>
+#ifdef CONFIG_MXC_KPD
+#include <mxc_keyb.h>
+#endif
+#include <asm/mach-imx/boot_mode.h>
+
+#ifdef CONFIG_MXC_KPD
+#define PRESSED_VOL_DOWN       0x01
+#define PRESSED_POWER      0x02
+#define RECOVERY_KEY_MASK (PRESSED_VOL_DOWN | PRESSED_POWER)
+
+inline int test_key(int value, struct kpp_key_info *ki)
+{
+       return (ki->val == value) && (ki->evt == KDepress);
+}
+
+int is_recovery_keypad_pressing(void)
+{
+       struct kpp_key_info *key_info = NULL;
+       int state = 0, keys, i;
+
+       int ret = 0;
+
+       mxc_kpp_init();
+       /* due to glitch suppression circuit,
+          wait sometime to let all keys scanned. */
+       udelay(1000);
+       keys = mxc_kpp_getc(&key_info);
+
+       printf("Detecting VOL_DOWN+POWER key for recovery(%d:%d) ...\n",
+               keys, keys ? key_info->val : 0);
+       if (keys > 1) {
+               for (i = 0; i < keys; i++) {
+                       if (test_key(CONFIG_POWER_KEY, &key_info[i]))
+                               state |= PRESSED_POWER;
+                       else if (test_key(CONFIG_VOL_DOWN_KEY, &key_info[i]))
+                               state |= PRESSED_VOL_DOWN;
+               }
+       }
+       if ((state & RECOVERY_KEY_MASK) == RECOVERY_KEY_MASK)
+               ret = 1;
+       if (key_info)
+               free(key_info);
+       return ret;
+}
+#else
+/* If not using mxc keypad, currently we will detect power key on board */
+int is_recovery_keypad_pressing(void)
+{
+       return 0;
+}
+#endif
diff --git a/board/freescale/common/recovery_keypad.h b/board/freescale/common/recovery_keypad.h
new file mode 100644 (file)
index 0000000..9adf224
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier:    GPL-2.0+
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ *
+ */
+
+#ifndef __RECOVERY_KEYPAD_H_
+#define __RECOVERY_KEYPAD_H_
+
+int is_recovery_keypad_pressing(void);
+
+#endif
index fe5fa8a..a71303e 100644 (file)
@@ -41,7 +41,7 @@
 #include <asm/mach-imx/sata.h>
 #endif
 #ifdef CONFIG_FSL_FASTBOOT
-#include <fsl_fastboot.h>
+#include <fb_fsl.h>
 #ifdef CONFIG_ANDROID_RECOVERY
 #include <recovery.h>
 #endif
index bc0266d..d7e56e4 100644 (file)
@@ -46,7 +46,7 @@
 #include <asm/mach-imx/sata.h>
 #endif
 #ifdef CONFIG_FSL_FASTBOOT
-#include <fsl_fastboot.h>
+#include <fb_fsl.h>
 #ifdef CONFIG_ANDROID_RECOVERY
 #include <recovery.h>
 #endif
index ad5c064..a547645 100644 (file)
@@ -52,6 +52,9 @@ static int do_fastboot_usb(int argc, char *const argv[],
                pr_err("Error: Wrong USB controller index format\n");
                return CMD_RET_FAILURE;
        }
+#ifdef CONFIG_FASTBOOT_USB_DEV
+       controller_index = CONFIG_FASTBOOT_USB_DEV;
+#endif
 
        ret = usb_gadget_initialize(controller_index);
        if (ret) {
index 34f53f9..daea30a 100644 (file)
@@ -12,7 +12,7 @@
 #include <command.h>
 #include <part.h>
 
-int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+int do_raw_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        char *ep;
        struct blk_desc *dev_desc = NULL;
@@ -75,7 +75,7 @@ int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 }
 
 U_BOOT_CMD(
-       read,   6,      0,      do_read,
+       read,   6,      0,      do_raw_read,
        "Load binary data from a partition",
        "<interface> <dev[:part]> addr blk# cnt"
 );
index 2fde0a1..904cc99 100644 (file)
@@ -77,6 +77,9 @@
 #ifdef CONFIG_EFI_SETUP_EARLY
 #include <efi_loader.h>
 #endif
+#ifdef CONFIG_FSL_FASTBOOT
+#include <fb_fsl.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -586,6 +589,20 @@ static int initr_avbkey(void)
 }
 #endif
 
+#ifdef CONFIG_FSL_FASTBOOT
+static int initr_fastboot_setup(void)
+{
+       fastboot_setup();
+       return 0;
+}
+
+static int initr_check_fastboot(void)
+{
+       fastboot_run_bootmode();
+       return 0;
+}
+#endif
+
 static int run_main_loop(void)
 {
 #ifdef CONFIG_SANDBOX
@@ -767,6 +784,9 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_BOARD_LATE_INIT
        board_late_init,
 #endif
+#ifdef CONFIG_FSL_FASTBOOT
+       initr_fastboot_setup,
+#endif
 #if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
        INIT_FUNC_WATCHDOG_RESET
        initr_scsi,
@@ -808,6 +828,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #if defined(AVB_RPMB) && !defined(CONFIG_SPL)
        initr_avbkey,
+#endif
+#ifdef CONFIG_FSL_FASTBOOT
+       initr_check_fastboot,
 #endif
        run_main_loop,
 };
index d07b0e0..048eac7 100644 (file)
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
  */
 
 #include <common.h>
 #include <asm/unaligned.h>
 #include <mapmem.h>
 #include <linux/libfdt.h>
+#include <asm/bootm.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <fb_fsl.h>
+#include <asm/setup.h>
+#include <dm.h>
+#include <init.h>
 
 #define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR      0x10008000
 
@@ -62,6 +72,7 @@ static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr)
 int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
                             ulong *os_data, ulong *os_len)
 {
+       extern boot_metric metrics;
        u32 kernel_addr = android_image_get_kernel_addr(hdr);
        const struct image_header *ihdr = (const struct image_header *)
                ((uintptr_t)hdr + hdr->page_size);
@@ -79,31 +90,188 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
        printf("Kernel load addr 0x%08x size %u KiB\n",
               kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
 
-       int len = 0;
-       if (*hdr->cmdline) {
-               printf("Kernel command line: %s\n", hdr->cmdline);
-               len += strlen(hdr->cmdline);
+       char newbootargs[512] = {0};
+       char commandline[2048] = {0};
+       int offset;
+       char *bootargs = env_get("bootargs");
+
+       if (bootargs) {
+               if (strlen(bootargs) + 1 > sizeof(commandline)) {
+                       printf("bootargs is too long!\n");
+                       return -1;
+               }
+               else
+                       strncpy(commandline, bootargs, sizeof(commandline) - 1);
+       } else {
+               offset = fdt_path_offset(gd->fdt_blob, "/chosen");
+               if (offset > 0) {
+                       bootargs = (char *)fdt_getprop(gd->fdt_blob, offset,
+                                                       "bootargs", NULL);
+                       if (bootargs)
+                               sprintf(commandline, "%s ", bootargs);
+               }
+
+               if (*hdr->cmdline) {
+                       if (strlen(hdr->cmdline) + 1 >
+                               sizeof(commandline) - strlen(commandline)) {
+                               printf("cmdline in bootimg is too long!\n");
+                               return -1;
+                       }
+                       else
+                               strncat(commandline, hdr->cmdline, sizeof(commandline) - strlen(commandline));
+               }
        }
 
-       char *bootargs = env_get("bootargs");
-       if (bootargs)
-               len += strlen(bootargs);
+       /* Add 'bootargs_ram_capacity' to hold the parameters based on different ram capacity */
+       char *bootargs_ram_capacity = env_get("bootargs_ram_capacity");
+       if (bootargs_ram_capacity) {
+               strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+               strncat(commandline, bootargs_ram_capacity,
+                       sizeof(commandline) - strlen(commandline));
+       }
+
+#ifdef CONFIG_SERIAL_TAG
+       struct tag_serialnr serialnr;
+       get_board_serial(&serialnr);
+
+       sprintf(newbootargs,
+                                       " androidboot.serialno=%08x%08x",
+                                       serialnr.high,
+                                       serialnr.low);
+       strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+
+       char bd_addr[16]={0};
+       sprintf(bd_addr,
+               "%08x%08x",
+               serialnr.high,
+               serialnr.low);
+       sprintf(newbootargs,
+               " androidboot.btmacaddr=%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
+               bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],bd_addr[5],
+               bd_addr[6],bd_addr[7],bd_addr[8],bd_addr[9],bd_addr[10],bd_addr[11]);
+       strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+#endif
 
-       char *newbootargs = malloc(len + 2);
-       if (!newbootargs) {
-               puts("Error: malloc in android_image_get_kernel failed!\n");
-               return -ENOMEM;
+       /* append soc type into bootargs */
+       char *soc_type = env_get("soc_type");
+       if (soc_type) {
+               sprintf(newbootargs,
+                       " androidboot.soc_type=%s",
+                       soc_type);
+               strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
        }
-       *newbootargs = '\0';
 
-       if (bootargs) {
-               strcpy(newbootargs, bootargs);
-               strcat(newbootargs, " ");
+       char *storage_type = env_get("storage_type");
+       if (storage_type) {
+               sprintf(newbootargs,
+                       " androidboot.storage_type=%s",
+                       storage_type);
+               strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+       } else {
+               int bootdev = get_boot_device();
+               if (bootdev == SD1_BOOT || bootdev == SD2_BOOT ||
+                       bootdev == SD3_BOOT || bootdev == SD4_BOOT) {
+                       sprintf(newbootargs,
+                               " androidboot.storage_type=sd");
+               } else if (bootdev == MMC1_BOOT || bootdev == MMC2_BOOT ||
+                       bootdev == MMC3_BOOT || bootdev == MMC4_BOOT) {
+                       sprintf(newbootargs,
+                               " androidboot.storage_type=emmc");
+               } else if (bootdev == NAND_BOOT) {
+                       sprintf(newbootargs,
+                               " androidboot.storage_type=nand");
+               } else
+                       printf("boot device type is incorrect.\n");
+               strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+               if (bootloader_gpt_overlay()) {
+                       sprintf(newbootargs, " gpt");
+                       strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+               }
        }
-       if (*hdr->cmdline)
-               strcat(newbootargs, hdr->cmdline);
 
-       env_set("bootargs", newbootargs);
+       /* boot metric variables */
+       metrics.ble_1 = get_timer(0);
+       sprintf(newbootargs,
+               " androidboot.boottime=1BLL:%d,1BLE:%d,KL:%d,KD:%d,AVB:%d,ODT:%d,SW:%d",
+               metrics.bll_1, metrics.ble_1, metrics.kl, metrics.kd, metrics.avb,
+               metrics.odt, metrics.sw);
+       strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+
+#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \
+       defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M)
+       char cause[18];
+
+       memset(cause, '\0', sizeof(cause));
+       get_reboot_reason(cause);
+       if (strstr(cause, "POR"))
+               sprintf(newbootargs," androidboot.bootreason=cold,powerkey");
+       else if (strstr(cause, "WDOG") || strstr(cause, "WDG"))
+               sprintf(newbootargs," androidboot.bootreason=watchdog");
+       else
+               sprintf(newbootargs," androidboot.bootreason=reboot");
+#else
+       sprintf(newbootargs," androidboot.bootreason=reboot");
+#endif
+       strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+
+#ifdef CONFIG_AVB_SUPPORT
+       /* secondary cmdline added by avb */
+       char *bootargs_sec = env_get("bootargs_sec");
+       if (bootargs_sec) {
+               strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+               strncat(commandline, bootargs_sec, sizeof(commandline) - strlen(commandline));
+       }
+#endif
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+       /* Normal boot:
+        * cmdline to bypass ramdisk in boot.img, but use the system.img
+        * Recovery boot:
+        * Use the ramdisk in boot.img
+        */
+       char *bootargs_3rd = env_get("bootargs_3rd");
+       if (bootargs_3rd) {
+               strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+               strncat(commandline, bootargs_3rd, sizeof(commandline) - strlen(commandline));
+       }
+#endif
+
+       /* VTS need this commandline to verify fdt overlay. Pass the
+        * dtb index as "0" here since we only have one dtb in dtbo
+        * partition and haven't enabled the dtb overlay.
+        */
+#if defined(CONFIG_ANDROID_SUPPORT) || defined(CONFIG_ANDROID_AUTO_SUPPORT)
+       sprintf(newbootargs," androidboot.dtbo_idx=0");
+       strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+#endif
+
+       char *keystore = env_get("keystore");
+       if ((keystore == NULL) || strncmp(keystore, "trusty", sizeof("trusty"))) {
+               char *bootargs_trusty = "androidboot.keystore=software";
+               strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+               strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline));
+       } else {
+               char *bootargs_trusty = "androidboot.keystore=trusty";
+               strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+               strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline));
+       }
+
+#ifdef CONFIG_APPEND_BOOTARGS
+       /* Add 'append_bootargs' to hold some paramemters which need to be appended
+        * to bootargs */
+       char *append_bootargs = env_get("append_bootargs");
+       if (append_bootargs) {
+               if (strlen(append_bootargs) + 2 >
+                               (sizeof(commandline) - strlen(commandline))) {
+                       printf("The 'append_bootargs' is too long to be appended to bootargs\n");
+               } else {
+                       strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+                       strncat(commandline, append_bootargs, sizeof(commandline) - strlen(commandline));
+               }
+       }
+#endif
+
+       debug("Kernel command line: %s\n", commandline);
+       env_set("bootargs", commandline);
 
        if (os_data) {
                if (image_get_magic(ihdr) == IH_MAGIC) {
@@ -537,3 +705,15 @@ bool android_image_print_dtb_contents(ulong hdr_addr)
        return true;
 }
 #endif
+
+#define ARM64_IMAGE_MAGIC      0x644d5241
+bool image_arm64(void *images)
+{
+       struct header_image *ih;
+
+       ih = (struct header_image *)images;
+       debug("image magic: %x\n", ih->magic);
+       if (ih->magic == le32_to_cpu(ARM64_IMAGE_MAGIC))
+               return true;
+       return false;
+}
index e5636ea..49a871b 100644 (file)
@@ -151,6 +151,25 @@ static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
        return 0;
 }
 
+static void prepare_last_lba_gpt_header(struct blk_desc *dev_desc, gpt_header *gpt_h)
+{
+       uint32_t calc_crc32;
+       uint64_t val;
+
+       /* recalculate the values for the Backup GPT Header */
+       val = le64_to_cpu(gpt_h->my_lba);
+       gpt_h->my_lba = cpu_to_le64(dev_desc->lba - 1);;
+       gpt_h->alternate_lba = cpu_to_le64(val);
+       gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
+       gpt_h->partition_entry_lba =
+                       cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
+       gpt_h->header_crc32 = 0;
+
+       calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+                              le32_to_cpu(gpt_h->header_size));
+       gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+}
+
 static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e)
 {
        uint32_t calc_crc32;
@@ -161,7 +180,7 @@ static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e)
                le32_to_cpu(gpt_h->sizeof_partition_entry));
 
        if (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) {
-               printf("%s: 0x%x != 0x%x\n",
+               debug("%s: 0x%x != 0x%x\n",
                       "GUID Partition Table Entry Array CRC is wrong",
                       le32_to_cpu(gpt_h->partition_entry_array_crc32),
                       calc_crc32);
@@ -873,6 +892,58 @@ int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf)
 
        return 0;
 }
+int write_backup_gpt_partitions(struct blk_desc *dev_desc, void *buf)
+{
+       gpt_header *gpt_h;
+       gpt_entry *gpt_e;
+       int gpt_e_blk_cnt;
+       lbaint_t lba;
+       int cnt;
+
+       if (is_valid_gpt_buf(dev_desc, buf))
+               return -1;
+
+       /* determine start of GPT Header in the buffer */
+       gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
+                      dev_desc->blksz);
+
+       /* determine start of GPT Entries in the buffer */
+       gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
+                      dev_desc->blksz);
+       gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) *
+                                  le32_to_cpu(gpt_h->sizeof_partition_entry)),
+                                 dev_desc);
+
+       /* write MBR */
+       lba = 0;        /* MBR is always at 0 */
+       cnt = 1;        /* MBR (1 block) */
+       if (blk_dwrite(dev_desc, lba, cnt, buf) != cnt) {
+               printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+                      __func__, "MBR", cnt, lba);
+               return 1;
+       }
+
+       prepare_last_lba_gpt_header(dev_desc, gpt_h);
+
+       /* write Backup GPT */
+       lba = le64_to_cpu(gpt_h->partition_entry_lba);
+       cnt = gpt_e_blk_cnt;
+       if (blk_dwrite(dev_desc, lba, cnt, gpt_e) != cnt) {
+               printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+                      __func__, "Backup GPT Entries", cnt, lba);
+               return 1;
+       }
+
+       lba = le64_to_cpu(gpt_h->my_lba);
+       cnt = 1;        /* GPT Header (1 block) */
+       if (blk_dwrite(dev_desc, lba, cnt, gpt_h) != cnt) {
+               printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+                      __func__, "Backup GPT Header", cnt, lba);
+               return 1;
+       }
+
+       return 0;
+}
 #endif
 
 /*
@@ -1005,7 +1076,7 @@ static int find_valid_gpt(struct blk_desc *dev_desc, gpt_header *gpt_head,
 
        if (r != 1) {
                if (r != 2)
-                       printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
+                       debug("%s: *** ERROR: Invalid GPT ***\n", __func__);
 
                if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), gpt_head,
                                 pgpt_pte) != 1) {
@@ -1014,7 +1085,7 @@ static int find_valid_gpt(struct blk_desc *dev_desc, gpt_header *gpt_head,
                        return 0;
                }
                if (r != 2)
-                       printf("%s: ***        Using Backup GPT ***\n",
+                       debug("%s: ***        Using Backup GPT ***\n",
                               __func__);
        }
        return 1;
index 2d1836a..04d630e 100644 (file)
@@ -74,16 +74,55 @@ config FASTBOOT_FLASH
 
 config FASTBOOT_UUU_SUPPORT
        bool "Enable FASTBOOT i.MX UUU special command"
-       default n
+       default y if ARCH_MX7 || ARCH_MX6 || ARCH_IMX8 || ARCH_IMX8M || ARCH_MX7ULP
+       select FSL_FASTBOOT
        help
          The fastboot protocol includes "UCmd" and "ACmd" command.
          Be aware that you provide full access to any U-Boot command,
          including working with memory and may open a huge backdoor,
          when enabling this option.
 
+config FSL_FASTBOOT
+       bool "Enable FSL fastboot support"
+       depends on FASTBOOT_FLASH
+       help
+         This enables FSL implementation for Android fastboot.
+
+config ANDROID_RECOVERY
+       bool "Enable the recovery boot function"
+       depends on FSL_FASTBOOT
+       help
+         This enables the Android Recovery boot function.
+
+config CMD_BOOTA
+       bool "Enable the boota command"
+       depends on FSL_FASTBOOT
+       help
+         This enables the boota command for booting android images.
+
+config BCB_SUPPORT
+       bool "Enable the boot control block support"
+       depends on FSL_FASTBOOT
+       help
+         This enables the boot control block support for android reboot command
+
+config FASTBOOT_LOCK
+       bool "Enable the lock and unlock feature to the partitions"
+       depends on FSL_FASTBOOT
+       help
+         This enables the lock support for android flashing command
+
+config FASTBOOT_USB_DEV
+       int "USB controller number"
+       default 0
+       help
+         Some boards have USB OTG controller other than 0. Define this
+         option so it can be used in compiled environment (e.g. in
+         CONFIG_BOOTCOMMAND).
+
 choice
        prompt "Flash provider for FASTBOOT"
-       depends on FASTBOOT_FLASH
+       depends on FASTBOOT_FLASH && !FSL_FASTBOOT
 
 config FASTBOOT_FLASH_MMC
        bool "FASTBOOT on MMC"
index 048af5a..902da22 100644 (file)
@@ -1,7 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 obj-y += fb_common.o
-obj-y += fb_getvar.o
+ifndef CONFIG_FSL_FASTBOOT
 obj-y += fb_command.o
+obj-y += fb_getvar.o
 obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o
 obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o
+else
+obj-y += fb_fsl/
+endif
index cbcc368..140f949 100644 (file)
@@ -16,6 +16,7 @@
 #include <env.h>
 #include <fastboot.h>
 #include <net/fastboot.h>
+#include <image.h>
 
 /**
  * fastboot_buf_addr - base address of the fastboot download buffer
@@ -136,12 +137,22 @@ void fastboot_boot(void)
                run_command(s, CMD_FLAG_ENV);
        } else {
                static char boot_addr_start[20];
+#ifdef CONFIG_FSL_FASTBOOT
+               static char *const bootm_args[] = {
+                       "boota", boot_addr_start, NULL
+               };
+
+               snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
+                        "0x%p", (void *)image_load_addr);
+#else
                static char *const bootm_args[] = {
                        "bootm", boot_addr_start, NULL
                };
 
                snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
                         "0x%p", fastboot_buf_addr);
+#endif
+
                printf("Booting kernel at %s...\n\n\n", boot_addr_start);
 
                do_bootm(NULL, 0, 2, bootm_args);
@@ -178,8 +189,13 @@ void fastboot_set_progress_callback(void (*progress)(const char *msg))
  */
 void fastboot_init(void *buf_addr, u32 buf_size)
 {
+#ifdef CONFIG_FSL_FASTBOOT
+       fastboot_buf_addr = buf_addr ? buf_addr :
+                                      (void *)env_get_ulong("fastboot_buffer", 16, CONFIG_FASTBOOT_BUF_ADDR);
+#else
        fastboot_buf_addr = buf_addr ? buf_addr :
                                       (void *)CONFIG_FASTBOOT_BUF_ADDR;
+#endif
        fastboot_buf_size = buf_size ? buf_size : CONFIG_FASTBOOT_BUF_SIZE;
        fastboot_set_progress_callback(NULL);
 }
diff --git a/drivers/fastboot/fb_fsl/Makefile b/drivers/fastboot/fb_fsl/Makefile
new file mode 100644 (file)
index 0000000..34f90c7
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Copyright 2019 NXP
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+ccflags-y += -I./lib/avb
+
+ifndef CONFIG_SPL_BUILD
+obj-y += fb_fsl_dev.o fb_fsl_boot.o fb_fsl_command.o fb_fsl_common.o fb_fsl_getvar.o fb_fsl_partitions.o
+obj-$(CONFIG_FASTBOOT_LOCK) += fastboot_lock_unlock.o
+obj-$(CONFIG_BCB_SUPPORT) += command.o bcb.o
+endif
diff --git a/drivers/fastboot/fb_fsl/bcb.c b/drivers/fastboot/fb_fsl/bcb.c
new file mode 100644 (file)
index 0000000..5807321
--- /dev/null
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#include <fb_fsl.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <common.h>
+#include <g_dnl.h>
+#include <mmc.h>
+#include "bcb.h"
+#define ALIGN_BYTES 64 /*armv7 cache line need 64 bytes aligned */
+
+static ulong get_block_size(char *ifname, int dev)
+{
+       struct blk_desc *dev_desc = NULL;
+
+       dev_desc = blk_get_dev(ifname, dev);
+       if (dev_desc == NULL) {
+               printf("Block device %s %d not supported\n", ifname, dev);
+               return 0;
+       }
+
+       return dev_desc->blksz;
+}
+
+static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       char *ep;
+       struct blk_desc *dev_desc = NULL;
+       int dev;
+       int part = 0;
+       struct disk_partition part_info;
+       ulong offset = 0u;
+       ulong limit = 0u;
+       void *addr;
+       uint blk;
+       uint cnt;
+
+       if (argc != 6) {
+               cmd_usage(cmdtp);
+               return 1;
+       }
+
+       dev = (int)simple_strtoul(argv[2], &ep, 16);
+       if (*ep) {
+               if (*ep != ':') {
+                       printf("Invalid block device %s\n", argv[2]);
+                       return 1;
+               }
+               part = (int)simple_strtoul(++ep, NULL, 16);
+       }
+
+       dev_desc = blk_get_dev(argv[1], dev);
+       if (dev_desc == NULL) {
+               printf("Block device %s %d not supported\n", argv[1], dev);
+               return 1;
+       }
+
+       addr = (void *)simple_strtoul(argv[3], NULL, 16);
+       blk = simple_strtoul(argv[4], NULL, 16);
+       cnt = simple_strtoul(argv[5], NULL, 16);
+
+       if (part != 0) {
+               if (part_get_info(dev_desc, part, &part_info)) {
+                       printf("Cannot find partition %d\n", part);
+                       return 1;
+               }
+               offset = part_info.start;
+               limit = part_info.size;
+       } else {
+               /* Largest address not available in block_dev_desc_t. */
+               limit = ~0;
+       }
+
+       if (cnt + blk > limit) {
+               printf("Write out of range\n");
+               return 1;
+       }
+
+       if (blk_dwrite(dev_desc, offset + blk, cnt, addr) != cnt) {
+               printf("Error writing blocks\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       write,  6,      0,      do_write,
+       "write binary data to a partition",
+       "<interface> <dev[:part]> addr blk# cnt"
+);
+
+int bcb_rw_block(bool bread, char **ppblock,
+               uint *pblksize, char *pblock_write, uint offset, uint size)
+{
+       int ret;
+       char *argv[6];
+       char addr_str[20];
+       char cnt_str[8];
+       char devpart_str[8];
+       char block_begin_str[8];
+       ulong blk_size = 0;
+       uint blk_begin = 0;
+       uint blk_end = 0;
+       uint block_cnt = 0;
+       char *p_block = NULL;
+       unsigned int mmc_id;
+
+       if (bread && ((ppblock == NULL) || (pblksize == NULL)))
+               return -1;
+
+       if (!bread && (pblock_write == NULL))
+               return -1;
+
+       mmc_id = mmc_get_env_dev();
+       blk_size = get_block_size("mmc", mmc_id);
+       if (blk_size == 0) {
+               printf("bcb_rw_block, get_block_size return 0\n");
+               return -1;
+       }
+
+       blk_begin = offset/blk_size;
+       blk_end = (offset + size)/blk_size;
+       block_cnt = 1 + (blk_end - blk_begin);
+
+       sprintf(devpart_str, "0x%x:0x%x", mmc_id,
+                       fastboot_flash_find_index(FASTBOOT_PARTITION_MISC));
+       sprintf(block_begin_str, "0x%x", blk_begin);
+       sprintf(cnt_str, "0x%x", block_cnt);
+
+       argv[0] = "rw"; /* not care */
+       argv[1] = "mmc";
+       argv[2] = devpart_str;
+       argv[3] = addr_str;
+       argv[4] = block_begin_str;
+       argv[5] = cnt_str;
+
+       if (bread) {
+               p_block = (char *)memalign(ALIGN_BYTES, blk_size * block_cnt);
+               if (NULL == p_block) {
+                       printf("bcb_rw_block, memalign %d bytes failed\n",
+                       (int)(blk_size * block_cnt));
+                       return -1;
+               }
+               sprintf(addr_str, "0x%x", (unsigned int)(uintptr_t)p_block);
+               ret = do_raw_read(NULL, 0, 6, argv);
+               if (ret) {
+                       free(p_block);
+                       printf("do_raw_read failed, ret %d\n", ret);
+                       return -1;
+               }
+
+               *ppblock = p_block;
+               *pblksize = (uint)blk_size;
+       } else {
+               sprintf(addr_str, "0x%x", (unsigned int)(uintptr_t)pblock_write);
+               ret = do_write(NULL, 0, 6, argv);
+               if (ret) {
+                       printf("do_write failed, ret %d\n", ret);
+                       return -1;
+               }
+       }
+       return 0;
+}
diff --git a/drivers/fastboot/fb_fsl/bcb.h b/drivers/fastboot/fb_fsl/bcb.h
new file mode 100644 (file)
index 0000000..af01c19
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ */
+
+#ifndef BCB_H
+#define BCB_H
+#include <linux/types.h>
+#include <linux/stat.h>
+
+#define FASTBOOT_BCB_CMD "bootonce-bootloader"
+#ifdef CONFIG_ANDROID_RECOVERY
+#define RECOVERY_BCB_CMD "boot-recovery"
+#endif
+/* keep same as bootable/recovery/bootloader.h */
+struct bootloader_message {
+       char command[32];
+       char status[32];
+       char recovery[768];
+
+       /* The 'recovery' field used to be 1024 bytes. It has only ever
+        been used to store the recovery command line, so 768 bytes
+        should be plenty.  We carve off the last 256 bytes to store the
+        stage string (for multistage packages) and possible future
+        expansion. */
+       char stage[32];
+
+       /* The 'reserved' field used to be 224 bytes when it was initially
+        carved off from the 1024-byte recovery field. Bump it up to
+        1184-byte so that the entire bootloader_message struct rounds up
+        to 2048-byte.
+        */
+       char reserved[1184];
+};
+
+struct bootloader_message_ab {
+       struct bootloader_message message;
+       char slot_suffix[32];
+
+       /* Round up the entire struct to 4096-byte. */
+       char reserved[2016];
+};
+
+/* start from bootloader_message_ab.slot_suffix[BOOTCTRL_IDX] */
+#define BOOTCTRL_IDX                            0
+#define MISC_COMMAND_IDX                        0
+#define BOOTCTRL_OFFSET         \
+       (u32)(&(((struct bootloader_message_ab *)0)->slot_suffix[BOOTCTRL_IDX]))
+#define MISC_COMMAND \
+       (u32)(uintptr_t)(&(((struct bootloader_message *)0)->command[MISC_COMMAND_IDX]))
+int bcb_rw_block(bool bread, char **ppblock,
+               uint *pblksize, char *pblock_write, uint offset, uint size);
+
+int bcb_write_command(char *bcb_command);
+int bcb_read_command(char *command);
+
+#endif
diff --git a/drivers/fastboot/fb_fsl/command.c b/drivers/fastboot/fb_fsl/command.c
new file mode 100644 (file)
index 0000000..349a014
--- /dev/null
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <g_dnl.h>
+#include "bcb.h"
+
+int bcb_read_command(char *command)
+{
+       int ret = 0;
+       char *p_block = NULL;
+       uint offset_in_block = 0;
+       uint blk_size = 0;
+
+       if (command == NULL)
+               return -1;
+
+       ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32);
+       if (ret) {
+               printf("read_bootctl, bcb_rw_block read failed\n");
+               return -1;
+       }
+
+       offset_in_block = MISC_COMMAND%blk_size;
+       memcpy(command, p_block + offset_in_block, 32);
+       free(p_block);
+
+       return 0;
+}
+int bcb_write_command(char *bcb_command)
+{
+       int ret = 0;
+       char *p_block = NULL;
+       uint offset_in_block = 0;
+       uint blk_size = 0;
+
+       if (bcb_command == NULL)
+               return -1;
+
+
+       ret = bcb_rw_block(true, &p_block, &blk_size, NULL,  MISC_COMMAND, 32);
+       if (ret) {
+               printf("write_bootctl, bcb_rw_block read failed\n");
+               return -1;
+       }
+
+       offset_in_block = MISC_COMMAND%blk_size;
+       memcpy(p_block + offset_in_block, bcb_command, 32);
+
+       ret = bcb_rw_block(false, NULL, NULL, p_block, MISC_COMMAND, 32);
+       if (ret) {
+               free(p_block);
+               printf("write_bootctl, bcb_rw_block write failed\n");
+               return -1;
+       }
+
+       free(p_block);
+       return 0;
+}
diff --git a/drivers/fastboot/fb_fsl/fastboot_lock_unlock.c b/drivers/fastboot/fb_fsl/fastboot_lock_unlock.c
new file mode 100644 (file)
index 0000000..e5caced
--- /dev/null
@@ -0,0 +1,583 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ */
+#include <common.h>
+#include <mapmem.h>
+#include <linux/types.h>
+#include <part.h>
+#include <mmc.h>
+#include <ext_common.h>
+#include <stdio_dev.h>
+#include <stdlib.h>
+#include "fastboot_lock_unlock.h"
+#include <fb_fsl.h>
+#include <memalign.h>
+#include <asm/mach-imx/sys_proto.h>
+#ifdef CONFIG_IMX_TRUSTY_OS
+#include <trusty/libtipc.h>
+#include <asm/mach-imx/hab.h>
+#endif
+
+#ifdef FASTBOOT_ENCRYPT_LOCK
+
+#include <hash.h>
+#include <fsl_caam.h>
+
+//Encrypted data is 80bytes length.
+#define ENDATA_LEN 80
+
+#endif
+
+int fastboot_flash_find_index(const char *name);
+
+#if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_ARM64)
+#define IVT_HEADER_MAGIC       0xD1
+#define IVT_HDR_LEN       0x20
+#define HAB_MAJ_VER       0x40
+#define HAB_MAJ_MASK      0xF0
+
+bool tos_flashed;
+
+static bool tos_ivt_check(ulong start_addr, int ivt_offset) {
+       const struct ivt *ivt_initial = NULL;
+       const uint8_t *start = (const uint8_t *)start_addr;
+
+       if (start_addr & 0x3) {
+               puts("Error: tos's start address is not 4 byte aligned\n");
+               return false;
+       }
+
+       ivt_initial = (const struct ivt *)(start + ivt_offset);
+
+       const struct ivt_header *ivt_hdr = &ivt_initial->hdr;
+
+       if ((ivt_hdr->magic == IVT_HEADER_MAGIC && \
+               (be16_to_cpu(ivt_hdr->length) == IVT_HDR_LEN) && \
+               (ivt_hdr->version & HAB_MAJ_MASK) == HAB_MAJ_VER) && \
+               (ivt_initial->entry != 0x0) && \
+               (ivt_initial->reserved1 == 0x0) && \
+               (ivt_initial->self == (uint32_t)ivt_initial) && \
+               (ivt_initial->csf != 0x0) && \
+               (ivt_initial->reserved2 == 0x0)) {
+               if (ivt_initial->dcd != 0x0)
+                       return false;
+               else
+                       return true;
+       }
+
+       return false;
+}
+
+bool valid_tos() {
+       /*
+        * If enabled SECURE_BOOT then use HAB to verify tos.
+        * Or check the IVT only.
+        */
+       bool valid = false;
+#ifdef CONFIG_IMX_HAB
+       if (is_hab_enabled()) {
+               valid = authenticate_image(TRUSTY_OS_ENTRY, TRUSTY_OS_PADDED_SZ);
+       } else
+#endif
+       valid = tos_ivt_check(TRUSTY_OS_ENTRY, TRUSTY_OS_PADDED_SZ);
+
+       if (valid) {
+               tos_flashed = true;
+               return true;
+       } else {
+               tos_flashed = false;
+               return false;
+       }
+}
+
+#endif
+
+#if !defined(FASTBOOT_ENCRYPT_LOCK) || defined(NON_SECURE_FASTBOOT)
+
+/*
+ * This will return FASTBOOT_LOCK, FASTBOOT_UNLOCK or FASTBOOT_ERROR
+ */
+#ifndef CONFIG_IMX_TRUSTY_OS
+static FbLockState decrypt_lock_store(unsigned char* bdata) {
+       if (!strncmp((const char *)bdata, "locked", strlen("locked")))
+               return FASTBOOT_LOCK;
+       else if (!strncmp((const char *)bdata, "unlocked", strlen("unlocked")))
+               return FASTBOOT_UNLOCK;
+       else
+               return FASTBOOT_LOCK_ERROR;
+}
+static inline int encrypt_lock_store(FbLockState lock, unsigned char* bdata) {
+       if (FASTBOOT_LOCK == lock)
+               strncpy((char *)bdata, "locked", strlen("locked"));
+       else if (FASTBOOT_UNLOCK == lock)
+               strncpy((char *)bdata, "unlocked", strlen("unlocked"));
+       else
+               return -1;
+       return 0;
+}
+#endif
+#else
+
+static int sha1sum(unsigned char* data, int len, unsigned char* output) {
+       struct hash_algo *algo;
+       void *buf;
+       if (hash_lookup_algo("sha1", &algo)) {
+               printf("error in lookup sha1 algo!\n");
+               return -1;
+       }
+       buf = map_sysmem((ulong)data, len);
+       algo->hash_func_ws(buf, len, output, algo->chunk_size);
+       unmap_sysmem(buf);
+
+       return algo->digest_size;
+
+}
+
+static int generate_salt(unsigned char* salt) {
+       unsigned long time = get_timer(0);
+       return sha1sum((unsigned char *)&time, sizeof(unsigned long), salt);
+
+}
+
+static FbLockState decrypt_lock_store(unsigned char *bdata) {
+       int p = 0, ret;
+       ALLOC_CACHE_ALIGN_BUFFER(uint8_t, plain_data, ENDATA_LEN);
+
+       caam_open();
+       ret = caam_decap_blob((uint32_t)(ulong)plain_data,
+                             (uint32_t)(ulong)bdata + ROUND(ENDATA_LEN, ARCH_DMA_MINALIGN),
+                             ENDATA_LEN);
+       if (ret != 0) {
+               printf("Error during blob decap operation: 0x%x\n",ret);
+               return FASTBOOT_LOCK_ERROR;
+       }
+#ifdef FASTBOOT_LOCK_DEBUG
+       FB_DEBUG("Decrypt data block are:\n \t=======\t\n");
+       for (p = 0; p < ENDATA_LEN; p++) {
+               FB_DEBUG("0x%2x  ", *(bdata + p));
+               if (p % 16 == 0)
+                       FB_DEBUG("\n");
+       }
+       FB_DEBUG("\n \t========\t\n");
+       for (p = ENDATA_LEN; p < (ENDATA_LEN + ENDATA_LEN + 48 ); p++) {
+               FB_DEBUG("0x%2x  ", *(bdata + p));
+               if (p % 16 == 0)
+                       FB_DEBUG("\n");
+       }
+
+       FB_DEBUG("\n plain text are:\n");
+       for (p = 0; p < ENDATA_LEN; p++) {
+               FB_DEBUG("0x%2x  ", plain_data[p]);
+               if (p % 16 == 0)
+                       FB_DEBUG("\n");
+       }
+       FB_DEBUG("\n");
+#endif
+
+       for (p = 0; p < ENDATA_LEN-1; p++) {
+               if (*(bdata+p) != plain_data[p]) {
+                       FB_DEBUG("Verify salt in decrypt error on pointer %d\n", p);
+                       return FASTBOOT_LOCK_ERROR;
+               }
+       }
+
+       if (plain_data[ENDATA_LEN - 1] >= FASTBOOT_LOCK_NUM)
+               return FASTBOOT_LOCK_ERROR;
+       else
+               return plain_data[ENDATA_LEN-1];
+}
+
+static int encrypt_lock_store(FbLockState lock, unsigned char* bdata) {
+       unsigned int p = 0;
+       int ret;
+       int salt_len = generate_salt(bdata);
+       if (salt_len < 0)
+               return -1;
+
+    //salt_len cannot be longer than endata block size.
+       if (salt_len >= ENDATA_LEN)
+               salt_len = ENDATA_LEN - 1;
+
+       p = ENDATA_LEN - 1;
+
+       //Set lock value
+       *(bdata + p) = lock;
+
+       caam_open();
+       ret = caam_gen_blob((uint32_t)(ulong)bdata,
+                       (uint32_t)(ulong)bdata + ROUND(ENDATA_LEN, ARCH_DMA_MINALIGN),
+                       ENDATA_LEN);
+       if (ret != 0) {
+               printf("error in caam_gen_blob:0x%x\n", ret);
+               return -1;
+       }
+
+
+#ifdef FASTBOOT_LOCK_DEBUG
+       int i = 0;
+       FB_DEBUG("encrypt plain_text:\n");
+       for (i = 0; i < ENDATA_LEN; i++) {
+               FB_DEBUG("0x%2x\t", *(bdata+i));
+               if (i % 16 == 0)
+                       printf("\n");
+       }
+       printf("\nto:\n");
+       for (i=0; i < ENDATA_LEN + 48; i++) {
+               FB_DEBUG("0x%2x\t", *(bdata + ENDATA_LEN + i));
+               if (i % 16 == 0)
+                       printf("\n");
+       }
+       printf("\n");
+
+#endif
+       //protect value
+       *(bdata + p) = 0xff;
+       return 0;
+}
+
+#endif
+
+static char mmc_dev_part[16];
+static char* get_mmc_part(int part) {
+       u32 dev_no = mmc_get_env_dev();
+       sprintf(mmc_dev_part,"%x:%x",dev_no, part);
+       return mmc_dev_part;
+}
+
+static inline void set_lock_disable_data(unsigned char* bdata) {
+       *(bdata + SECTOR_SIZE -1) = 0;
+}
+
+/*
+ * The enabling value is stored in the last byte of target partition.
+ */
+static inline unsigned char lock_enable_parse(unsigned char* bdata) {
+       FB_DEBUG("lock_enable_parse: 0x%x\n", *(bdata + SECTOR_SIZE -1));
+       if (*(bdata + SECTOR_SIZE -1) >= FASTBOOT_UL_NUM)
+               return FASTBOOT_UL_ERROR;
+       else
+               return *(bdata + SECTOR_SIZE -1);
+}
+
+static FbLockState g_lockstat = FASTBOOT_UNLOCK;
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+FbLockState fastboot_get_lock_stat(void) {
+       uint8_t l_status;
+       int ret;
+       /*
+        * If Trusty OS not flashed, then must return
+        * unlock status to make device been able
+        * to flash Trusty OS binary.
+        */
+#ifndef CONFIG_ARM64
+       if (!tos_flashed)
+               return FASTBOOT_UNLOCK;
+#endif
+       ret = trusty_read_lock_state(&l_status);
+       if (ret < 0)
+               return g_lockstat;
+       else
+               return l_status;
+
+}
+
+int fastboot_set_lock_stat(FbLockState lock) {
+       int ret;
+       /*
+        * If Trusty OS not flashed, we must prevent set lock
+        * status. Due the Trusty IPC won't work here.
+        */
+#ifndef CONFIG_ARM64
+       if (!tos_flashed)
+               return 0;
+#endif
+       ret = trusty_write_lock_state(lock);
+       if (ret < 0) {
+               printf("cannot set lock status due Trusty return %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+#else
+
+/*
+ * Set status of the lock&unlock to FSL_FASTBOOT_FB_PART
+ * Currently use the very first Byte of FSL_FASTBOOT_FB_PART
+ * to store the fastboot lock&unlock status
+ */
+int fastboot_set_lock_stat(FbLockState lock) {
+       struct blk_desc *fs_dev_desc;
+       struct disk_partition fs_partition;
+       unsigned char *bdata;
+       int mmc_id;
+       int status, ret;
+
+       bdata = (unsigned char *)memalign(ARCH_DMA_MINALIGN, SECTOR_SIZE);
+       if (bdata == NULL)
+               goto fail2;
+       memset(bdata, 0, SECTOR_SIZE);
+
+       mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_FBMISC);
+       if (mmc_id < 0) {
+               printf("%s: error in get mmc part\n", __FUNCTION__);
+               ret = -1;
+               goto fail;
+       }
+       status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV,
+               get_mmc_part(mmc_id),
+               &fs_dev_desc, &fs_partition, 1);
+       if (status < 0) {
+               printf("%s:error in getdevice partition.\n", __FUNCTION__);
+               ret = -1;
+               goto fail;
+       }
+
+       status = encrypt_lock_store(lock, bdata);
+       if (status < 0) {
+               ret = -1;
+               goto fail;
+       }
+       status = blk_dwrite(fs_dev_desc, fs_partition.start, 1, bdata);
+       if (!status) {
+               printf("%s:error in block write.\n", __FUNCTION__);
+               ret = -1;
+               goto fail;
+       }
+       ret = 0;
+fail:
+       free(bdata);
+       return ret;
+fail2:
+       g_lockstat = lock;
+       return 0;
+}
+
+FbLockState fastboot_get_lock_stat(void) {
+       struct blk_desc *fs_dev_desc;
+       struct disk_partition fs_partition;
+       unsigned char *bdata;
+       int mmc_id;
+       FbLockState ret;
+       /* uboot used by uuu will boot from USB, always return UNLOCK state */
+       if (is_boot_from_usb())
+               return g_lockstat;
+
+       bdata = (unsigned char *)memalign(ARCH_DMA_MINALIGN, SECTOR_SIZE);
+       if (bdata == NULL)
+               return g_lockstat;
+
+       int status;
+       mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_FBMISC);
+       if (mmc_id < 0) {
+               printf("%s: error in get mmc part\n", __FUNCTION__);
+               ret = g_lockstat;
+               goto fail;
+       }
+       status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV,
+               get_mmc_part(mmc_id),
+               &fs_dev_desc, &fs_partition, 1);
+
+       if (status < 0) {
+               printf("%s:error in getdevice partition.\n", __FUNCTION__);
+               ret = g_lockstat;
+               goto fail;
+       }
+
+       status = blk_dread(fs_dev_desc, fs_partition.start, 1, bdata);
+       if (!status) {
+               printf("%s:error in block read.\n", __FUNCTION__);
+               ret = FASTBOOT_LOCK_ERROR;
+               goto fail;
+       }
+
+       ret = decrypt_lock_store(bdata);
+fail:
+       free(bdata);
+       return ret;
+}
+#endif
+
+
+/* Return the last byte of of FSL_FASTBOOT_PR_DATA
+ * which is managed by PresistDataService
+ */
+
+#ifdef CONFIG_ENABLE_LOCKSTATUS_SUPPORT
+//Brillo has no presist data partition
+FbLockEnableResult fastboot_lock_enable(void) {
+       return FASTBOOT_UL_ENABLE;
+}
+void set_fastboot_lock_disable(void) {
+}
+#else
+void set_fastboot_lock_disable(void) {
+       struct blk_desc *fs_dev_desc;
+       struct disk_partition fs_partition;
+       unsigned char *bdata;
+       int mmc_id;
+
+       bdata = (unsigned char *)memalign(ALIGN_BYTES, SECTOR_SIZE);
+       if (bdata == NULL)
+               return;
+       set_lock_disable_data(bdata);
+       int status;
+       mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_PRDATA);
+       if (mmc_id < 0) {
+               printf("%s: error in get mmc part\n", __FUNCTION__);
+               goto fail;
+       }
+       status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV,
+               get_mmc_part(mmc_id),
+               &fs_dev_desc, &fs_partition, 1);
+       if (status < 0) {
+               printf("%s:error in getdevice partition.\n", __FUNCTION__);
+               goto fail;
+       }
+
+       lbaint_t target_block = fs_partition.start + fs_partition.size - 1;
+       status = blk_dwrite(fs_dev_desc, target_block, 1, bdata);
+       if (!status) {
+               printf("%s: error in block read\n", __FUNCTION__);
+               goto fail;
+       }
+
+fail:
+       free(bdata);
+       return;
+
+}
+FbLockEnableResult fastboot_lock_enable() {
+       struct blk_desc *fs_dev_desc;
+       struct disk_partition fs_partition;
+       unsigned char *bdata;
+       int mmc_id;
+       FbLockEnableResult ret;
+
+       bdata = (unsigned char *)memalign(ALIGN_BYTES, SECTOR_SIZE);
+       if (bdata == NULL)
+               return FASTBOOT_UL_ERROR;
+       int status;
+       mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_PRDATA);
+       if (mmc_id < 0) {
+               printf("%s: error in get mmc part\n", __FUNCTION__);
+               ret = FASTBOOT_UL_ERROR;
+               goto fail;
+       }
+       status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV,
+               get_mmc_part(mmc_id),
+               &fs_dev_desc, &fs_partition, 1);
+       if (status < 0) {
+               printf("%s:error in getdevice partition.\n", __FUNCTION__);
+               ret = FASTBOOT_UL_ERROR;
+               goto fail;
+       }
+
+    //The data is stored in the last blcok of this partition.
+       lbaint_t target_block = fs_partition.start + fs_partition.size - 1;
+       status = blk_dread(fs_dev_desc, target_block, 1, bdata);
+       if (!status) {
+               printf("%s: error in block read\n", __FUNCTION__);
+               ret = FASTBOOT_UL_ERROR;
+               goto fail;
+       }
+       int i = 0;
+       FB_DEBUG("\n PRIST last sector is:\n");
+       for (i = 0; i < SECTOR_SIZE; i++) {
+               FB_DEBUG("0x%x  ", *(bdata + i));
+               if (i % 32 == 0)
+                       FB_DEBUG("\n");
+       }
+       FB_DEBUG("\n");
+       ret = lock_enable_parse(bdata);
+fail:
+       free(bdata);
+       return ret;
+
+}
+#endif
+
+int display_lock(FbLockState lock, int verify) {
+       struct stdio_dev *disp;
+       disp = stdio_get_by_name("vga");
+       if (disp != NULL) {
+               if (lock == FASTBOOT_UNLOCK) {
+                       disp->puts(disp, "\n============= NOTICE ============\n");
+                       disp->puts(disp,   "|                               |\n");
+                       disp->puts(disp,   "|   Your device is NOT locked.  |\n");
+                       disp->puts(disp,   "|                               |\n");
+                       disp->puts(disp,   "=================================\n");
+               } else {
+                       if (verify == -1) {
+                               disp->puts(disp, "\n============= NOTICE ============\n");
+                               disp->puts(disp,   "|                               |\n");
+                               disp->puts(disp,   "| Your device is NOT protected. |\n");
+                               disp->puts(disp,   "|                               |\n");
+                               disp->puts(disp,   "=================================\n");
+                       } else if (verify == 1) {
+                               disp->puts(disp, "\n============= NOTICE ============\n");
+                               disp->puts(disp,   "|                               |\n");
+                               disp->puts(disp,   "|       Boot verify failed!     |\n");
+                               disp->puts(disp,   "|                               |\n");
+                               disp->puts(disp,   "=================================\n");
+                       }
+               }
+               return 0;
+       } else
+               printf("not found VGA disp console.\n");
+
+       return -1;
+
+}
+
+int fastboot_wipe_data_partition(void)
+{
+       struct blk_desc *fs_dev_desc;
+       struct disk_partition fs_partition;
+       int status;
+       int mmc_id;
+       mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_DATA);
+       if (mmc_id < 0) {
+               printf("%s: error in get mmc part\n", __FUNCTION__);
+               return -1;
+       }
+       status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV,
+               get_mmc_part(mmc_id), &fs_dev_desc, &fs_partition, 1);
+       if (status < 0) {
+               printf("error in get device partition for wipe /data\n");
+               return -1;
+       }
+       status = blk_derase(fs_dev_desc, fs_partition.start , fs_partition.size );
+       if (status != fs_partition.size ) {
+               printf("erase not complete\n");
+               return -1;
+       }
+       mdelay(2000);
+
+       return 0;
+}
+
+void fastboot_wipe_all(void) {
+       struct blk_desc *fs_dev_desc;
+       struct disk_partition fs_partition;
+       int status;
+       int mmc_id;
+       mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_GPT);
+       if (mmc_id < 0) {
+               printf("%s: error in get mmc part\n", __FUNCTION__);
+               return;
+       }
+       status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV,
+               get_mmc_part(mmc_id), &fs_dev_desc, &fs_partition, 1);
+       if (status < 0) {
+               printf("error in get device partition for wipe user partition\n");
+               return;
+       }
+       status = blk_derase(fs_dev_desc, fs_partition.start , fs_partition.size );
+       if (status != fs_partition.size ) {
+               printf("erase not complete\n");
+               return;
+       }
+       printf("fastboot wiped all.\n");
+}
diff --git a/drivers/fastboot/fb_fsl/fastboot_lock_unlock.h b/drivers/fastboot/fb_fsl/fastboot_lock_unlock.h
new file mode 100644 (file)
index 0000000..06c69ca
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FASTBOOT_LOCK_UNLOCK_H
+#define FASTBOOT_LOCK_UNLOCK_H
+
+#define ALIGN_BYTES 64 /*armv7 cache line need 64 bytes aligned */
+
+//#define FASTBOOT_LOCK_DEBUG
+#ifdef CONFIG_FSL_CAAM_KB
+#define FASTBOOT_ENCRYPT_LOCK
+#endif
+
+#ifdef FASTBOOT_LOCK_DEBUG
+#define FB_DEBUG(format, ...) printf(format, ##__VA_ARGS__)
+#else
+#define FB_DEBUG(format, ...)
+#endif
+
+typedef enum {
+       FASTBOOT_UNLOCK,
+       FASTBOOT_LOCK,
+       FASTBOOT_LOCK_ERROR,
+       FASTBOOT_LOCK_NUM
+}FbLockState;
+
+typedef enum {
+       FASTBOOT_UL_DISABLE,
+       FASTBOOT_UL_ENABLE,
+       FASTBOOT_UL_ERROR,
+       FASTBOOT_UL_NUM
+}FbLockEnableResult;
+
+FbLockState fastboot_get_lock_stat(void);
+
+int fastboot_set_lock_stat(FbLockState lock);
+
+int fastboot_wipe_data_partition(void);
+void fastboot_wipe_all(void);
+
+FbLockEnableResult fastboot_lock_enable(void);
+void set_fastboot_lock_disable(void);
+
+int display_lock(FbLockState lock, int verify);
+
+bool valid_tos(void);
+#endif
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_boot.c b/drivers/fastboot/fb_fsl/fb_fsl_boot.c
new file mode 100644 (file)
index 0000000..7877207
--- /dev/null
@@ -0,0 +1,1051 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <asm/mach-imx/sys_proto.h>
+#include <fb_fsl.h>
+#include <fastboot.h>
+#include <mmc.h>
+#include <android_image.h>
+#include <asm/bootm.h>
+#include <nand.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+#include <image.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/setup.h>
+#include <env.h>
+#include "../lib/avb/fsl/utils.h"
+
+#ifdef CONFIG_AVB_SUPPORT
+#include <dt_table.h>
+#include <fsl_avb.h>
+#endif
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+#include <asm-generic/gpio.h>
+#include <asm/mach-imx/gpio.h>
+#include "../lib/avb/fsl/fsl_avbkey.h"
+#include "../arch/arm/include/asm/mach-imx/hab.h"
+#endif
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+#include "fastboot_lock_unlock.h"
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#include "u-boot/sha256.h"
+#include <trusty/libtipc.h>
+#endif
+
+#include "fb_fsl_common.h"
+
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+#define DST_DECOMPRESS_LEN 1024*1024*32
+#endif
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+#define FDT_PART_NAME "oem_bootloader"
+#else
+#define FDT_PART_NAME "dtbo"
+#endif
+
+/* Offset (in u32's) of start and end fields in the zImage header. */
+#define ZIMAGE_START_ADDR      10
+#define ZIMAGE_END_ADDR        11
+
+/* Boot metric variables */
+boot_metric metrics = {
+  .bll_1 = 0,
+  .ble_1 = 0,
+  .kl   = 0,
+  .kd   = 0,
+  .avb  = 0,
+  .odt  = 0,
+  .sw   = 0
+};
+
+int read_from_partition_multi(const char* partition,
+               int64_t offset, size_t num_bytes, void* buffer, size_t* out_num_read)
+{
+       struct fastboot_ptentry *pte;
+       unsigned char *bdata;
+       unsigned char *out_buf = (unsigned char *)buffer;
+       unsigned char *dst, *dst64 = NULL;
+       unsigned long blksz;
+       unsigned long s, cnt;
+       size_t num_read = 0;
+       lbaint_t part_start, part_end, bs, be, bm, blk_num;
+       margin_pos_t margin;
+       struct blk_desc *fs_dev_desc = NULL;
+       int dev_no;
+       int ret;
+
+       assert(buffer != NULL && out_num_read != NULL);
+
+       dev_no = mmc_get_env_dev();
+       if ((fs_dev_desc = blk_get_dev("mmc", dev_no)) == NULL) {
+               printf("mmc device not found\n");
+               return -1;
+       }
+
+       pte = fastboot_flash_find_ptn(partition);
+       if (!pte) {
+               printf("no %s partition\n", partition);
+               fastboot_flash_dump_ptn();
+               return -1;
+       }
+
+       blksz = fs_dev_desc->blksz;
+       part_start = pte->start;
+       part_end = pte->start + pte->length - 1;
+
+       if (get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
+                               &margin, offset, num_bytes, true))
+               return -1;
+
+       bs = (lbaint_t)margin.blk_start;
+       be = (lbaint_t)margin.blk_end;
+       s = margin.start;
+       bm = margin.multi;
+
+       /* alloc a blksz mem */
+       bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
+       if (bdata == NULL) {
+               printf("Failed to allocate memory!\n");
+               return -1;
+       }
+
+       /* support multi blk read */
+       while (bs <= be) {
+               if (!s && bm > 1) {
+                       dst = out_buf;
+                       dst64 = PTR_ALIGN(out_buf, 64); /* for mmc blk read alignment */
+                       if (dst64 != dst) {
+                               dst = dst64;
+                               bm--;
+                       }
+                       blk_num = bm;
+                       cnt = bm * blksz;
+                       bm = 0; /* no more multi blk */
+               } else {
+                       blk_num = 1;
+                       cnt = blksz - s;
+                       if (num_read + cnt > num_bytes)
+                               cnt = num_bytes - num_read;
+                       dst = bdata;
+               }
+               if (blk_dread(fs_dev_desc, bs, blk_num, dst) != blk_num) {
+                       ret = -1;
+                       goto fail;
+               }
+
+               if (dst == bdata)
+                       memcpy(out_buf, bdata + s, cnt);
+               else if (dst == dst64)
+                       memcpy(out_buf, dst, cnt); /* internal copy */
+
+               s = 0;
+               bs += blk_num;
+               num_read += cnt;
+               out_buf += cnt;
+       }
+       *out_num_read = num_read;
+       ret = 0;
+
+fail:
+       free(bdata);
+       return ret;
+}
+
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+int do_lock_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
+       FbLockState status = fastboot_get_lock_stat();
+       if (status != FASTBOOT_LOCK_ERROR) {
+               if (status == FASTBOOT_LOCK)
+                       printf("fastboot lock status: locked.\n");
+               else
+                       printf("fastboot lock status: unlocked.\n");
+       } else
+               printf("fastboot lock status error!\n");
+
+       display_lock(status, -1);
+
+       return 0;
+
+}
+
+U_BOOT_CMD(
+       lock_status, 2, 1, do_lock_status,
+       "lock_status",
+       "lock_status");
+#endif
+
+#if defined(CONFIG_FLASH_MCUFIRMWARE_SUPPORT) && defined(CONFIG_ARCH_IMX8M)
+static int do_bootmcu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int ret;
+       size_t out_num_read;
+       void *m4_base_addr = (void *)M4_BOOTROM_BASE_ADDR;
+       char command[32];
+
+       ret = read_from_partition_multi(FASTBOOT_MCU_FIRMWARE_PARTITION,
+                       0, ANDROID_MCU_FIRMWARE_SIZE, (void *)m4_base_addr, &out_num_read);
+       if ((ret != 0) || (out_num_read != ANDROID_MCU_FIRMWARE_SIZE)) {
+               printf("Read M4 images failed!\n");
+               return 1;
+       } else {
+               printf("run command: 'bootaux 0x%x'\n",(unsigned int)(ulong)m4_base_addr);
+
+               sprintf(command, "bootaux 0x%x", (unsigned int)(ulong)m4_base_addr);
+               ret = run_command(command, 0);
+               if (ret) {
+                       printf("run 'bootaux' command failed!\n");
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+U_BOOT_CMD(
+       bootmcu, 1, 0, do_bootmcu,
+       "boot mcu images\n",
+       "boot mcu images from 'm4_os' partition, only support images run from TCM"
+);
+#endif
+
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+/* Setup booargs for taking the system parition as ramdisk */
+static void fastboot_setup_system_boot_args(const char *slot, bool append_root)
+{
+       const char *system_part_name = NULL;
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+       if(slot == NULL)
+               return;
+       if(!strncmp(slot, "_a", strlen("_a")) || !strncmp(slot, "boot_a", strlen("boot_a"))) {
+               system_part_name = FASTBOOT_PARTITION_SYSTEM_A;
+       }
+       else if(!strncmp(slot, "_b", strlen("_b")) || !strncmp(slot, "boot_b", strlen("boot_b"))) {
+               system_part_name = FASTBOOT_PARTITION_SYSTEM_B;
+       } else {
+               printf("slot invalid!\n");
+               return;
+       }
+#else
+       system_part_name = FASTBOOT_PARTITION_SYSTEM;
+#endif
+
+       struct fastboot_ptentry *ptentry = fastboot_flash_find_ptn(system_part_name);
+       if(ptentry != NULL) {
+               char bootargs_3rd[ANDR_BOOT_ARGS_SIZE];
+               if (append_root) {
+                       u32 dev_no = mmc_map_to_kernel_blk(mmc_get_env_dev());
+                       sprintf(bootargs_3rd, "skip_initramfs root=/dev/mmcblk%dp%d",
+                                       dev_no,
+                                       ptentry->partition_index);
+               } else {
+                       sprintf(bootargs_3rd, "skip_initramfs");
+               }
+               strcat(bootargs_3rd, " rootwait");
+               env_set("bootargs_3rd", bootargs_3rd);
+       } else {
+               printf("Can't find partition: %s\n", system_part_name);
+               fastboot_flash_dump_ptn();
+       }
+}
+#endif
+
+#ifdef CONFIG_CMD_BOOTA
+
+/* Section for Android bootimage format support
+* Refer:
+* http://android.git.kernel.org/?p=platform/system/core.git;a=blob;
+* f=mkbootimg/bootimg.h
+*/
+
+void
+bootimg_print_image_hdr(struct andr_img_hdr *hdr)
+{
+#ifdef DEBUG
+       int i;
+       printf("   Image magic:   %s\n", hdr->magic);
+
+       printf("   kernel_size:   0x%x\n", hdr->kernel_size);
+       printf("   kernel_addr:   0x%x\n", hdr->kernel_addr);
+
+       printf("   rdisk_size:   0x%x\n", hdr->ramdisk_size);
+       printf("   rdisk_addr:   0x%x\n", hdr->ramdisk_addr);
+
+       printf("   second_size:   0x%x\n", hdr->second_size);
+       printf("   second_addr:   0x%x\n", hdr->second_addr);
+
+       printf("   tags_addr:   0x%x\n", hdr->tags_addr);
+       printf("   page_size:   0x%x\n", hdr->page_size);
+
+       printf("   name:      %s\n", hdr->name);
+       printf("   cmdline:   %s\n", hdr->cmdline);
+
+       for (i = 0; i < 8; i++)
+               printf("   id[%d]:   0x%x\n", i, hdr->id[i]);
+#endif
+}
+
+#if !defined(CONFIG_AVB_SUPPORT) || !defined(CONFIG_MMC)
+static struct andr_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN);
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_AVB_ATX)
+static int sha256_concatenation(uint8_t *hash_buf, uint8_t *vbh, uint8_t *image_hash)
+{
+       if ((hash_buf == NULL) || (vbh == NULL) || (image_hash == NULL)) {
+               printf("sha256_concatenation: null buffer found!\n");
+               return -1;
+       }
+
+       memcpy(hash_buf, vbh, AVB_SHA256_DIGEST_SIZE);
+       memcpy(hash_buf + AVB_SHA256_DIGEST_SIZE,
+              image_hash, AVB_SHA256_DIGEST_SIZE);
+       sha256_csum_wd((unsigned char *)hash_buf, 2 * AVB_SHA256_DIGEST_SIZE,
+                      (unsigned char *)vbh, CHUNKSZ_SHA256);
+
+       return 0;
+}
+
+/* Since we use fit format to organize the atf, tee, u-boot and u-boot dtb,
+ * so calculate the hash of fit is enough.
+ */
+static int vbh_bootloader(uint8_t *image_hash)
+{
+       char* slot_suffixes[2] = {"_a", "_b"};
+       char partition_name[20];
+       AvbABData ab_data;
+       uint8_t *image_buf = NULL;
+       uint32_t image_size;
+       size_t image_num_read;
+       int target_slot;
+       int ret = 0;
+
+       /* Load A/B metadata and decide which slot we are going to load */
+       if (fsl_avb_ab_ops.read_ab_metadata(&fsl_avb_ab_ops, &ab_data) !=
+                                           AVB_IO_RESULT_OK) {
+               ret = -1;
+               goto fail ;
+       }
+       target_slot = get_curr_slot(&ab_data);
+       sprintf(partition_name, "bootloader%s", slot_suffixes[target_slot]);
+
+       /* Read image header to find the image size */
+       image_buf = (uint8_t *)malloc(MMC_SATA_BLOCK_SIZE);
+       if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, partition_name,
+                                           0, MMC_SATA_BLOCK_SIZE,
+                                           image_buf, &image_num_read)) {
+               printf("bootloader image load error!\n");
+               ret = -1;
+               goto fail;
+       }
+       image_size = fdt_totalsize((struct image_header *)image_buf);
+       image_size = (image_size + 3) & ~3;
+       free(image_buf);
+
+       /* Load full fit image */
+       image_buf = (uint8_t *)malloc(image_size);
+       if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, partition_name,
+                                           0, image_size,
+                                           image_buf, &image_num_read)) {
+               printf("bootloader image load error!\n");
+               ret = -1;
+               goto fail;
+       }
+       /* Calculate hash */
+       sha256_csum_wd((unsigned char *)image_buf, image_size,
+                      (unsigned char *)image_hash, CHUNKSZ_SHA256);
+
+fail:
+       if (image_buf != NULL)
+               free(image_buf);
+       return ret;
+}
+
+int vbh_calculate(uint8_t *vbh, AvbSlotVerifyData *avb_out_data)
+{
+       uint8_t image_hash[AVB_SHA256_DIGEST_SIZE];
+       uint8_t hash_buf[2 * AVB_SHA256_DIGEST_SIZE];
+       uint8_t* image_buf = NULL;
+       uint32_t image_size;
+       size_t image_num_read;
+       int ret = 0;
+
+       if (vbh == NULL)
+               return -1;
+
+       /* Initial VBH (VBH0) should be 32 bytes 0 */
+       memset(vbh, 0, AVB_SHA256_DIGEST_SIZE);
+       /* Load and calculate the sha256 hash of spl.bin */
+       image_size = (ANDROID_SPL_SIZE + MMC_SATA_BLOCK_SIZE -1) /
+                     MMC_SATA_BLOCK_SIZE;
+       image_buf = (uint8_t *)malloc(image_size);
+       if (fsl_avb_ops.read_from_partition(&fsl_avb_ops,
+                                           FASTBOOT_PARTITION_BOOTLOADER,
+                                           0, image_size,
+                                           image_buf, &image_num_read)) {
+               printf("spl image load error!\n");
+               ret = -1;
+               goto fail;
+       }
+       sha256_csum_wd((unsigned char *)image_buf, image_size,
+                      (unsigned char *)image_hash, CHUNKSZ_SHA256);
+       /* Calculate VBH1 */
+       if (sha256_concatenation(hash_buf, vbh, image_hash)) {
+               ret = -1;
+               goto fail;
+       }
+       free(image_buf);
+
+       /* Load and calculate hash of bootloader.img */
+       if (vbh_bootloader(image_hash)) {
+               ret = -1;
+               goto fail;
+       }
+       /* Calculate VBH2 */
+       if (sha256_concatenation(hash_buf, vbh, image_hash)) {
+               ret = -1;
+               goto fail;
+       }
+
+       /* Calculate the hash of vbmeta.img */
+       avb_slot_verify_data_calculate_vbmeta_digest(avb_out_data,
+                                                    AVB_DIGEST_TYPE_SHA256,
+                                                    image_hash);
+       /* Calculate VBH3 */
+       if (sha256_concatenation(hash_buf, vbh, image_hash)) {
+               ret = -1;
+               goto fail;
+       }
+
+fail:
+       if (image_buf != NULL)
+               free(image_buf);
+       return ret;
+}
+#endif /* CONFIG_DUAL_BOOTLOADER && CONFIG_AVB_ATX */
+
+int trusty_setbootparameter(struct andr_img_hdr *hdr, AvbABFlowResult avb_result,
+                           AvbSlotVerifyData *avb_out_data) {
+#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_AVB_ATX)
+       uint8_t vbh[AVB_SHA256_DIGEST_SIZE];
+#endif
+       int ret = 0;
+       u32 os_ver = hdr->os_version >> 11;
+       u32 os_ver_km = (((os_ver >> 14) & 0x7F) * 100 + ((os_ver >> 7) & 0x7F)) * 100
+           + (os_ver & 0x7F);
+       u32 os_lvl = hdr->os_version & ((1U << 11) - 1);
+       u32 os_lvl_km = ((os_lvl >> 4) + 2000) * 100 + (os_lvl & 0x0F);
+       keymaster_verified_boot_t vbstatus;
+       FbLockState lock_status = fastboot_get_lock_stat();
+
+       uint8_t boot_key_hash[AVB_SHA256_DIGEST_SIZE];
+#ifdef CONFIG_AVB_ATX
+       if (fsl_read_permanent_attributes_hash(&fsl_avb_atx_ops, boot_key_hash)) {
+               printf("ERROR - failed to read permanent attributes hash for keymaster\n");
+               memset(boot_key_hash, 0, AVB_SHA256_DIGEST_SIZE);
+       }
+#else
+       uint8_t public_key_buf[AVB_MAX_BUFFER_LENGTH];
+       if (trusty_read_vbmeta_public_key(public_key_buf,
+                                               AVB_MAX_BUFFER_LENGTH) != 0) {
+               printf("ERROR - failed to read public key for keymaster\n");
+               memset(boot_key_hash, 0, AVB_SHA256_DIGEST_SIZE);
+       } else
+               sha256_csum_wd((unsigned char *)public_key_buf, AVB_SHA256_DIGEST_SIZE,
+                               (unsigned char *)boot_key_hash, CHUNKSZ_SHA256);
+#endif
+
+       bool lock = (lock_status == FASTBOOT_LOCK)? true: false;
+       if (avb_result == AVB_AB_FLOW_RESULT_OK)
+               vbstatus = KM_VERIFIED_BOOT_VERIFIED;
+       else
+               vbstatus = KM_VERIFIED_BOOT_FAILED;
+
+       /* Calculate VBH */
+#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_AVB_ATX)
+       if (vbh_calculate(vbh, avb_out_data)) {
+               ret = -1;
+               goto fail;
+       }
+
+       trusty_set_boot_params(os_ver_km, os_lvl_km, vbstatus, lock,
+                              boot_key_hash, AVB_SHA256_DIGEST_SIZE,
+                              vbh, AVB_SHA256_DIGEST_SIZE);
+#else
+       trusty_set_boot_params(os_ver_km, os_lvl_km, vbstatus, lock,
+                              boot_key_hash, AVB_SHA256_DIGEST_SIZE,
+                              NULL, 0);
+#endif
+
+fail:
+       return ret;
+}
+#endif
+
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
+/* we can use avb to verify Trusty if we want */
+const char *requested_partitions_boot[] = {"boot", FDT_PART_NAME, NULL};
+const char *requested_partitions_recovery[] = {"recovery", FDT_PART_NAME, NULL};
+
+static bool is_load_fdt_from_part(void)
+{
+       bool ptn_find;
+
+#if defined(CONFIG_ANDROID_THINGS_SUPPORT)
+       ptn_find = fastboot_flash_find_ptn("oem_bootloader_a") &&
+               fastboot_flash_find_ptn("oem_bootloader_b");
+#elif defined(CONFIG_ANDROID_AB_SUPPORT)
+       ptn_find = fastboot_flash_find_ptn("dtbo_a") &&
+               fastboot_flash_find_ptn("dtbo_b");
+#else
+       ptn_find = fastboot_flash_find_ptn("dtbo");
+#endif
+
+       if (ptn_find)
+               return true;
+       else
+               return false;
+}
+
+static int find_partition_data_by_name(char* part_name,
+               AvbSlotVerifyData* avb_out_data, AvbPartitionData** avb_loadpart)
+{
+       int num = 0;
+       AvbPartitionData* loadpart = NULL;
+
+       for (num = 0; num < avb_out_data->num_loaded_partitions; num++) {
+               loadpart = &(avb_out_data->loaded_partitions[num]);
+               if (!(strncmp(loadpart->partition_name,
+                       part_name, strlen(part_name)))) {
+                       *avb_loadpart = loadpart;
+                       break;
+               }
+       }
+       if (num == avb_out_data->num_loaded_partitions) {
+               printf("Error! Can't find %s partition from avb partition data!\n",
+                               part_name);
+               return -1;
+       }
+       else
+               return 0;
+}
+
+int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
+
+       ulong addr = 0;
+       struct andr_img_hdr *hdr = NULL;
+       void *boot_buf = NULL;
+       ulong image_size;
+       u32 avb_metric;
+       bool check_image_arm64 =  false;
+       bool is_recovery_mode = false;
+
+       AvbABFlowResult avb_result;
+       AvbSlotVerifyData *avb_out_data = NULL;
+       AvbPartitionData *avb_loadpart = NULL;
+
+       /* get bootmode, default to boot "boot" */
+       if (argc > 1) {
+               is_recovery_mode =
+                       (strncmp(argv[1], "recovery", sizeof("recovery")) != 0) ? false: true;
+               if (is_recovery_mode)
+                       printf("Will boot from recovery!\n");
+       }
+
+       /* check lock state */
+       FbLockState lock_status = fastboot_get_lock_stat();
+       if (lock_status == FASTBOOT_LOCK_ERROR) {
+#ifdef CONFIG_AVB_ATX
+               printf("In boota get fastboot lock status error, enter fastboot mode.\n");
+               goto fail;
+#else
+               printf("In boota get fastboot lock status error. Set lock status\n");
+               fastboot_set_lock_stat(FASTBOOT_LOCK);
+               lock_status = FASTBOOT_LOCK;
+#endif
+       }
+       bool allow_fail = (lock_status == FASTBOOT_UNLOCK ? true : false);
+       avb_metric = get_timer(0);
+       /* we don't need to verify fdt partition if we don't have it. */
+       if (!is_load_fdt_from_part()) {
+               requested_partitions_boot[1] = NULL;
+               requested_partitions_recovery[1] = NULL;
+       }
+#ifndef CONFIG_SYSTEM_RAMDISK_SUPPORT
+       else if (is_recovery_mode){
+               requested_partitions_recovery[1] = NULL;
+       }
+#endif
+
+       /* if in lock state, do avb verify */
+#ifndef CONFIG_DUAL_BOOTLOADER
+       /* For imx6 on Android, we don't have a/b slot and we want to verify
+        * boot/recovery with AVB. For imx8 and Android Things we don't have
+        * recovery and support a/b slot for boot */
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+       /* we can use avb to verify Trusty if we want */
+       avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions_boot, allow_fail,
+                       AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
+#else
+#ifndef CONFIG_SYSTEM_RAMDISK_SUPPORT
+       if (!is_recovery_mode) {
+               avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions_boot, allow_fail,
+                               AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+       } else {
+               avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions_recovery, allow_fail,
+                               AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+       }
+#else /* CONFIG_SYSTEM_RAMDISK_SUPPORT defined */
+       avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions_boot, allow_fail,
+                       AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+#endif /*CONFIG_SYSTEM_RAMDISK_SUPPORT*/
+#endif
+#else /* !CONFIG_DUAL_BOOTLOADER */
+       /* We will only verify single one slot which has been selected in SPL */
+       avb_result = avb_flow_dual_uboot(&fsl_avb_ab_ops, requested_partitions_boot, allow_fail,
+                       AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
+
+       /* Reboot if current slot is not bootable. */
+       if (avb_result == AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS) {
+               printf("boota: slot verify fail!\n");
+               do_reset(NULL, 0, 0, NULL);
+       }
+#endif /* !CONFIG_DUAL_BOOTLOADER */
+
+       /* get the duration of avb */
+       metrics.avb = get_timer(avb_metric);
+
+       if ((avb_result == AVB_AB_FLOW_RESULT_OK) ||
+                       (avb_result == AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR)) {
+               assert(avb_out_data != NULL);
+               /* We may have more than one partition loaded by AVB, find the boot
+                * partition first.
+                */
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+               if (find_partition_data_by_name("boot", avb_out_data, &avb_loadpart))
+                       goto fail;
+#else
+               if (!is_recovery_mode) {
+                       if (find_partition_data_by_name("boot", avb_out_data, &avb_loadpart))
+                               goto fail;
+               } else {
+                       if (find_partition_data_by_name("recovery", avb_out_data, &avb_loadpart))
+                               goto fail;
+               }
+#endif
+               assert(avb_loadpart != NULL);
+               /* we should use avb_part_data->data as boot image */
+               /* boot image is already read by avb */
+               hdr = (struct andr_img_hdr *)avb_loadpart->data;
+               if (android_image_check_header(hdr)) {
+                       printf("boota: bad boot image magic\n");
+                       goto fail;
+               }
+               if (avb_result == AVB_AB_FLOW_RESULT_OK)
+                       printf(" verify OK, boot '%s%s'\n",
+                                       avb_loadpart->partition_name, avb_out_data->ab_suffix);
+               else {
+                       printf(" verify FAIL, state: UNLOCK\n");
+                       printf(" boot '%s%s' still\n",
+                                       avb_loadpart->partition_name, avb_out_data->ab_suffix);
+               }
+               char bootargs_sec[ANDR_BOOT_EXTRA_ARGS_SIZE];
+               if (lock_status == FASTBOOT_LOCK) {
+                       snprintf(bootargs_sec, sizeof(bootargs_sec),
+                                       "androidboot.verifiedbootstate=green androidboot.slot_suffix=%s %s",
+                                       avb_out_data->ab_suffix, avb_out_data->cmdline);
+               } else {
+                       snprintf(bootargs_sec, sizeof(bootargs_sec),
+                                       "androidboot.verifiedbootstate=orange androidboot.slot_suffix=%s %s",
+                                       avb_out_data->ab_suffix, avb_out_data->cmdline);
+               }
+               env_set("bootargs_sec", bootargs_sec);
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+               if(!is_recovery_mode) {
+                       if(avb_out_data->cmdline != NULL && strstr(avb_out_data->cmdline, "root="))
+                               fastboot_setup_system_boot_args(avb_out_data->ab_suffix, false);
+                       else
+                               fastboot_setup_system_boot_args(avb_out_data->ab_suffix, true);
+               }
+#endif /* CONFIG_SYSTEM_RAMDISK_SUPPORT */
+               image_size = avb_loadpart->data_size;
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+               /* If we are using uncompressed kernel image, copy it directly to
+                * hdr->kernel_addr, if we are using compressed lz4 kernel image,
+                * we need to decompress the kernel image first. */
+               if (image_arm64((void *)((ulong)hdr + hdr->page_size))) {
+                       memcpy((void *)(long)hdr->kernel_addr,
+                                       (void *)((ulong)hdr + hdr->page_size), hdr->kernel_size);
+               } else {
+#ifdef CONFIG_LZ4
+                       size_t lz4_len = DST_DECOMPRESS_LEN;
+                       if (ulz4fn((void *)((ulong)hdr + hdr->page_size),
+                                               hdr->kernel_size, (void *)(ulong)hdr->kernel_addr, &lz4_len) != 0) {
+                               printf("Decompress kernel fail!\n");
+                               goto fail;
+                       }
+#else /* CONFIG_LZ4 */
+                       printf("please enable CONFIG_LZ4 if we're using compressed lz4 kernel image!\n");
+                       goto fail;
+#endif /* CONFIG_LZ4 */
+               }
+#else /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+               /* copy kernel image and boot header to hdr->kernel_addr - hdr->page_size */
+               memcpy((void *)(ulong)(hdr->kernel_addr - hdr->page_size), (void *)hdr,
+                               hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size));
+#endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+       } else {
+               /* Fall into fastboot mode if get unacceptable error from avb
+                * or verify fail in lock state.
+                */
+               if (lock_status == FASTBOOT_LOCK)
+                       printf(" verify FAIL, state: LOCK\n");
+
+               goto fail;
+       }
+
+       flush_cache((ulong)image_load_addr, image_size);
+       check_image_arm64  = image_arm64((void *)(ulong)hdr->kernel_addr);
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+       if (is_recovery_mode)
+               memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size
+                               + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
+#else
+       memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size
+                       + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
+#endif
+#ifdef CONFIG_OF_LIBFDT
+       /* load the dtb file */
+       u32 fdt_size = 0;
+       struct dt_table_header *dt_img = NULL;
+
+       if (is_load_fdt_from_part()) {
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+               if (find_partition_data_by_name("oem_bootloader",
+                                       avb_out_data, &avb_loadpart)) {
+                       goto fail;
+               } else
+                       dt_img = (struct dt_table_header *)avb_loadpart->data;
+#elif defined(CONFIG_SYSTEM_RAMDISK_SUPPORT) /* It means boot.img(recovery) do not include dtb, it need load dtb from partition */
+               if (find_partition_data_by_name("dtbo",
+                                       avb_out_data, &avb_loadpart)) {
+                       goto fail;
+               } else
+                       dt_img = (struct dt_table_header *)avb_loadpart->data;
+#else /* recovery.img include dts while boot.img use dtbo */
+               if (is_recovery_mode) {
+                       if (hdr->header_version != 1) {
+                               printf("boota: boot image header version error!\n");
+                               goto fail;
+                       }
+
+                       dt_img = (struct dt_table_header *)((void *)(ulong)hdr +
+                                               hdr->page_size +
+                                               ALIGN(hdr->kernel_size, hdr->page_size) +
+                                               ALIGN(hdr->ramdisk_size, hdr->page_size) +
+                                               ALIGN(hdr->second_size, hdr->page_size));
+               } else if (find_partition_data_by_name("dtbo",
+                                               avb_out_data, &avb_loadpart)) {
+                       goto fail;
+               } else
+                       dt_img = (struct dt_table_header *)avb_loadpart->data;
+#endif
+
+               if (be32_to_cpu(dt_img->magic) != DT_TABLE_MAGIC) {
+                       printf("boota: bad dt table magic %08x\n",
+                                       be32_to_cpu(dt_img->magic));
+                       goto fail;
+               } else if (!be32_to_cpu(dt_img->dt_entry_count)) {
+                       printf("boota: no dt entries\n");
+                       goto fail;
+               }
+
+               struct dt_table_entry *dt_entry;
+               dt_entry = (struct dt_table_entry *)((ulong)dt_img +
+                               be32_to_cpu(dt_img->dt_entries_offset));
+               fdt_size = be32_to_cpu(dt_entry->dt_size);
+               memcpy((void *)(ulong)hdr->second_addr, (void *)((ulong)dt_img +
+                               be32_to_cpu(dt_entry->dt_offset)), fdt_size);
+       } else {
+               if (hdr->second_size && hdr->second_addr) {
+                       memcpy((void *)(ulong)hdr->second_addr,
+                               (void *)(ulong)hdr + hdr->page_size
+                               + ALIGN(hdr->kernel_size, hdr->page_size)
+                               + ALIGN(hdr->ramdisk_size, hdr->page_size),
+                               hdr->second_size);
+               }
+       }
+#endif /*CONFIG_OF_LIBFDT*/
+
+       if (check_image_arm64) {
+               android_image_get_kernel(hdr, 0, NULL, NULL);
+               addr = hdr->kernel_addr;
+       } else {
+               addr = (ulong)(hdr->kernel_addr - hdr->page_size);
+       }
+       printf("kernel   @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);
+       printf("ramdisk  @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);
+#ifdef CONFIG_OF_LIBFDT
+       if (is_load_fdt_from_part()) {
+               if (fdt_size)
+                       printf("fdt      @ %08x (%d)\n", hdr->second_addr, fdt_size);
+       } else {
+               if (hdr->second_size)
+                       printf("fdt      @ %08x (%d)\n", hdr->second_addr, hdr->second_size);
+       }
+#endif /*CONFIG_OF_LIBFDT*/
+
+       char boot_addr_start[12];
+       char ramdisk_addr[25];
+       char fdt_addr[12];
+
+       char *boot_args[] = { NULL, boot_addr_start, ramdisk_addr, fdt_addr};
+       if (check_image_arm64)
+               boot_args[0] = "booti";
+       else
+               boot_args[0] = "bootm";
+
+       sprintf(boot_addr_start, "0x%lx", addr);
+       sprintf(ramdisk_addr, "0x%x:0x%x", hdr->ramdisk_addr, hdr->ramdisk_size);
+       sprintf(fdt_addr, "0x%x", hdr->second_addr);
+
+/* no need to pass ramdisk addr for normal boot mode when enable CONFIG_SYSTEM_RAMDISK_SUPPORT*/
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+       if (!is_recovery_mode)
+               boot_args[2] = NULL;
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+       /* Trusty keymaster needs some parameters before it work */
+       if (trusty_setbootparameter(hdr, avb_result, avb_out_data))
+               goto fail;
+       /* lock the boot status and rollback_idx preventing Linux modify it */
+       trusty_lock_boot_state();
+       /* put ql-tipc to release resource for Linux */
+       trusty_ipc_shutdown();
+#endif
+
+       if (avb_out_data != NULL)
+               avb_slot_verify_data_free(avb_out_data);
+       if (boot_buf != NULL)
+               free(boot_buf);
+
+       if (check_image_arm64) {
+#ifdef CONFIG_CMD_BOOTI
+               do_booti(NULL, 0, 4, boot_args);
+#else
+               debug("please enable CONFIG_CMD_BOOTI when kernel are Image");
+#endif
+       } else {
+               do_bootm(NULL, 0, 4, boot_args);
+       }
+
+       /* This only happens if image is somehow faulty so we start over */
+       do_reset(NULL, 0, 0, NULL);
+
+       return 1;
+
+fail:
+       /* avb has no recovery */
+       if (avb_out_data != NULL)
+               avb_slot_verify_data_free(avb_out_data);
+
+       return run_command("fastboot 0", 0);
+}
+
+U_BOOT_CMD(
+       boota,  2,      1,      do_boota,
+       "boota   - boot android bootimg \n",
+       "boot from current mmc with avb verify\n"
+);
+
+#else /* CONFIG_AVB_SUPPORT */
+/* boota <addr> [ mmc0 | mmc1 [ <partition> ] ] */
+int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       ulong addr = 0;
+       char *ptn = "boot";
+       int mmcc = -1;
+       struct andr_img_hdr *hdr = &boothdr;
+       ulong image_size;
+       bool check_image_arm64 =  false;
+       int i = 0;
+
+       for (i = 0; i < argc; i++)
+               printf("%s ", argv[i]);
+       printf("\n");
+
+       if (argc < 2)
+               return -1;
+
+       mmcc = simple_strtoul(argv[1]+3, NULL, 10);
+
+       if (argc > 2)
+               ptn = argv[2];
+
+       if (mmcc != -1) {
+#ifdef CONFIG_MMC
+               struct fastboot_ptentry *pte;
+               struct mmc *mmc;
+               struct disk_partition info;
+               struct blk_desc *dev_desc = NULL;
+               unsigned bootimg_sectors;
+
+               memset((void *)&info, 0 , sizeof(struct disk_partition));
+               /* i.MX use MBR as partition table, so this will have
+                  to find the start block and length for the
+                  partition name and register the fastboot pte we
+                  define the partition number of each partition in
+                  config file
+                */
+               mmc = find_mmc_device(mmcc);
+               if (!mmc) {
+                       printf("boota: cannot find '%d' mmc device\n", mmcc);
+                       goto fail;
+               }
+               dev_desc = blk_get_dev("mmc", mmcc);
+               if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
+                       printf("** Block device MMC %d not supported\n", mmcc);
+                       goto fail;
+               }
+
+               /* below was i.MX mmc operation code */
+               if (mmc_init(mmc)) {
+                       printf("mmc%d init failed\n", mmcc);
+                       goto fail;
+               }
+
+               pte = fastboot_flash_find_ptn(ptn);
+               if (!pte) {
+                       printf("boota: cannot find '%s' partition\n", ptn);
+                       fastboot_flash_dump_ptn();
+                       goto fail;
+               }
+
+               if (blk_dread(dev_desc, pte->start,
+                                             1, (void *)hdr) < 0) {
+                       printf("boota: mmc failed to read bootimg header\n");
+                       goto fail;
+               }
+
+               if (android_image_check_header(hdr)) {
+                       printf("boota: bad boot image magic\n");
+                       goto fail;
+               }
+
+               image_size = android_image_get_end(hdr) - (ulong)hdr;
+               bootimg_sectors = image_size/512;
+
+               if (blk_dread(dev_desc, pte->start,
+                                       bootimg_sectors,
+                                       (void *)(hdr->kernel_addr - hdr->page_size)) < 0) {
+                       printf("boota: mmc failed to read bootimage\n");
+                       goto fail;
+               }
+               check_image_arm64  = image_arm64((void *)hdr->kernel_addr);
+#if defined(CONFIG_FASTBOOT_LOCK)
+               int verifyresult = -1;
+#endif
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+               int lock_status = fastboot_get_lock_stat();
+               if (lock_status == FASTBOOT_LOCK_ERROR) {
+                       printf("In boota get fastboot lock status error. Set lock status\n");
+                       fastboot_set_lock_stat(FASTBOOT_LOCK);
+               }
+               display_lock(fastboot_get_lock_stat(), verifyresult);
+#endif
+               /* load the ramdisk file */
+               memcpy((void *)hdr->ramdisk_addr, (void *)hdr->kernel_addr
+                       + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
+
+#ifdef CONFIG_OF_LIBFDT
+               u32 fdt_size = 0;
+               /* load the dtb file */
+               if (hdr->second_addr) {
+                       u32 zimage_size = ((u32 *)hdrload->kernel_addr)[ZIMAGE_END_ADDR]
+                                       - ((u32 *)hdrload->kernel_addr)[ZIMAGE_START_ADDR];
+                       fdt_size = hdrload->kernel_size - zimage_size;
+                       memcpy((void *)(ulong)hdrload->second_addr,
+                                       (void*)(ulong)hdrload->kernel_addr + zimage_size, fdt_size);
+               }
+#endif /*CONFIG_OF_LIBFDT*/
+
+#else /*! CONFIG_MMC*/
+               return -1;
+#endif /*! CONFIG_MMC*/
+       } else {
+               printf("boota: parameters is invalid. only support mmcX device\n");
+               return -1;
+       }
+
+       printf("kernel   @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);
+       printf("ramdisk  @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);
+#ifdef CONFIG_OF_LIBFDT
+       if (fdt_size)
+               printf("fdt      @ %08x (%d)\n", hdr->second_addr, fdt_size);
+#endif /*CONFIG_OF_LIBFDT*/
+
+
+       char boot_addr_start[12];
+       char ramdisk_addr[25];
+       char fdt_addr[12];
+       char *boot_args[] = { NULL, boot_addr_start, ramdisk_addr, fdt_addr};
+       if (check_image_arm64 ) {
+               addr = hdr->kernel_addr;
+               boot_args[0] = "booti";
+       } else {
+               addr = hdr->kernel_addr - hdr->page_size;
+               boot_args[0] = "bootm";
+       }
+
+       sprintf(boot_addr_start, "0x%lx", addr);
+       sprintf(ramdisk_addr, "0x%x:0x%x", hdr->ramdisk_addr, hdr->ramdisk_size);
+       sprintf(fdt_addr, "0x%x", hdr->second_addr);
+       if (check_image_arm64) {
+               android_image_get_kernel(hdr, 0, NULL, NULL);
+#ifdef CONFIG_CMD_BOOTI
+               do_booti(NULL, 0, 4, boot_args);
+#else
+               debug("please enable CONFIG_CMD_BOOTI when kernel are Image");
+#endif
+       } else {
+               do_bootm(NULL, 0, 4, boot_args);
+       }
+       /* This only happens if image is somehow faulty so we start over */
+       do_reset(NULL, 0, 0, NULL);
+
+       return 1;
+
+fail:
+#if defined(CONFIG_FSL_FASTBOOT)
+       return run_command("fastboot 0", 0);
+#else /*! CONFIG_FSL_FASTBOOT*/
+       return -1;
+#endif /*! CONFIG_FSL_FASTBOOT*/
+}
+
+U_BOOT_CMD(
+       boota,  3,      1,      do_boota,
+       "boota   - boot android bootimg from memory\n",
+       "[<addr> | mmc0 | mmc1 | mmc2 | mmcX] [<partition>]\n    "
+       "- boot application image stored in memory or mmc\n"
+       "\t'addr' should be the address of boot image "
+       "which is zImage+ramdisk.img\n"
+       "\t'mmcX' is the mmc device you store your boot.img, "
+       "which will read the boot.img from 1M offset('/boot' partition)\n"
+       "\t 'partition' (optional) is the partition id of your device, "
+       "if no partition give, will going to 'boot' partition\n"
+);
+#endif /* CONFIG_AVB_SUPPORT */
+#endif /* CONFIG_CMD_BOOTA */
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_command.c b/drivers/fastboot/fb_fsl/fb_fsl_command.c
new file mode 100644 (file)
index 0000000..71e21eb
--- /dev/null
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <asm/mach-imx/sys_proto.h>
+#include <fb_fsl.h>
+#include <fastboot.h>
+#include <fastboot-internal.h>
+#include <mmc.h>
+#include <android_image.h>
+#include <asm/bootm.h>
+#include <nand.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+#include <image.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/setup.h>
+#include <env.h>
+#ifdef CONFIG_ANDROID_RECOVERY
+#include <recovery.h>
+#endif
+
+#ifdef CONFIG_BCB_SUPPORT
+#include "bcb.h"
+#endif
+
+#ifdef CONFIG_AVB_SUPPORT
+#include <dt_table.h>
+#include <fsl_avb.h>
+#endif
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+#include <asm-generic/gpio.h>
+#include <asm/mach-imx/gpio.h>
+#include "../lib/avb/fsl/fsl_avbkey.h"
+#include "../arch/arm/include/asm/mach-imx/hab.h"
+#endif
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+#include "fastboot_lock_unlock.h"
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#include "u-boot/sha256.h"
+#include <trusty/libtipc.h>
+#endif
+
+#include "fb_fsl_common.h"
+
+#define EP_BUFFER_SIZE                 4096
+
+/**
+ * fastboot_bytes_received - number of bytes received in the current download
+ */
+static u32 fastboot_bytes_received;
+
+/**
+ * fastboot_bytes_expected - number of bytes expected in the current download
+ */
+static u32 fastboot_bytes_expected;
+
+
+/* Write the bcb with fastboot bootloader commands */
+static void enable_fastboot_command(void)
+{
+#ifdef CONFIG_BCB_SUPPORT
+       char fastboot_command[32] = {0};
+       strncpy(fastboot_command, FASTBOOT_BCB_CMD, 31);
+       bcb_write_command(fastboot_command);
+#endif
+}
+
+/* Get the Boot mode from BCB cmd or Key pressed */
+static FbBootMode fastboot_get_bootmode(void)
+{
+       int boot_mode = BOOTMODE_NORMAL;
+#ifdef CONFIG_ANDROID_RECOVERY
+       if(is_recovery_key_pressing()) {
+               boot_mode = BOOTMODE_RECOVERY_KEY_PRESSED;
+               return boot_mode;
+       }
+#endif
+#ifdef CONFIG_BCB_SUPPORT
+       int ret = 0;
+       char command[32];
+       ret = bcb_read_command(command);
+       if (ret < 0) {
+               printf("read command failed\n");
+               return boot_mode;
+       }
+       if (!strcmp(command, FASTBOOT_BCB_CMD)) {
+               boot_mode = BOOTMODE_FASTBOOT_BCB_CMD;
+       }
+#ifdef CONFIG_ANDROID_RECOVERY
+       else if (!strcmp(command, RECOVERY_BCB_CMD)) {
+               boot_mode = BOOTMODE_RECOVERY_BCB_CMD;
+       }
+#endif
+
+       /* Clean the mode once its read out,
+          no matter what in the mode string */
+       memset(command, 0, 32);
+       bcb_write_command(command);
+#endif
+       return boot_mode;
+}
+
+/* export to lib_arm/board.c */
+void fastboot_run_bootmode(void)
+{
+       FbBootMode boot_mode = fastboot_get_bootmode();
+       switch(boot_mode){
+       case BOOTMODE_FASTBOOT_BCB_CMD:
+               /* Make the boot into fastboot mode*/
+               puts("Fastboot: Got bootloader commands!\n");
+               run_command("fastboot 0", 0);
+               break;
+#ifdef CONFIG_ANDROID_RECOVERY
+       case BOOTMODE_RECOVERY_BCB_CMD:
+       case BOOTMODE_RECOVERY_KEY_PRESSED:
+               /* Make the boot into recovery mode */
+               puts("Fastboot: Got Recovery key pressing or recovery commands!\n");
+               board_recovery_setup();
+               break;
+#endif
+       default:
+               /* skip special mode boot*/
+               puts("Fastboot: Normal\n");
+               break;
+       }
+}
+
+
+
+/**
+ * okay() - Send bare OKAY response
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ *
+ * Send a bare OKAY fastboot response. This is used where the command is
+ * valid, but all the work is done after the response has been sent (e.g.
+ * boot, reboot etc.)
+ */
+static void okay(char *cmd_parameter, char *response)
+{
+       fastboot_okay(NULL, response);
+}
+
+/**
+ * getvar() - Read a config/version variable
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void getvar(char *cmd_parameter, char *response)
+{
+       fastboot_getvar(cmd_parameter, response);
+}
+
+/**
+ * reboot_bootloader() - Sets reboot bootloader flag.
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void reboot_bootloader(char *cmd_parameter, char *response)
+{
+       enable_fastboot_command();
+
+       if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER))
+               fastboot_fail("Cannot set reboot flag", response);
+       else
+               fastboot_okay(NULL, response);
+}
+
+static void upload(char *cmd_parameter, char *response)
+{
+       if (!fastboot_bytes_received || fastboot_bytes_received > (EP_BUFFER_SIZE * 32)) {
+               fastboot_fail("", response);
+               return;
+       }
+
+       printf("Will upload %d bytes.\n", fastboot_bytes_received);
+       snprintf(response, FASTBOOT_RESPONSE_LEN, "DATA%08x", fastboot_bytes_received);
+       fastboot_tx_write_more(response);
+
+       fastboot_tx_write((const char *)(fastboot_buf_addr), fastboot_bytes_received);
+
+       snprintf(response,FASTBOOT_RESPONSE_LEN, "OKAY");
+       fastboot_tx_write_more(response);
+
+       fastboot_none_resp(response);
+}
+
+/**
+ * fastboot_download() - Start a download transfer from the client
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void download(char *cmd_parameter, char *response)
+{
+       char *tmp;
+
+       if (!cmd_parameter) {
+               fastboot_fail("Expected command parameter", response);
+               return;
+       }
+       fastboot_bytes_received = 0;
+       fastboot_bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16);
+       if (fastboot_bytes_expected == 0) {
+               fastboot_fail("Expected nonzero image size", response);
+               return;
+       }
+       /*
+        * Nothing to download yet. Response is of the form:
+        * [DATA|FAIL]$cmd_parameter
+        *
+        * where cmd_parameter is an 8 digit hexadecimal number
+        */
+       if (fastboot_bytes_expected > fastboot_buf_size) {
+               fastboot_fail(cmd_parameter, response);
+       } else {
+               printf("Starting download of %d bytes\n",
+                      fastboot_bytes_expected);
+               fastboot_response("DATA", response, "%s", cmd_parameter);
+       }
+}
+
+/**
+ * fastboot_data_remaining() - return bytes remaining in current transfer
+ *
+ * Return: Number of bytes left in the current download
+ */
+u32 fastboot_data_remaining(void)
+{
+       if (fastboot_bytes_received >= fastboot_bytes_expected)
+               return 0;
+
+       return fastboot_bytes_expected - fastboot_bytes_received;
+}
+
+/**
+ * fastboot_data_download() - Copy image data to fastboot_buf_addr.
+ *
+ * @fastboot_data: Pointer to received fastboot data
+ * @fastboot_data_len: Length of received fastboot data
+ * @response: Pointer to fastboot response buffer
+ *
+ * Copies image data from fastboot_data to fastboot_buf_addr. Writes to
+ * response. fastboot_bytes_received is updated to indicate the number
+ * of bytes that have been transferred.
+ *
+ * On completion sets image_size and ${filesize} to the total size of the
+ * downloaded image.
+ */
+void fastboot_data_download(const void *fastboot_data,
+                           unsigned int fastboot_data_len,
+                           char *response)
+{
+#define BYTES_PER_DOT  0x20000
+       u32 pre_dot_num, now_dot_num;
+
+       if (fastboot_data_len == 0 ||
+           (fastboot_bytes_received + fastboot_data_len) >
+           fastboot_bytes_expected) {
+               fastboot_fail("Received invalid data length",
+                             response);
+               return;
+       }
+       /* Download data to fastboot_buf_addr */
+       memcpy(fastboot_buf_addr + fastboot_bytes_received,
+              fastboot_data, fastboot_data_len);
+
+       pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
+       fastboot_bytes_received += fastboot_data_len;
+       now_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
+
+       if (pre_dot_num != now_dot_num) {
+               putc('.');
+               if (!(now_dot_num % 74))
+                       putc('\n');
+       }
+       *response = '\0';
+}
+
+/**
+ * fastboot_data_complete() - Mark current transfer complete
+ *
+ * @response: Pointer to fastboot response buffer
+ *
+ * Set image_size and ${filesize} to the total size of the downloaded image.
+ */
+void fastboot_data_complete(char *response)
+{
+       /* Download complete. Respond with "OKAY" */
+       fastboot_okay(NULL, response);
+       printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received);
+       env_set_hex("filesize", fastboot_bytes_received);
+       env_set_hex("fastboot_bytes", fastboot_bytes_received);
+       fastboot_bytes_expected = 0;
+}
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+static int partition_table_valid(void)
+{
+       int status, mmc_no;
+       struct blk_desc *dev_desc;
+#if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_ARM64)
+       /* Prevent other partition accessing when no TOS flashed. */
+       if (!tos_flashed)
+               return 0;
+#endif
+       struct disk_partition info;
+       mmc_no = fastboot_devinfo.dev_id;
+       dev_desc = blk_get_dev("mmc", mmc_no);
+       if (dev_desc)
+               status = part_get_info(dev_desc, 1, &info);
+       else
+               status = -1;
+       return (status == 0);
+}
+
+static void wipe_all_userdata(void)
+{
+       char response[FASTBOOT_RESPONSE_LEN];
+
+       /* Erase all user data */
+       printf("Start userdata wipe process....\n");
+       /* Erase /data partition */
+       fastboot_wipe_data_partition();
+
+#if defined (CONFIG_ANDROID_SUPPORT) || defined (CONFIG_ANDROID_AUTO_SUPPORT)
+       /* Erase the misc partition. */
+       process_erase_mmc(FASTBOOT_PARTITION_MISC, response);
+#endif
+
+#ifndef CONFIG_ANDROID_AB_SUPPORT
+       /* Erase the cache partition for legacy imx6/7 */
+       process_erase_mmc(FASTBOOT_PARTITION_CACHE, response);
+#endif
+       /* The unlock permissive flag is set by user and should be wiped here. */
+       set_fastboot_lock_disable();
+
+
+#if defined(AVB_RPMB) && !defined(CONFIG_IMX_TRUSTY_OS)
+       printf("Start stored_rollback_index wipe process....\n");
+       rbkidx_erase();
+       printf("Wipe stored_rollback_index completed.\n");
+#endif
+       printf("Wipe userdata completed.\n");
+}
+
+static FbLockState do_fastboot_unlock(bool force)
+{
+       int status;
+
+       if (fastboot_get_lock_stat() == FASTBOOT_UNLOCK) {
+               printf("The device is already unlocked\n");
+               return FASTBOOT_UNLOCK;
+       }
+       if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) {
+               printf("It is able to unlock device. %d\n",fastboot_lock_enable());
+               status = fastboot_set_lock_stat(FASTBOOT_UNLOCK);
+               if (status < 0)
+                       return FASTBOOT_LOCK_ERROR;
+
+               wipe_all_userdata();
+
+       } else {
+               printf("It is not able to unlock device.");
+               return FASTBOOT_LOCK_ERROR;
+       }
+
+       return FASTBOOT_UNLOCK;
+}
+
+static FbLockState do_fastboot_lock(void)
+{
+       int status;
+
+       if (fastboot_get_lock_stat() == FASTBOOT_LOCK) {
+               printf("The device is already locked\n");
+               return FASTBOOT_LOCK;
+       }
+       status = fastboot_set_lock_stat(FASTBOOT_LOCK);
+       if (status < 0)
+               return FASTBOOT_LOCK_ERROR;
+
+       wipe_all_userdata();
+
+       return FASTBOOT_LOCK;
+}
+
+static bool endswith(char* s, char* subs) {
+       if (!s || !subs)
+               return false;
+       uint32_t len = strlen(s);
+       uint32_t sublen = strlen(subs);
+       if (len < sublen) {
+               return false;
+       }
+       if (strncmp(s + len - sublen, subs, sublen)) {
+               return false;
+       }
+       return true;
+}
+
+static void flashing(char *cmd, char *response)
+{
+       FbLockState status;
+       FbLockEnableResult result;
+       if (endswith(cmd, "lock_critical")) {
+               strcpy(response, "OKAY");
+       }
+#ifdef CONFIG_AVB_ATX
+       else if (endswith(cmd, FASTBOOT_AVB_AT_PERM_ATTR)) {
+               if (avb_atx_fuse_perm_attr(fastboot_buf_addr, fastboot_bytes_received))
+                       strcpy(response, "FAILInternal error!");
+               else
+                       strcpy(response, "OKAY");
+       } else if (endswith(cmd, FASTBOOT_AT_GET_UNLOCK_CHALLENGE)) {
+               if (avb_atx_get_unlock_challenge(fsl_avb_ops.atx_ops,
+                                               fastboot_buf_addr, &fastboot_bytes_received))
+                       strcpy(response, "FAILInternal error!");
+               else
+                       strcpy(response, "OKAY");
+       } else if (endswith(cmd, FASTBOOT_AT_UNLOCK_VBOOT)) {
+               if (at_unlock_vboot_is_disabled()) {
+                       printf("unlock vboot already disabled, can't unlock the device!\n");
+                       strcpy(response, "FAILunlock vboot already disabled!.");
+               } else {
+#ifdef CONFIG_AT_AUTHENTICATE_UNLOCK
+                       if (avb_atx_verify_unlock_credential(fsl_avb_ops.atx_ops,
+                                                               fastboot_buf_addr))
+                               strcpy(response, "FAILIncorrect unlock credential!");
+                       else {
+#endif
+                               status = do_fastboot_unlock(true);
+                               if (status != FASTBOOT_LOCK_ERROR)
+                                       strcpy(response, "OKAY");
+                               else
+                                       strcpy(response, "FAILunlock device failed.");
+#ifdef CONFIG_AT_AUTHENTICATE_UNLOCK
+                       }
+#endif
+               }
+       } else if (endswith(cmd, FASTBOOT_AT_LOCK_VBOOT)) {
+               if (perm_attr_are_fused()) {
+                       status = do_fastboot_lock();
+                       if (status != FASTBOOT_LOCK_ERROR)
+                               strcpy(response, "OKAY");
+                       else
+                               strcpy(response, "FAILlock device failed.");
+               } else
+                       strcpy(response, "FAILpermanent attributes not fused!");
+       } else if (endswith(cmd, FASTBOOT_AT_DISABLE_UNLOCK_VBOOT)) {
+               /* This command can only be called after 'oem at-lock-vboot' */
+               status = fastboot_get_lock_stat();
+               if (status == FASTBOOT_LOCK) {
+                       if (at_unlock_vboot_is_disabled()) {
+                               printf("unlock vboot already disabled!\n");
+                               strcpy(response, "OKAY");
+                       }
+                       else {
+                               if (!at_disable_vboot_unlock())
+                                       strcpy(response, "OKAY");
+                               else
+                                       strcpy(response, "FAILdisable unlock vboot fail!");
+                       }
+               } else
+                       strcpy(response, "FAILplease lock the device first!");
+       }
+#endif /* CONFIG_AVB_ATX */
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+       else if (endswith(cmd, FASTBOOT_BOOTLOADER_VBOOT_KEY)) {
+               strcpy(response, "OKAY");
+       }
+#endif /* CONFIG_ANDROID_THINGS_SUPPORT */
+#ifdef CONFIG_IMX_TRUSTY_OS
+       else if (endswith(cmd, FASTBOOT_GET_CA_REQ)) {
+               uint8_t *ca_output;
+               uint32_t ca_length, cp_length;
+               if (trusty_atap_get_ca_request(fastboot_buf_addr, fastboot_bytes_received,
+                                               &(ca_output), &ca_length)) {
+                       printf("ERROR get_ca_request failed!\n");
+                       strcpy(response, "FAILInternal error!");
+               } else {
+                       cp_length = min((uint32_t)CONFIG_FASTBOOT_BUF_SIZE, ca_length);
+                       memcpy(fastboot_buf_addr, ca_output, cp_length);
+                       fastboot_bytes_received = ca_length;
+                       strcpy(response, "OKAY");
+               }
+
+       } else if (endswith(cmd, FASTBOOT_SET_CA_RESP)) {
+               if (trusty_atap_set_ca_response(fastboot_buf_addr, fastboot_bytes_received)) {
+                       printf("ERROR set_ca_response failed!\n");
+                       strcpy(response, "FAILInternal error!");
+               } else
+                       strcpy(response, "OKAY");
+       } else if (endswith(cmd, FASTBOOT_SET_RSA_ATTESTATION_KEY)) {
+               if (trusty_set_attestation_key(fastboot_buf_addr,
+                                               fastboot_bytes_received,
+                                               KM_ALGORITHM_RSA)) {
+                       printf("ERROR set rsa attestation key failed!\n");
+                       strcpy(response, "FAILInternal error!");
+               } else {
+                       printf("Set rsa attestation key successfully!\n");
+                       strcpy(response, "OKAY");
+               }
+       } else if (endswith(cmd, FASTBOOT_SET_EC_ATTESTATION_KEY)) {
+               if (trusty_set_attestation_key(fastboot_buf_addr,
+                                               fastboot_bytes_received,
+                                               KM_ALGORITHM_EC)) {
+                       printf("ERROR set ec attestation key failed!\n");
+                       strcpy(response, "FAILInternal error!");
+               } else {
+                       printf("Set ec attestation key successfully!\n");
+                       strcpy(response, "OKAY");
+               }
+       } else if (endswith(cmd, FASTBOOT_APPEND_RSA_ATTESTATION_CERT)) {
+               if (trusty_append_attestation_cert_chain(fastboot_buf_addr,
+                                                       fastboot_bytes_received,
+                                                       KM_ALGORITHM_RSA)) {
+                       printf("ERROR append rsa attestation cert chain failed!\n");
+                       strcpy(response, "FAILInternal error!");
+               } else {
+                       printf("Append rsa attestation key successfully!\n");
+                       strcpy(response, "OKAY");
+               }
+       }  else if (endswith(cmd, FASTBOOT_APPEND_EC_ATTESTATION_CERT)) {
+               if (trusty_append_attestation_cert_chain(fastboot_buf_addr,
+                                                       fastboot_bytes_received,
+                                                       KM_ALGORITHM_EC)) {
+                       printf("ERROR append ec attestation cert chain failed!\n");
+                       strcpy(response, "FAILInternal error!");
+               } else {
+                       printf("Append ec attestation key successfully!\n");
+                       strcpy(response, "OKAY");
+               }
+       }
+#ifndef CONFIG_AVB_ATX
+       else if (endswith(cmd, FASTBOOT_SET_RPMB_KEY)) {
+               if (fastboot_set_rpmb_key(fastboot_buf_addr, fastboot_bytes_received)) {
+                       printf("ERROR set rpmb key failed!\n");
+                       strcpy(response, "FAILset rpmb key failed!");
+               } else
+                       strcpy(response, "OKAY");
+       } else if (endswith(cmd, FASTBOOT_SET_RPMB_RANDOM_KEY)) {
+               if (fastboot_set_rpmb_random_key()) {
+                       printf("ERROR set rpmb random key failed!\n");
+                       strcpy(response, "FAILset rpmb random key failed!");
+               } else
+                       strcpy(response, "OKAY");
+       } else if (endswith(cmd, FASTBOOT_SET_VBMETA_PUBLIC_KEY)) {
+               if (avb_set_public_key(fastboot_buf_addr,
+                                       fastboot_bytes_received))
+                       strcpy(response, "FAILcan't set public key!");
+               else
+                       strcpy(response, "OKAY");
+       }
+#endif /* !CONFIG_AVB_ATX */
+#endif /* CONFIG_IMX_TRUSTY_OS */
+       else if (endswith(cmd, "unlock_critical")) {
+               strcpy(response, "OKAY");
+       } else if (endswith(cmd, "unlock")) {
+               printf("flashing unlock.\n");
+#ifdef CONFIG_AVB_ATX
+               /* We should do nothing here For Android Things which
+                * enables the authenticated unlock feature.
+                */
+               strcpy(response, "OKAY");
+#else
+               status = do_fastboot_unlock(false);
+               if (status != FASTBOOT_LOCK_ERROR)
+                       strcpy(response, "OKAY");
+               else
+                       strcpy(response, "FAILunlock device failed.");
+#endif
+       } else if (endswith(cmd, "lock")) {
+#ifdef CONFIG_AVB_ATX
+               /* We should do nothing here For Android Things which
+                * enables the at-lock-vboot feature.
+                */
+               strcpy(response, "OKAY");
+#else
+               printf("flashing lock.\n");
+               status = do_fastboot_lock();
+               if (status != FASTBOOT_LOCK_ERROR)
+                       strcpy(response, "OKAY");
+               else
+                       strcpy(response, "FAILlock device failed.");
+#endif
+       } else if (endswith(cmd, "get_unlock_ability")) {
+               result = fastboot_lock_enable();
+               if (result == FASTBOOT_UL_ENABLE) {
+                       fastboot_tx_write_more("INFO1");
+                       strcpy(response, "OKAY");
+               } else if (result == FASTBOOT_UL_DISABLE) {
+                       fastboot_tx_write_more("INFO0");
+                       strcpy(response, "OKAY");
+               } else {
+                       printf("flashing get_unlock_ability fail!\n");
+                       strcpy(response, "FAILget unlock ability failed.");
+               }
+       } else {
+               printf("Unknown flashing command:%s\n", cmd);
+               strcpy(response, "FAILcommand not defined");
+       }
+       fastboot_tx_write_more(response);
+
+       /* Must call fastboot_none_resp before returning from the dispatch function
+        *  which uses fastboot_tx_write_more
+        */
+       fastboot_none_resp(response);
+}
+#endif /* CONFIG_FASTBOOT_LOCK */
+
+#ifdef CONFIG_AVB_SUPPORT
+static void set_active_avb(char *cmd, char *response)
+{
+       AvbIOResult ret;
+       int slot = 0;
+
+       if (!cmd) {
+               pr_err("missing slot suffix\n");
+               fastboot_fail("missing slot suffix", response);
+               return;
+       }
+
+       slot = slotidx_from_suffix(cmd);
+
+       if (slot < 0) {
+               fastboot_fail("err slot suffix", response);
+               return;
+       }
+
+       ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot);
+       if (ret != AVB_IO_RESULT_OK)
+               fastboot_fail("avb IO error", response);
+       else
+               fastboot_okay(NULL, response);
+
+       return;
+}
+#endif /*CONFIG_AVB_SUPPORT*/
+
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+static void flash(char *cmd, char *response)
+{
+       if (!cmd) {
+               pr_err("missing partition name");
+               fastboot_fail("missing partition name", response);
+               return;
+       }
+
+       /* Always enable image flash for Android Things. */
+#if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX)
+       int status;
+       status = fastboot_get_lock_stat();
+
+       if (status == FASTBOOT_LOCK) {
+               pr_err("device is LOCKed!\n");
+               fastboot_fail("device is locked.", response);
+               return;
+
+       } else if (status == FASTBOOT_LOCK_ERROR) {
+               pr_err("write lock status into device!\n");
+               fastboot_set_lock_stat(FASTBOOT_LOCK);
+               fastboot_fail("device is locked.", response);
+               return;
+       }
+#endif
+
+       fastboot_process_flash(cmd, fastboot_buf_addr,
+               fastboot_bytes_received, response);
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+       if (strncmp(cmd, "gpt", 3) == 0) {
+               int gpt_valid = 0;
+               gpt_valid = partition_table_valid();
+               /* If gpt is valid, load partitons table into memory.
+                  So if the next command is "fastboot reboot bootloader",
+                  it can find the "misc" partition to r/w. */
+               if(gpt_valid) {
+                       fastboot_load_partitions();
+                       /* Unlock device if the gpt is valid */
+                       do_fastboot_unlock(true);
+               }
+       }
+
+#endif
+}
+
+static void erase(char *cmd, char *response)
+{
+       if (!cmd) {
+               pr_err("missing partition name");
+               fastboot_fail("missing partition name", response);
+               return;
+       }
+
+#if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX)
+       FbLockState status;
+       status = fastboot_get_lock_stat();
+       if (status == FASTBOOT_LOCK) {
+               pr_err("device is LOCKed!\n");
+               fastboot_fail("device is locked.", response);
+               return;
+       } else if (status == FASTBOOT_LOCK_ERROR) {
+               pr_err("write lock status into device!\n");
+               fastboot_set_lock_stat(FASTBOOT_LOCK);
+               fastboot_fail("device is locked.", response);
+               return;
+       }
+#endif
+       fastboot_process_erase(cmd, response);
+}
+#endif
+
+#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+/**
+ * run_ucmd() - Execute the UCmd command
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void run_ucmd(char *cmd_parameter, char *response)
+{
+       if (!cmd_parameter) {
+               pr_err("missing slot suffix\n");
+               fastboot_fail("missing command", response);
+               return;
+       }
+       if(run_command(cmd_parameter, 0)) {
+               fastboot_fail("", response);
+       } else {
+               fastboot_okay(NULL, response);
+               /* cmd may impact fastboot related environment*/
+               fastboot_setup();
+       }
+}
+
+static char g_a_cmd_buff[64];
+
+void fastboot_acmd_complete(void)
+{
+       run_command(g_a_cmd_buff, 0);
+}
+
+/**
+ * run_acmd() - Execute the ACmd command
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void run_acmd(char *cmd_parameter, char *response)
+{
+       if (!cmd_parameter) {
+               pr_err("missing slot suffix\n");
+               fastboot_fail("missing command", response);
+               return;
+       }
+
+       if (strlen(cmd_parameter) >= sizeof(g_a_cmd_buff)) {
+               pr_err("input acmd is too long\n");
+               fastboot_fail("too long command", response);
+               return;
+       }
+
+       strcpy(g_a_cmd_buff, cmd_parameter);
+       fastboot_okay(NULL, response);
+}
+#endif
+
+static const struct {
+       const char *command;
+       void (*dispatch)(char *cmd_parameter, char *response);
+} commands[FASTBOOT_COMMAND_COUNT] = {
+               [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] = {
+                       .command = "reboot-bootloader",
+                       .dispatch = reboot_bootloader,
+               },
+               [FASTBOOT_COMMAND_UPLOAD] = {
+                       .command = "upload",
+                       .dispatch = upload,
+               },
+               [FASTBOOT_COMMAND_GETSTAGED] = {
+                       .command = "get_staged",
+                       .dispatch = upload,
+               },
+#if defined(CONFIG_FASTBOOT_LOCK)
+               [FASTBOOT_COMMAND_FLASHING] = {
+                       .command = "flashing",
+                       .dispatch = flashing,
+               },
+               [FASTBOOT_COMMAND_OEM] = {
+                       .command = "oem",
+                       .dispatch = flashing,
+               },
+#endif
+#ifdef CONFIG_AVB_SUPPORT
+               [FASTBOOT_COMMAND_SETACTIVE] = {
+                       .command = "set_active",
+                       .dispatch = set_active_avb,
+               },
+#endif
+#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+               [FASTBOOT_COMMAND_UCMD] = {
+                       .command = "UCmd",
+                       .dispatch = run_ucmd,
+               },
+               [FASTBOOT_COMMAND_ACMD] = {
+                       .command ="ACmd",
+                       .dispatch = run_acmd,
+               },
+#endif
+               [FASTBOOT_COMMAND_REBOOT] = {
+                       .command = "reboot",
+                       .dispatch = okay,
+               },
+               [FASTBOOT_COMMAND_GETVAR] = {
+                       .command = "getvar",
+                       .dispatch = getvar,
+               },
+               [FASTBOOT_COMMAND_DOWNLOAD] = {
+                       .command = "download",
+                       .dispatch = download,
+               },
+               [FASTBOOT_COMMAND_BOOT] = {
+                       .command = "boot",
+                       .dispatch = okay,
+               },
+               [FASTBOOT_COMMAND_CONTINUE] = {
+                       .command = "continue",
+                       .dispatch = okay,
+               },
+#ifdef CONFIG_FASTBOOT_FLASH
+               [FASTBOOT_COMMAND_FLASH] = {
+                       .command = "flash",
+                       .dispatch = flash,
+               },
+               [FASTBOOT_COMMAND_ERASE] = {
+                       .command = "erase",
+                       .dispatch = erase,
+               },
+#endif
+#ifdef CONFIG_AVB_ATX
+               [FASTBOOT_COMMAND_STAGE] = {
+                       .command = "stage",
+                       .dispatch = download,
+               },
+#endif
+};
+
+/**
+ * fastboot_handle_command - Handle fastboot command
+ *
+ * @cmd_string: Pointer to command string
+ * @response: Pointer to fastboot response buffer
+ *
+ * Return: Executed command, or -1 if not recognized
+ */
+int fastboot_handle_command(char *cmd_string, char *response)
+{
+       int i;
+       char *cmd_parameter;
+
+       cmd_parameter = cmd_string;
+       strsep(&cmd_parameter, ":");
+       /* separate cmdstring for "fastboot oem/flashing" with a blank */
+       if(cmd_parameter == NULL)
+       {
+               cmd_parameter = cmd_string;
+               strsep(&cmd_parameter, " ");
+       }
+
+       for (i = 0; i < ARRAY_SIZE(commands); i++) {
+               if (commands[i].command != NULL &&
+                       !strcmp(commands[i].command, cmd_string)) {
+                       if (commands[i].dispatch) {
+                               commands[i].dispatch(cmd_parameter,
+                                                       response);
+                               return i;
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       pr_err("command %s not recognized.\n", cmd_string);
+       fastboot_fail("unrecognized command", response);
+       return -1;
+}
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_common.c b/drivers/fastboot/fb_fsl/fb_fsl_common.c
new file mode 100644 (file)
index 0000000..c65524a
--- /dev/null
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <asm/mach-imx/sys_proto.h>
+#include <fb_fsl.h>
+#include <fastboot.h>
+#include <mmc.h>
+#include <android_image.h>
+#include <asm/bootm.h>
+#include <nand.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+#include <image.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/setup.h>
+#include <env.h>
+#ifdef CONFIG_ANDROID_RECOVERY
+#include <recovery.h>
+#endif
+
+#ifdef CONFIG_BCB_SUPPORT
+#include "bcb.h"
+#endif
+
+#ifdef CONFIG_AVB_SUPPORT
+#include <dt_table.h>
+#include <fsl_avb.h>
+#endif
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+#include <asm-generic/gpio.h>
+#include <asm/mach-imx/gpio.h>
+#include "../lib/avb/fsl/fsl_avbkey.h"
+#include "../arch/arm/include/asm/mach-imx/hab.h"
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#include "u-boot/sha256.h"
+#include <trusty/libtipc.h>
+
+extern int armv7_init_nonsec(void);
+extern void trusty_os_init(void);
+#endif
+
+#include "fb_fsl_common.h"
+
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
+AvbABOps fsl_avb_ab_ops = {
+       .read_ab_metadata = fsl_read_ab_metadata,
+       .write_ab_metadata = fsl_write_ab_metadata,
+       .ops = NULL
+};
+#ifdef CONFIG_AVB_ATX
+AvbAtxOps fsl_avb_atx_ops = {
+       .ops = NULL,
+       .read_permanent_attributes = fsl_read_permanent_attributes,
+       .read_permanent_attributes_hash = fsl_read_permanent_attributes_hash,
+#ifdef CONFIG_IMX_TRUSTY_OS
+       .set_key_version = fsl_write_rollback_index_rpmb,
+#else
+       .set_key_version = fsl_set_key_version,
+#endif
+       .get_random = fsl_get_random
+};
+#endif
+AvbOps fsl_avb_ops = {
+       .ab_ops = &fsl_avb_ab_ops,
+#ifdef CONFIG_AVB_ATX
+       .atx_ops = &fsl_avb_atx_ops,
+#endif
+       .read_from_partition = fsl_read_from_partition_multi,
+       .write_to_partition = fsl_write_to_partition,
+#ifdef CONFIG_AVB_ATX
+       .validate_vbmeta_public_key = avb_atx_validate_vbmeta_public_key,
+#else
+       .validate_vbmeta_public_key = fsl_validate_vbmeta_public_key_rpmb,
+#endif
+       .read_rollback_index = fsl_read_rollback_index_rpmb,
+        .write_rollback_index = fsl_write_rollback_index_rpmb,
+       .read_is_device_unlocked = fsl_read_is_device_unlocked,
+       .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition,
+       .get_size_of_partition = fsl_get_size_of_partition
+};
+#endif
+
+int get_block_size(void) {
+        int dev_no = 0;
+        struct blk_desc *dev_desc;
+
+        dev_no = fastboot_devinfo.dev_id;
+        dev_desc = blk_get_dev(fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", dev_no);
+        if (NULL == dev_desc) {
+                printf("** Block device %s %d not supported\n",
+                       fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc",
+                       dev_no);
+                return 0;
+        }
+        return dev_desc->blksz;
+}
+
+struct fastboot_device_info fastboot_devinfo = {0xff, 0xff};
+
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+struct fastboot_device_info fastboot_firmwareinfo;
+#endif
+
+/**
+ * fastboot_none() - Skip the common write operation, nothing output.
+ *
+ * @response: Pointer to fastboot response buffer
+ */
+void fastboot_none_resp(char *response)
+{
+       *response = 0;
+}
+
+void board_fastboot_setup(void)
+{
+       static char boot_dev_part[32];
+       u32 dev_no;
+
+       switch (get_boot_device()) {
+       case SD1_BOOT:
+       case SD2_BOOT:
+       case SD3_BOOT:
+       case SD4_BOOT:
+       case MMC1_BOOT:
+       case MMC2_BOOT:
+       case MMC3_BOOT:
+       case MMC4_BOOT:
+               dev_no = mmc_get_env_dev();
+               sprintf(boot_dev_part,"mmc%d",dev_no);
+               if (!env_get("fastboot_dev"))
+                       env_set("fastboot_dev", boot_dev_part);
+               sprintf(boot_dev_part, "boota mmc%d", dev_no);
+               if (!env_get("bootcmd"))
+                       env_set("bootcmd", boot_dev_part);
+               break;
+       case USB_BOOT:
+               printf("Detect USB boot. Will enter fastboot mode!\n");
+               if (!env_get("bootcmd"))
+                       env_set("bootcmd", "fastboot 0");
+               break;
+       default:
+               if (!env_get("bootcmd"))
+                       printf("unsupported boot devices\n");
+               break;
+       }
+
+       /* add soc type into bootargs */
+       if (is_mx6dqp()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx6qp");
+       } else if (is_mx6dq()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx6q");
+       } else if (is_mx6sdl()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx6dl");
+       } else if (is_mx6sx()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx6sx");
+       } else if (is_mx6sl()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx6sl");
+       } else if (is_mx6ul()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx6ul");
+       } else if (is_mx7()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx7d");
+       } else if (is_mx7ulp()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx7ulp");
+       } else if (is_imx8qm()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx8qm");
+       } else if (is_imx8qxp()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx8qxp");
+       } else if (is_imx8mq()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx8mq");
+       } else if (is_imx8mm()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx8mm");
+       } else if (is_imx8mn()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx8mn");
+       } else if (is_imx8mp()) {
+               if (!env_get("soc_type"))
+                       env_set("soc_type", "imx8mp");
+       }
+}
+
+#ifdef CONFIG_ANDROID_RECOVERY
+void board_recovery_setup(void)
+{
+/* boot from current mmc with avb verify */
+#ifdef CONFIG_AVB_SUPPORT
+       if (!env_get("bootcmd_android_recovery"))
+               env_set("bootcmd_android_recovery", "boota recovery");
+#else
+       static char boot_dev_part[32];
+       u32 dev_no;
+
+       int bootdev = get_boot_device();
+       switch (bootdev) {
+       case SD1_BOOT:
+       case SD2_BOOT:
+       case SD3_BOOT:
+       case SD4_BOOT:
+       case MMC1_BOOT:
+       case MMC2_BOOT:
+       case MMC3_BOOT:
+       case MMC4_BOOT:
+               dev_no = mmc_get_env_dev();
+               sprintf(boot_dev_part,"boota mmc%d recovery",dev_no);
+               if (!env_get("bootcmd_android_recovery"))
+                       env_set("bootcmd_android_recovery", boot_dev_part);
+               break;
+       default:
+               printf("Unsupported bootup device for recovery: dev: %d\n",
+                       bootdev);
+               return;
+       }
+#endif /* CONFIG_AVB_SUPPORT */
+       printf("setup env for recovery..\n");
+       env_set("bootcmd", env_get("bootcmd_android_recovery"));
+}
+#endif /*CONFIG_ANDROID_RECOVERY*/
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#ifdef CONFIG_ARM64
+void tee_setup(void)
+{
+       trusty_ipc_init();
+}
+
+#else
+extern bool tos_flashed;
+
+void tee_setup(void)
+{
+       /* load tee from boot1 of eMMC. */
+       int mmcc = mmc_get_env_dev();
+       struct blk_desc *dev_desc = NULL;
+
+       struct mmc *mmc;
+       mmc = find_mmc_device(mmcc);
+       if (!mmc) {
+                   printf("boota: cannot find '%d' mmc device\n", mmcc);
+                           goto fail;
+       }
+
+       dev_desc = blk_get_dev("mmc", mmcc);
+       if (NULL == dev_desc) {
+                   printf("** Block device MMC %d not supported\n", mmcc);
+                           goto fail;
+       }
+
+       /* below was i.MX mmc operation code */
+       if (mmc_init(mmc)) {
+                   printf("mmc%d init failed\n", mmcc);
+                           goto fail;
+       }
+
+       struct fastboot_ptentry *tee_pte;
+       char *tee_ptn = FASTBOOT_PARTITION_TEE;
+       tee_pte = fastboot_flash_find_ptn(tee_ptn);
+       mmc_switch_part(mmc, TEE_HWPARTITION_ID);
+       if (!tee_pte) {
+               printf("boota: cannot find tee partition!\n");
+               fastboot_flash_dump_ptn();
+       }
+
+       if (blk_dread(dev_desc, tee_pte->start,
+                   tee_pte->length, (void *)TRUSTY_OS_ENTRY) < 0) {
+               printf("Failed to load tee.");
+       }
+       mmc_switch_part(mmc, FASTBOOT_MMC_USER_PARTITION_ID);
+
+       tos_flashed = false;
+       if(!valid_tos()) {
+               printf("TOS not flashed! Will enter TOS recovery mode. Everything will be wiped!\n");
+               fastboot_wipe_all();
+               run_command("fastboot 0", 0);
+               goto fail;
+       }
+#ifdef NON_SECURE_FASTBOOT
+       armv7_init_nonsec();
+       trusty_os_init();
+       trusty_ipc_init();
+#endif
+
+fail:
+       return;
+
+}
+#endif /* CONFIG_ARM64 */
+#endif /* CONFIG_IMX_TRUSTY_OS */
+
+static int _fastboot_setup_dev(int *switched)
+{
+       char *fastboot_env;
+       struct fastboot_device_info devinfo;;
+       fastboot_env = env_get("fastboot_dev");
+
+       if (fastboot_env) {
+               if (!strcmp(fastboot_env, "sata")) {
+                       devinfo.type = DEV_SATA;
+                       devinfo.dev_id = 0;
+               } else if (!strncmp(fastboot_env, "mmc", 3)) {
+                       devinfo.type = DEV_MMC;
+                       if(env_get("target_ubootdev"))
+                               devinfo.dev_id = simple_strtoul(env_get("target_ubootdev"), NULL, 10);
+                       else
+                               devinfo.dev_id = mmc_get_env_dev();
+               } else {
+                       return 1;
+               }
+       } else {
+               return 1;
+       }
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+       /* For imx7ulp, flash m4 images directly to spi nor-flash, M4 will
+        * run automatically after powered on. For imx8mq, flash m4 images to
+        * physical partition 'm4_os', m4 will be kicked off by A core. */
+       fastboot_firmwareinfo.type = ANDROID_MCU_FRIMWARE_DEV_TYPE;
+#endif
+
+       if (switched) {
+               if (devinfo.type != fastboot_devinfo.type || devinfo.dev_id != fastboot_devinfo.dev_id)
+                       *switched = 1;
+               else
+                       *switched = 0;
+       }
+
+       fastboot_devinfo.type    = devinfo.type;
+       fastboot_devinfo.dev_id = devinfo.dev_id;
+
+       return 0;
+}
+
+void fastboot_setup(void)
+{
+       int sw, ret;
+       struct tag_serialnr serialnr;
+       char serial[17];
+
+       if (!env_get("serial#")) {
+               get_board_serial(&serialnr);
+               sprintf(serial, "%08x%08x", serialnr.high, serialnr.low);
+               env_set("serial#", serial);
+       }
+
+       /*execute board relevant initilizations for preparing fastboot */
+       board_fastboot_setup();
+
+       /*get the fastboot dev*/
+       ret = _fastboot_setup_dev(&sw);
+
+       /*load partitions information for the fastboot dev*/
+       if (!ret && sw)
+               fastboot_load_partitions();
+
+       fastboot_init(NULL, 0);
+#ifdef CONFIG_AVB_SUPPORT
+       fsl_avb_ab_ops.ops = &fsl_avb_ops;
+#ifdef CONFIG_AVB_ATX
+       fsl_avb_atx_ops.ops = &fsl_avb_ops;
+#endif
+#endif
+}
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_common.h b/drivers/fastboot/fb_fsl/fb_fsl_common.h
new file mode 100644 (file)
index 0000000..4577d9e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FB_FSL_COMMON_H
+#define FB_FSL_COMMON_H
+
+#ifdef CONFIG_AVB_SUPPORT
+#include <dt_table.h>
+#include <fsl_avb.h>
+#endif
+
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
+extern AvbABOps fsl_avb_ab_ops;
+#ifdef CONFIG_AVB_ATX
+extern AvbAtxOps fsl_avb_atx_ops;
+#endif
+extern AvbOps fsl_avb_ops;
+#endif
+
+int get_block_size(void);
+void process_erase_mmc(const char *cmdbuf, char *response);
+
+#endif // FB_FSL_COMMON_H
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_dev.c b/drivers/fastboot/fb_fsl/fb_fsl_dev.c
new file mode 100644 (file)
index 0000000..1f75442
--- /dev/null
@@ -0,0 +1,552 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <asm/mach-imx/sys_proto.h>
+#include <fb_fsl.h>
+#include <fastboot.h>
+#include <mmc.h>
+#include <android_image.h>
+#include <asm/bootm.h>
+#include <nand.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+#include <image.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/setup.h>
+#include <env.h>
+
+#include "fb_fsl_common.h"
+
+static lbaint_t mmc_sparse_write(struct sparse_storage *info,
+               lbaint_t blk, lbaint_t blkcnt, const void *buffer)
+{
+#define SPARSE_FILL_BUF_SIZE (2 * 1024 * 1024)
+
+
+       struct blk_desc *dev_desc = (struct blk_desc *)info->priv;
+       ulong ret = 0;
+       void *data;
+       int fill_buf_num_blks, cnt;
+
+       if ((unsigned long)buffer & (CONFIG_SYS_CACHELINE_SIZE - 1)) {
+
+               fill_buf_num_blks = SPARSE_FILL_BUF_SIZE / info->blksz;
+
+               data = memalign(CONFIG_SYS_CACHELINE_SIZE, fill_buf_num_blks * info->blksz);
+
+               while (blkcnt) {
+
+                       if (blkcnt > fill_buf_num_blks)
+                               cnt = fill_buf_num_blks;
+                       else
+                               cnt = blkcnt;
+
+                       memcpy(data, buffer, cnt * info->blksz);
+
+                       ret += blk_dwrite(dev_desc, blk, cnt, data);
+
+                       blk += cnt;
+                       blkcnt -= cnt;
+                       buffer = (void *)((unsigned long)buffer + cnt * info->blksz);
+
+               }
+
+               free(data);
+       } else {
+               ret = blk_dwrite(dev_desc, blk, blkcnt, buffer);
+       }
+
+       return ret;
+}
+
+static lbaint_t mmc_sparse_reserve(struct sparse_storage *info,
+               lbaint_t blk, lbaint_t blkcnt)
+{
+       return blkcnt;
+}
+
+int write_backup_gpt(void *download_buffer)
+{
+       int mmc_no = 0;
+       struct mmc *mmc;
+       struct blk_desc *dev_desc;
+
+       mmc_no = fastboot_devinfo.dev_id;
+       mmc = find_mmc_device(mmc_no);
+       if (mmc == NULL) {
+               printf("invalid mmc device\n");
+               return -1;
+       }
+       dev_desc = blk_get_dev("mmc", mmc_no);
+       if (dev_desc == NULL) {
+               printf("Can't get Block device MMC %d\n",
+                       mmc_no);
+               return -ENODEV;
+       }
+
+       /* write backup get partition */
+       if (write_backup_gpt_partitions(dev_desc, download_buffer)) {
+               printf("writing GPT image fail\n");
+               return -1;
+       }
+
+       printf("flash backup gpt image successfully\n");
+       return 0;
+}
+
+static int get_fastboot_target_dev(char *mmc_dev, struct fastboot_ptentry *ptn)
+{
+       int dev = 0;
+       struct mmc *target_mmc;
+
+       /* Support flash bootloader to mmc 'target_ubootdev' devices, if the
+       * 'target_ubootdev' env is not set just flash bootloader to current
+       * mmc device.
+       */
+       if ((!strncmp(ptn->name, FASTBOOT_PARTITION_BOOTLOADER,
+                                       sizeof(FASTBOOT_PARTITION_BOOTLOADER))) &&
+                                       (env_get("target_ubootdev"))) {
+               dev = simple_strtoul(env_get("target_ubootdev"), NULL, 10);
+
+               /* if target_ubootdev is set, it must be that users want to change
+                * fastboot device, then fastboot environment need to be updated */
+               fastboot_setup();
+
+               target_mmc = find_mmc_device(dev);
+               if ((target_mmc == NULL) || mmc_init(target_mmc)) {
+                       printf("MMC card init failed!\n");
+                       return -1;
+               } else {
+                       printf("Flash target is mmc%d\n", dev);
+                       if (target_mmc->part_config != MMCPART_NOAVAILABLE)
+                               sprintf(mmc_dev, "mmc dev %x %x", dev, /*slot no*/
+                                               FASTBOOT_MMC_BOOT_PARTITION_ID/*part no*/);
+                       else
+                               sprintf(mmc_dev, "mmc dev %x", dev);
+                       }
+       } else if (ptn->partition_id != FASTBOOT_MMC_NONE_PARTITION_ID)
+               sprintf(mmc_dev, "mmc dev %x %x",
+                               fastboot_devinfo.dev_id, /*slot no*/
+                               ptn->partition_id /*part no*/);
+       else
+               sprintf(mmc_dev, "mmc dev %x",
+                               fastboot_devinfo.dev_id /*slot no*/);
+       return 0;
+}
+
+static void process_flash_blkdev(const char *cmdbuf, void *download_buffer,
+                             u32 download_bytes, char *response)
+{
+       if (download_bytes) {
+               struct fastboot_ptentry *ptn;
+
+               /* Next is the partition name */
+               ptn = fastboot_flash_find_ptn(cmdbuf);
+               if (ptn == NULL) {
+                       fastboot_fail("partition does not exist", response);
+                       fastboot_flash_dump_ptn();
+               } else if ((download_bytes >
+                          ptn->length * MMC_SATA_BLOCK_SIZE) &&
+                               !(ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV)) {
+                       printf("Image too large for the partition\n");
+                       fastboot_fail("image too large for partition", response);
+               } else {
+                       unsigned int temp;
+
+                       char blk_dev[128];
+                       char blk_write[128];
+                       int blkret;
+
+                       printf("writing to partition '%s'\n", ptn->name);
+                       /* Get target flash device. */
+                       if (get_fastboot_target_dev(blk_dev, ptn) != 0)
+                               return;
+
+                       if (!fastboot_parts_is_raw(ptn) &&
+                               is_sparse_image(download_buffer)) {
+                               int dev_no = 0;
+                               struct mmc *mmc;
+                               struct blk_desc *dev_desc;
+                               struct disk_partition info;
+                               struct sparse_storage sparse;
+                               int err;
+
+                               dev_no = fastboot_devinfo.dev_id;
+
+                               printf("sparse flash target is %s:%d\n",
+                                      fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc",
+                                      dev_no);
+                               if (fastboot_devinfo.type == DEV_MMC) {
+                                       mmc = find_mmc_device(dev_no);
+                                       if (mmc && mmc_init(mmc))
+                                               printf("MMC card init failed!\n");
+                               }
+
+                               dev_desc = blk_get_dev(fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", dev_no);
+                               if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
+                                       printf("** Block device %s %d not supported\n",
+                                              fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc",
+                                              dev_no);
+                                       return;
+                               }
+
+                               if( strncmp(ptn->name, FASTBOOT_PARTITION_ALL,
+                                           strlen(FASTBOOT_PARTITION_ALL)) == 0) {
+                                       info.blksz = dev_desc->blksz;
+                                       info.size = dev_desc->lba;
+                                       info.start = 0;
+                               } else {
+
+                                       if (part_get_info(dev_desc,
+                                                         ptn->partition_index, &info)) {
+                                               printf("Bad partition index:%d for partition:%s\n",
+                                               ptn->partition_index, ptn->name);
+                                               return;
+                                       }
+                               }
+                               printf("writing to partition '%s' for sparse, buffer size %d\n",
+                                               ptn->name, download_bytes);
+
+                               sparse.blksz = info.blksz;
+                               sparse.start = info.start;
+                               sparse.size = info.size;
+                               sparse.write = mmc_sparse_write;
+                               sparse.reserve = mmc_sparse_reserve;
+                               sparse.mssg = fastboot_fail;
+                               printf("Flashing sparse image at offset " LBAFU "\n",
+                                      sparse.start);
+
+                               sparse.priv = dev_desc;
+                               err = write_sparse_image(&sparse, ptn->name, download_buffer,
+                                                  response);
+
+                               if (!err)
+                                       fastboot_okay(NULL, response);
+                       } else {
+                               /* Will flash images in below case:
+                                * 1. Is not gpt partition.
+                                * 2. Is gpt partition but no overlay detected.
+                                * */
+                               if (strncmp(ptn->name, "gpt", 3) || !bootloader_gpt_overlay()) {
+                                       /* block count */
+                                       if (strncmp(ptn->name, "gpt", 3) == 0) {
+                                               temp = (ANDROID_GPT_END +
+                                                               MMC_SATA_BLOCK_SIZE - 1) /
+                                                               MMC_SATA_BLOCK_SIZE;
+                                       } else {
+                                               temp = (download_bytes +
+                                                               MMC_SATA_BLOCK_SIZE - 1) /
+                                                               MMC_SATA_BLOCK_SIZE;
+                                       }
+
+                                       sprintf(blk_write, "%s write 0x%x 0x%x 0x%x",
+                                               fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc",
+                                               (unsigned int)(uintptr_t)download_buffer, /*source*/
+                                               ptn->start, /*dest*/
+                                               temp /*length*/);
+
+                                       printf("Initializing '%s'\n", ptn->name);
+
+                                       blkret = run_command(blk_dev, 0);
+                                       if (blkret)
+                                               fastboot_fail("Init of BLK device failed", response);
+                                       else
+                                               fastboot_okay(NULL, response);
+
+                                       printf("Writing '%s'\n", ptn->name);
+                                       if (run_command(blk_write, 0)) {
+                                               printf("Writing '%s' FAILED!\n", ptn->name);
+                                               fastboot_fail("Write partition failed", response);
+                                       } else {
+                                               printf("Writing '%s' DONE!\n", ptn->name);
+                                               fastboot_okay(NULL, response);
+                                       }
+                               }
+                               /* Write backup gpt image */
+                               if (strncmp(ptn->name, "gpt", 3) == 0) {
+                                       if (write_backup_gpt(download_buffer))
+                                               fastboot_fail("write backup GPT image fail", response);
+                                       else
+                                               fastboot_okay(NULL, response);
+
+                                       /* will force scan the device,
+                                        * so dev_desc can be re-inited
+                                        * with the latest data */
+                                       run_command(blk_dev, 0);
+                               }
+                       }
+               }
+       } else {
+               fastboot_fail("no image downloaded", response);
+       }
+}
+
+static void process_erase_blkdev(const char *cmdbuf, char *response)
+{
+       int mmc_no = 0;
+       lbaint_t blks, blks_start, blks_size, grp_size;
+       struct mmc *mmc;
+       struct blk_desc *dev_desc;
+       struct fastboot_ptentry *ptn;
+       struct disk_partition info;
+
+       ptn = fastboot_flash_find_ptn(cmdbuf);
+       if ((ptn == NULL) || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) {
+               fastboot_fail("partition does not exist or uneraseable", response);
+               fastboot_flash_dump_ptn();
+               return;
+       }
+
+       if (fastboot_devinfo.type == DEV_SATA) {
+               printf("Not support erase on SATA\n");
+               return;
+       }
+
+       mmc_no = fastboot_devinfo.dev_id;
+       printf("erase target is MMC:%d\n", mmc_no);
+
+       mmc = find_mmc_device(mmc_no);
+       if ((mmc == NULL) || mmc_init(mmc)) {
+               printf("MMC card init failed!\n");
+               return;
+       }
+
+       dev_desc = blk_get_dev("mmc", mmc_no);
+       if (NULL == dev_desc) {
+               printf("Block device MMC %d not supported\n",
+                       mmc_no);
+               fastboot_fail("not valid MMC card", response);
+               return;
+       }
+
+       if (part_get_info(dev_desc,
+                               ptn->partition_index, &info)) {
+               printf("Bad partition index:%d for partition:%s\n",
+               ptn->partition_index, ptn->name);
+               fastboot_fail("erasing of MMC card", response);
+               return;
+       }
+
+       /* Align blocks to erase group size to avoid erasing other partitions */
+       grp_size = mmc->erase_grp_size;
+       blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
+       if (info.size >= grp_size)
+               blks_size = (info.size - (blks_start - info.start)) &
+                               (~(grp_size - 1));
+       else
+               blks_size = 0;
+
+       printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
+              blks_start, blks_start + blks_size);
+
+       blks = blk_derase(dev_desc, blks_start, blks_size);
+       if (blks != blks_size) {
+               printf("failed erasing from device %d", dev_desc->devnum);
+               fastboot_fail("erasing of MMC card", response);
+               return;
+       }
+
+       printf("........ erased " LBAFU " bytes from '%s'\n",
+              blks_size * info.blksz, cmdbuf);
+       fastboot_okay(NULL, response);
+
+    return;
+}
+
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+static void process_flash_sf(const char *cmdbuf, void *download_buffer,
+                             u32 download_bytes, char *response)
+{
+       int blksz = 0;
+       blksz = get_block_size();
+
+       if (download_bytes) {
+               struct fastboot_ptentry *ptn;
+               ptn = fastboot_flash_find_ptn(cmdbuf);
+               if (ptn == 0) {
+                       fastboot_fail("partition does not exist", response);
+                       fastboot_flash_dump_ptn();
+               } else if ((download_bytes > ptn->length * blksz)) {
+                       fastboot_fail("image too large for partition", response);
+               /* TODO : Improve check for yaffs write */
+               } else {
+                       int ret;
+                       char sf_command[128];
+                       /* Normal case */
+                       /* Probe device */
+                       sprintf(sf_command, "sf probe");
+                       ret = run_command(sf_command, 0);
+                       if (ret){
+                               fastboot_fail("Probe sf failed", response);
+                               return;
+                       }
+                       /* Erase */
+                       sprintf(sf_command, "sf erase 0x%x 0x%x", ptn->start * blksz, /*start*/
+                       ptn->length * blksz /*size*/);
+                       ret = run_command(sf_command, 0);
+                       if (ret) {
+                               fastboot_fail("Erasing sf failed", response);
+                               return;
+                       }
+                       /* Write image */
+                       sprintf(sf_command, "sf write 0x%x 0x%x 0x%x",
+                                       (unsigned int)(ulong)download_buffer, /* source */
+                                       ptn->start * blksz, /* start */
+                                       download_bytes /*size*/);
+                       printf("sf write '%s'\n", ptn->name);
+                       ret = run_command(sf_command, 0);
+                       if (ret){
+                               fastboot_fail("Writing sf failed", response);
+                               return;
+                       }
+                       printf("sf write finished '%s'\n", ptn->name);
+                       fastboot_okay(NULL, response);
+               }
+       } else {
+               fastboot_fail("no image downloaded", response);
+       }
+}
+
+#ifdef CONFIG_ARCH_IMX8M
+/* Check if the mcu image is built for running from TCM */
+static bool is_tcm_image(unsigned char *image_addr)
+{
+       u32 stack;
+
+       stack = *(u32 *)image_addr;
+
+       if ((stack != (u32)ANDROID_MCU_FIRMWARE_HEADER_STACK)) {
+               printf("Please flash mcu firmware images for running from TCM\n");
+               return false;
+       } else
+               return true;
+}
+#endif
+#endif
+
+void fastboot_process_erase(const char *cmdbuf, char *response)
+{
+       switch (fastboot_devinfo.type) {
+       case DEV_SATA:
+       case DEV_MMC:
+               process_erase_blkdev(cmdbuf, response);
+               break;
+       default:
+               printf("Not support flash command for current device %d\n",
+                       fastboot_devinfo.type);
+               fastboot_fail("failed to flash device", response);
+               break;
+       }
+}
+
+void fastboot_process_flash(const char *cmdbuf, void *download_buffer,
+                             u32 download_bytes, char *response)
+{
+/* Check if we need to flash mcu firmware */
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+       if (!strncmp(cmdbuf, FASTBOOT_MCU_FIRMWARE_PARTITION,
+                               sizeof(FASTBOOT_MCU_FIRMWARE_PARTITION))) {
+               switch (fastboot_firmwareinfo.type) {
+               case DEV_SF:
+                       process_flash_sf(cmdbuf, download_buffer,
+                               download_bytes, response);
+                       break;
+#ifdef CONFIG_ARCH_IMX8M
+               case DEV_MMC:
+                       if (is_tcm_image(download_buffer))
+                               process_flash_blkdev(cmdbuf, download_buffer,
+                                       download_bytes, response);
+                       break;
+#endif
+               default:
+                       printf("Don't support flash firmware\n");
+               }
+               return;
+       }
+#endif
+       /* Normal case */
+       switch (fastboot_devinfo.type) {
+       case DEV_SATA:
+       case DEV_MMC:
+               process_flash_blkdev(cmdbuf, download_buffer,
+                       download_bytes, response);
+               break;
+       default:
+               printf("Not support flash command for current device %d\n",
+                       fastboot_devinfo.type);
+               fastboot_fail("failed to flash device", response);
+               break;
+       }
+}
+
+/* erase a partition on mmc */
+void process_erase_mmc(const char *cmdbuf, char *response)
+{
+       int mmc_no = 0;
+       lbaint_t blks, blks_start, blks_size, grp_size;
+       struct mmc *mmc;
+       struct blk_desc *dev_desc;
+       struct fastboot_ptentry *ptn;
+       struct disk_partition info;
+
+       ptn = fastboot_flash_find_ptn(cmdbuf);
+       if ((ptn == NULL) || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) {
+               sprintf(response, "FAILpartition does not exist or uneraseable");
+               fastboot_flash_dump_ptn();
+               return;
+       }
+
+       mmc_no = fastboot_devinfo.dev_id;
+       printf("erase target is MMC:%d\n", mmc_no);
+
+       mmc = find_mmc_device(mmc_no);
+       if ((mmc == NULL) || mmc_init(mmc)) {
+               printf("MMC card init failed!\n");
+               return;
+       }
+
+       dev_desc = blk_get_dev("mmc", mmc_no);
+       if (NULL == dev_desc) {
+               printf("Block device MMC %d not supported\n",
+                       mmc_no);
+               sprintf(response, "FAILnot valid MMC card");
+               return;
+       }
+
+       if (part_get_info(dev_desc,
+                               ptn->partition_index, &info)) {
+               printf("Bad partition index:%d for partition:%s\n",
+               ptn->partition_index, ptn->name);
+               sprintf(response, "FAILerasing of MMC card");
+               return;
+       }
+
+       /* Align blocks to erase group size to avoid erasing other partitions */
+       grp_size = mmc->erase_grp_size;
+       blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
+       if (info.size >= grp_size)
+               blks_size = (info.size - (blks_start - info.start)) &
+                               (~(grp_size - 1));
+       else
+               blks_size = 0;
+
+       printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
+              blks_start, blks_start + blks_size);
+
+       blks = blk_derase(dev_desc, blks_start, blks_size);
+       if (blks != blks_size) {
+               printf("failed erasing from device %d", dev_desc->devnum);
+               sprintf(response, "FAILerasing of MMC card");
+               return;
+       }
+
+       printf("........ erased " LBAFU " bytes from '%s'\n",
+              blks_size * info.blksz, cmdbuf);
+       sprintf(response, "OKAY");
+
+    return;
+}
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_getvar.c b/drivers/fastboot/fb_fsl/fb_fsl_getvar.c
new file mode 100644 (file)
index 0000000..24e94b8
--- /dev/null
@@ -0,0 +1,572 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/mach-imx/sys_proto.h>
+#include <fb_fsl.h>
+#include <fastboot.h>
+#include <mmc.h>
+#include <android_image.h>
+#include <asm/bootm.h>
+#include <nand.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+#include <image.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/setup.h>
+#include <env.h>
+#include <version.h>
+
+#ifdef CONFIG_AVB_SUPPORT
+#include <dt_table.h>
+#include <fsl_avb.h>
+#endif
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+#include <asm-generic/gpio.h>
+#include <asm/mach-imx/gpio.h>
+#include "../lib/avb/fsl/fsl_avbkey.h"
+#include "../arch/arm/include/asm/mach-imx/hab.h"
+#endif
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+#include "fastboot_lock_unlock.h"
+#endif
+
+#include "fb_fsl_common.h"
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#include "u-boot/sha256.h"
+#include <trusty/libtipc.h>
+
+#define ATAP_UUID_SIZE 32
+#define ATAP_UUID_STR_SIZE ((ATAP_UUID_SIZE*2) + 1)
+#endif
+
+#if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M)
+#define FASTBOOT_COMMON_VAR_NUM 14
+#else
+#define FASTBOOT_COMMON_VAR_NUM 13
+#endif
+
+#define FASTBOOT_VAR_YES    "yes"
+#define FASTBOOT_VAR_NO     "no"
+
+/* common variables of fastboot getvar command */
+char *fastboot_common_var[FASTBOOT_COMMON_VAR_NUM] = {
+       "version",
+       "version-bootloader",
+       "version-baseband",
+       "product",
+       "secure",
+       "max-download-size",
+       "erase-block-size",
+       "logical-block-size",
+       "unlocked",
+       "off-mode-charge",
+       "battery-voltage",
+       "variant",
+       "battery-soc-ok",
+#if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M)
+       "baseboard_id"
+#endif
+};
+
+/* at-vboot-state variable list */
+#ifdef CONFIG_AVB_ATX
+#define AT_VBOOT_STATE_VAR_NUM 6
+extern struct imx_sec_config_fuse_t const imx_sec_config_fuse;
+extern int fuse_read(u32 bank, u32 word, u32 *val);
+
+char *fastboot_at_vboot_state_var[AT_VBOOT_STATE_VAR_NUM] = {
+       "bootloader-locked",
+       "bootloader-min-versions",
+       "avb-perm-attr-set",
+       "avb-locked",
+       "avb-unlock-disabled",
+       "avb-min-versions"
+};
+#endif
+
+static int strcmp_l1(const char *s1, const char *s2)
+{
+       if (!s1 || !s2)
+               return -1;
+       return strncmp(s1, s2, strlen(s1));
+}
+
+static bool is_slotvar(char *cmd)
+{
+       assert(cmd != NULL);
+       if (!strcmp_l1("has-slot:", cmd) ||
+               !strcmp_l1("slot-successful:", cmd) ||
+               !strcmp_l1("slot-count", cmd) ||
+               !strcmp_l1("slot-suffixes", cmd) ||
+               !strcmp_l1("current-slot", cmd) ||
+               !strcmp_l1("slot-unbootable:", cmd) ||
+               !strcmp_l1("slot-retry-count:", cmd))
+                       return true;
+       return false;
+}
+
+static char *get_serial(void)
+{
+#ifdef CONFIG_SERIAL_TAG
+       struct tag_serialnr serialnr;
+       static char serial[32];
+       get_board_serial(&serialnr);
+       sprintf(serial, "%08x%08x", serialnr.high,      serialnr.low);
+       return serial;
+#else
+       return NULL;
+#endif
+}
+
+#if !defined(PRODUCT_NAME)
+#define PRODUCT_NAME "NXP i.MX"
+#endif
+
+#if !defined(VARIANT_NAME)
+#define VARIANT_NAME "NXP i.MX"
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+static void uuid_hex2string(uint8_t *uuid, char* buf, uint32_t uuid_len, uint32_t uuid_strlen) {
+       uint32_t i;
+       if (!uuid || !buf)
+               return;
+       char *cp = buf;
+       char *buf_end = buf + uuid_strlen;
+       for (i = 0; i < uuid_len; i++) {
+               cp += snprintf(cp, buf_end - cp, "%02x", uuid[i]);
+       }
+}
+#endif
+
+#if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M)
+int get_imx8m_baseboard_id(void);
+#endif
+
+static int get_single_var(char *cmd, char *response)
+{
+       char *str = cmd;
+       int chars_left;
+       const char *s;
+       struct mmc *mmc;
+       int mmc_dev_no;
+       int blksz;
+
+       chars_left = FASTBOOT_RESPONSE_LEN - strlen(response) - 1;
+
+       if ((str = strstr(cmd, "partition-size:"))) {
+               str +=strlen("partition-size:");
+               struct fastboot_ptentry* fb_part;
+               fb_part = fastboot_flash_find_ptn(str);
+               if (!fb_part) {
+                       strncat(response, "Wrong partition name.", chars_left);
+                       fastboot_flash_dump_ptn();
+                       return -1;
+               } else {
+                       snprintf(response + strlen(response), chars_left,
+                                "0x%llx",
+                                (uint64_t)fb_part->length * get_block_size());
+               }
+       } else if ((str = strstr(cmd, "partition-type:"))) {
+               str +=strlen("partition-type:");
+               struct fastboot_ptentry* fb_part;
+               fb_part = fastboot_flash_find_ptn(str);
+               if (!fb_part) {
+                       strncat(response, "Wrong partition name.", chars_left);
+                       fastboot_flash_dump_ptn();
+                       return -1;
+               } else {
+                       strncat(response, fb_part->fstype, chars_left);
+               }
+       } else if (!strcmp_l1("version-baseband", cmd)) {
+               strncat(response, "N/A", chars_left);
+       } else if (!strcmp_l1("version-bootloader", cmd) ||
+               !strcmp_l1("bootloader-version", cmd)) {
+               strncat(response, U_BOOT_VERSION, chars_left);
+       } else if (!strcmp_l1("version", cmd)) {
+               strncat(response, FASTBOOT_VERSION, chars_left);
+       } else if (!strcmp_l1("battery-voltage", cmd)) {
+               strncat(response, "0mV", chars_left);
+       } else if (!strcmp_l1("battery-soc-ok", cmd)) {
+               strncat(response, "yes", chars_left);
+       } else if (!strcmp_l1("variant", cmd)) {
+               strncat(response, VARIANT_NAME, chars_left);
+       } else if (!strcmp_l1("off-mode-charge", cmd)) {
+               strncat(response, "1", chars_left);
+       } else if (!strcmp_l1("downloadsize", cmd) ||
+               !strcmp_l1("max-download-size", cmd)) {
+
+               snprintf(response + strlen(response), chars_left, "0x%x", CONFIG_FASTBOOT_BUF_SIZE);
+       } else if (!strcmp_l1("erase-block-size", cmd)) {
+               mmc_dev_no = mmc_get_env_dev();
+               mmc = find_mmc_device(mmc_dev_no);
+               if (!mmc) {
+                       strncat(response, "FAILCannot get dev", chars_left);
+                       return -1;
+               }
+               blksz = get_block_size();
+               snprintf(response + strlen(response), chars_left, "0x%x",
+                               (blksz * mmc->erase_grp_size));
+       } else if (!strcmp_l1("logical-block-size", cmd)) {
+               blksz = get_block_size();
+               snprintf(response + strlen(response), chars_left, "0x%x", blksz);
+       } else if (!strcmp_l1("serialno", cmd)) {
+               s = get_serial();
+               if (s)
+                       strncat(response, s, chars_left);
+               else {
+                       strncat(response, "FAILValue not set", chars_left);
+                       return -1;
+               }
+       } else if (!strcmp_l1("product", cmd)) {
+               strncat(response, PRODUCT_NAME, chars_left);
+       }
+#ifdef CONFIG_IMX_TRUSTY_OS
+        else if(!strcmp_l1("at-attest-uuid", cmd)) {
+               char *uuid;
+               char uuid_str[ATAP_UUID_STR_SIZE];
+               if (trusty_atap_read_uuid_str(&uuid)) {
+                       printf("ERROR read uuid failed!\n");
+                       strncat(response, "FAILCannot get uuid!", chars_left);
+                       return -1;
+               } else {
+                       uuid_hex2string((uint8_t*)uuid, uuid_str,ATAP_UUID_SIZE, ATAP_UUID_STR_SIZE);
+                       strncat(response, uuid_str, chars_left);
+                       trusty_free(uuid);
+               }
+       }
+       else if(!strcmp_l1("at-attest-dh", cmd)) {
+               strncat(response, "1:P256,2:curve25519", chars_left);
+       }
+#endif
+#if defined(CONFIG_FASTBOOT_LOCK)
+       else if (!strcmp_l1("secure", cmd)) {
+               strncat(response, FASTBOOT_VAR_YES, chars_left);
+       } else if (!strcmp_l1("unlocked",cmd)){
+               int status = fastboot_get_lock_stat();
+               if (status == FASTBOOT_UNLOCK) {
+                       strncat(response, FASTBOOT_VAR_YES, chars_left);
+               } else {
+                       strncat(response, FASTBOOT_VAR_NO, chars_left);
+               }
+       }
+#else
+       else if (!strcmp_l1("secure", cmd)) {
+               strncat(response, FASTBOOT_VAR_NO, chars_left);
+       } else if (!strcmp_l1("unlocked",cmd)) {
+               strncat(response, FASTBOOT_VAR_NO, chars_left);
+       }
+#endif
+       else if (is_slotvar(cmd)) {
+#ifdef CONFIG_AVB_SUPPORT
+               if (get_slotvar_avb(&fsl_avb_ab_ops, cmd,
+                               response + strlen(response), chars_left + 1) < 0)
+                       return -1;
+#else
+               strncat(response, FASTBOOT_VAR_NO, chars_left);
+#endif
+       }
+#if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M)
+       else if (!strcmp_l1("baseboard_id", cmd)) {
+               int baseboard_id;
+
+               baseboard_id = get_imx8m_baseboard_id();
+               if (baseboard_id < 0) {
+                       printf("Get baseboard id failed!\n");
+                       strncat(response, "Get baseboard id failed!", chars_left);
+                       return -1;
+               } else
+                       snprintf(response + strlen(response), chars_left, "0x%x", baseboard_id);
+       }
+#endif
+#ifdef CONFIG_AVB_ATX
+       else if (!strcmp_l1("bootloader-locked", cmd)) {
+
+               /* Below is basically copied from is_hab_enabled() */
+               struct imx_sec_config_fuse_t *fuse =
+                       (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
+               uint32_t reg;
+               int ret;
+
+               /* Read the secure boot status from fuse. */
+               ret = fuse_read(fuse->bank, fuse->word, &reg);
+               if (ret) {
+                       printf("\nSecure boot fuse read error!\n");
+                       strncat(response, "Secure boot fuse read error!", chars_left);
+                       return -1;
+               }
+               /* Check if the secure boot bit is enabled */
+               if ((reg & 0x2000000) == 0x2000000)
+                       strncat(response, "1", chars_left);
+               else
+                       strncat(response, "0", chars_left);
+       } else if (!strcmp_l1("bootloader-min-versions", cmd)) {
+#ifndef CONFIG_ARM64
+               /* We don't support bootloader rbindex protection for
+                * ARM32(like imx7d) and the format is: "bootloader,tee". */
+               strncat(response, "-1,-1", chars_left);
+
+#elif defined(CONFIG_DUAL_BOOTLOADER)
+               /* Rbindex protection for bootloader is supported only when the
+                * 'dual bootloader' feature is enabled. U-boot will get the rbindx
+                * from RAM which is passed by spl because we can only get the rbindex
+                * at spl stage. The format in this case is: "spl,atf,tee,u-boot".
+                */
+               struct bl_rbindex_package *bl_rbindex;
+               uint32_t rbindex;
+
+               bl_rbindex = (struct bl_rbindex_package *)BL_RBINDEX_LOAD_ADDR;
+               if (!strncmp(bl_rbindex->magic, BL_RBINDEX_MAGIC,
+                               BL_RBINDEX_MAGIC_LEN)) {
+                       rbindex = bl_rbindex->rbindex;
+                       snprintf(response + strlen(response), chars_left,
+                                       "-1,%d,%d,%d",rbindex, rbindex, rbindex);
+               } else {
+                       printf("Error bootloader rbindex magic!\n");
+                       strncat(response, "Get bootloader rbindex fail!", chars_left);
+                       return -1;
+               }
+#else
+               /* Return -1 for all partition if 'dual bootloader' feature
+                * is not enabled */
+               strncat(response, "-1,-1,-1,-1", chars_left);
+#endif
+       } else if (!strcmp_l1("avb-perm-attr-set", cmd)) {
+               if (perm_attr_are_fused())
+                       strncat(response, "1", chars_left);
+               else
+                       strncat(response, "0", chars_left);
+       } else if (!strcmp_l1("avb-locked", cmd)) {
+               FbLockState status;
+
+               status = fastboot_get_lock_stat();
+               if (status == FASTBOOT_LOCK)
+                       strncat(response, "1", chars_left);
+               else if (status == FASTBOOT_UNLOCK)
+                       strncat(response, "0", chars_left);
+               else {
+                       printf("Get lock state error!\n");
+                       strncat(response, "Get lock state failed!", chars_left);
+                       return -1;
+               }
+       } else if (!strcmp_l1("avb-unlock-disabled", cmd)) {
+               if (at_unlock_vboot_is_disabled())
+                       strncat(response, "1", chars_left);
+               else
+                       strncat(response, "0", chars_left);
+       } else if (!strcmp_l1("avb-min-versions", cmd)) {
+               int i = 0;
+               /* rbindex location/value can be very large
+                * number so we reserve enough space here.
+                */
+               char buffer[35];
+               uint32_t rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2];
+               uint32_t location;
+               uint64_t rbindex;
+
+               memset(buffer, '\0', sizeof(buffer));
+
+               /* Set rbindex locations. */
+               for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
+                       rbindex_location[i] = i;
+
+               /* Set Android Things key version rbindex locations */
+               rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS]
+                                               = AVB_ATX_PIK_VERSION_LOCATION;
+               rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1]
+                                               = AVB_ATX_PSK_VERSION_LOCATION;
+
+               /* Read rollback index and set the reponse*/
+               for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2; i++) {
+                       location = rbindex_location[i];
+                       if (fsl_avb_ops.read_rollback_index(&fsl_avb_ops,
+                                                               location, &rbindex)
+                                                               != AVB_IO_RESULT_OK) {
+                               printf("Read rollback index error!\n");
+                               snprintf(response, FASTBOOT_RESPONSE_LEN,
+                                       "INFOread rollback index error when get avb-min-versions");
+                               return -1;
+                       }
+                       /* Generate the "location:value" pair */
+                       snprintf(buffer, sizeof(buffer), "%d:%lld", location, rbindex);
+                       if (i != AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1)
+                               strncat(buffer, ",", strlen(","));
+
+                       if ((chars_left - (int)strlen(buffer)) >= 0) {
+                               strncat(response, buffer, strlen(buffer));
+                               chars_left -= strlen(buffer);
+                       } else {
+                               strncat(response, buffer, chars_left);
+                               /* reponse buffer is full, send it first */
+                               fastboot_tx_write_more(response);
+                               /* reset the reponse buffer for next round */
+                               memset(response, '\0', FASTBOOT_RESPONSE_LEN);
+                               strncpy(response, "INFO", 5);
+                               /* Copy left strings from 'buffer' to 'response' */
+                               strncat(response, buffer + chars_left, strlen(buffer));
+                               chars_left = FASTBOOT_RESPONSE_LEN -
+                                               strlen(response) - 1;
+                       }
+               }
+
+       }
+#endif
+       else {
+               char envstr[32];
+
+               snprintf(envstr, sizeof(envstr) - 1, "fastboot.%s", cmd);
+               s = env_get(envstr);
+               if (s) {
+                       strncat(response, s, chars_left);
+               } else {
+                       snprintf(response, chars_left, "FAILunknown variable:%s",cmd);
+                       printf("WARNING: unknown variable: %s\n", cmd);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+void fastboot_getvar(char *cmd, char *response)
+{
+       int n = 0;
+       int status = 0;
+       int count = 0;
+       char var_name[FASTBOOT_RESPONSE_LEN];
+       char partition_base_name[MAX_PTN][20];
+       char slot_suffix[2][5] = {"a","b"};
+
+       if (!cmd) {
+               pr_err("missing variable");
+               fastboot_fail("missing var", response);
+               return;
+       }
+
+       if (!strcmp_l1("all", cmd)) {
+
+               memset(response, '\0', FASTBOOT_RESPONSE_LEN);
+
+
+               /* get common variables */
+               for (n = 0; n < FASTBOOT_COMMON_VAR_NUM; n++) {
+                       snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_common_var[n]);
+                       get_single_var(fastboot_common_var[n], response);
+                       fastboot_tx_write_more(response);
+               }
+
+               /* get at-vboot-state variables */
+#ifdef CONFIG_AVB_ATX
+               for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) {
+                       snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_at_vboot_state_var[n]);
+                       get_single_var(fastboot_at_vboot_state_var[n], response);
+                       fastboot_tx_write_more(response);
+               }
+#endif
+               /* get partition type */
+               for (n = 0; n < g_pcount; n++) {
+                       snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOpartition-type:%s:", g_ptable[n].name);
+                       snprintf(var_name, sizeof(var_name), "partition-type:%s", g_ptable[n].name);
+                       get_single_var(var_name, response);
+                       fastboot_tx_write_more(response);
+               }
+               /* get partition size */
+               for (n = 0; n < g_pcount; n++) {
+                       snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOpartition-size:%s:", g_ptable[n].name);
+                       snprintf(var_name, sizeof(var_name), "partition-size:%s", g_ptable[n].name);
+                       get_single_var(var_name,response);
+                       fastboot_tx_write_more(response);
+               }
+               /* slot related variables */
+               if (fastboot_parts_is_slot()) {
+                       /* get has-slot variables */
+                       count = fastboot_parts_get_name(partition_base_name);
+                       for (n = 0; n < count; n++) {
+                               snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOhas-slot:%s:", partition_base_name[n]);
+                               snprintf(var_name, sizeof(var_name), "has-slot:%s", partition_base_name[n]);
+                               get_single_var(var_name,response);
+                               fastboot_tx_write_more(response);
+                       }
+                       /* get current slot */
+                       strncpy(response, "INFOcurrent-slot:", FASTBOOT_RESPONSE_LEN);
+                       get_single_var("current-slot", response);
+                       fastboot_tx_write_more(response);
+                       /* get slot count */
+                       strncpy(response, "INFOslot-count:", FASTBOOT_RESPONSE_LEN);
+                       get_single_var("slot-count", response);
+                       fastboot_tx_write_more(response);
+                       /* get slot-successful variable */
+                       for (n = 0; n < 2; n++) {
+                               snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-successful:%s:", slot_suffix[n]);
+                               snprintf(var_name, sizeof(var_name), "slot-successful:%s", slot_suffix[n]);
+                               get_single_var(var_name, response);
+                               fastboot_tx_write_more(response);
+                       }
+                       /*get slot-unbootable variable*/
+                       for (n = 0; n < 2; n++) {
+                               snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-unbootable:%s:", slot_suffix[n]);
+                               snprintf(var_name, sizeof(var_name), "slot-unbootable:%s", slot_suffix[n]);
+                               get_single_var(var_name, response);
+                               fastboot_tx_write_more(response);
+                       }
+                       /*get slot-retry-count variable*/
+                       for (n = 0; n < 2; n++) {
+                               snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-retry-count:%s:", slot_suffix[n]);
+                               snprintf(var_name, sizeof(var_name), "slot-retry-count:%s", slot_suffix[n]);
+                               get_single_var(var_name, response);
+                               fastboot_tx_write_more(response);
+                       }
+               }
+
+               strncpy(response, "OKAYDone!", 10);
+               fastboot_tx_write_more(response);
+               fastboot_none_resp(response);
+
+               return;
+       }
+#ifdef CONFIG_AVB_ATX
+       else if (!strcmp_l1("at-vboot-state", cmd)) {
+                       /* get at-vboot-state variables */
+               for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) {
+                       snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_at_vboot_state_var[n]);
+                       get_single_var(fastboot_at_vboot_state_var[n], response);
+                       fastboot_tx_write_more(response);
+               }
+
+               strncpy(response, "OKAY", 5);
+               fastboot_tx_write_more(response);
+               fastboot_none_resp(response);
+
+               return;
+       } else if ((!strcmp_l1("bootloader-locked", cmd)) ||
+                       (!strcmp_l1("bootloader-min-versions", cmd)) ||
+                       (!strcmp_l1("avb-perm-attr-set", cmd)) ||
+                       (!strcmp_l1("avb-locked", cmd)) ||
+                       (!strcmp_l1("avb-unlock-disabled", cmd)) ||
+                       (!strcmp_l1("avb-min-versions", cmd))) {
+
+               printf("Can't get this variable alone, get 'at-vboot-state' instead!\n");
+               fastboot_fail("Can't get this variable alone, get 'at-vboot-state' instead.", response);
+               return;
+       }
+#endif
+       else {
+               char reason[FASTBOOT_RESPONSE_LEN];
+               memset(reason, '\0', FASTBOOT_RESPONSE_LEN);
+
+               status = get_single_var(cmd, reason);
+               if (status != 0)
+                       fastboot_fail(reason, response);
+               else
+                       fastboot_okay(reason, response);
+
+               return;
+       }
+}
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_partitions.c b/drivers/fastboot/fb_fsl/fb_fsl_partitions.c
new file mode 100644 (file)
index 0000000..3ea3a27
--- /dev/null
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <asm/mach-imx/sys_proto.h>
+#include <fb_fsl.h>
+#include <fastboot.h>
+#include <mmc.h>
+#include <android_image.h>
+#include <asm/bootm.h>
+#include <nand.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+#include <image.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/setup.h>
+#include <env.h>
+#ifdef CONFIG_SATA
+#include <sata.h>
+#endif
+
+#if defined(CONFIG_FASTBOOT_LOCK)
+#include "fastboot_lock_unlock.h"
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#include "u-boot/sha256.h"
+#include <trusty/libtipc.h>
+#endif
+
+
+#ifndef TRUSTY_OS_MMC_BLKS
+#define TRUSTY_OS_MMC_BLKS 0x7FF
+#endif
+
+#define MEK_8QM_EMMC 0
+
+enum {
+       PTN_GPT_INDEX = 0,
+       PTN_TEE_INDEX,
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+       PTN_M4_OS_INDEX,
+#endif
+       PTN_ALL_INDEX,
+       PTN_BOOTLOADER_INDEX,
+};
+
+struct fastboot_ptentry g_ptable[MAX_PTN];
+unsigned int g_pcount;
+
+static ulong bootloader_mmc_offset(void)
+{
+       if (is_imx8mq() || is_imx8mm() || (is_imx8() && is_soc_rev(CHIP_REV_A)))
+               return 0x8400;
+       else if (is_imx8qm()) {
+               if (MEK_8QM_EMMC == fastboot_devinfo.dev_id)
+               /* target device is eMMC boot0 partition, bootloader offset is 0x0 */
+                       return 0x0;
+               else
+               /* target device is SD card, bootloader offset is 0x8000 */
+                       return 0x8000;
+       } else if (is_imx8mn() || is_imx8mp()) {
+               /* target device is eMMC boot0 partition, bootloader offset is 0x0 */
+               if (env_get_ulong("emmc_dev", 10, 2) == fastboot_devinfo.dev_id)
+                       return 0;
+               else
+                       return 0x8000;
+       }
+       else if (is_imx8())
+               return 0x8000;
+       else
+               return 0x400;
+}
+
+bool bootloader_gpt_overlay(void)
+{
+       return (g_ptable[PTN_GPT_INDEX].partition_id  == g_ptable[PTN_BOOTLOADER_INDEX].partition_id  &&
+               bootloader_mmc_offset() < ANDROID_GPT_END);
+}
+
+/**
+   @mmc_dos_partition_index: the partition index in mbr.
+   @mmc_partition_index: the boot partition or user partition index,
+   not related to the partition table.
+ */
+static int _fastboot_parts_add_ptable_entry(int ptable_index,
+                                     int mmc_dos_partition_index,
+                                     int mmc_partition_index,
+                                     const char *name,
+                                     const char *fstype,
+                                     struct blk_desc *dev_desc,
+                                     struct fastboot_ptentry *ptable)
+{
+       struct disk_partition info;
+
+       if (part_get_info(dev_desc,
+                              mmc_dos_partition_index, &info)) {
+               debug("Bad partition index:%d for partition:%s\n",
+                      mmc_dos_partition_index, name);
+               return -1;
+       }
+       ptable[ptable_index].start = info.start;
+       ptable[ptable_index].length = info.size;
+       ptable[ptable_index].partition_id = mmc_partition_index;
+       ptable[ptable_index].partition_index = mmc_dos_partition_index;
+       strncpy(ptable[ptable_index].name, (const char *)info.name,
+                       sizeof(ptable[ptable_index].name) - 1);
+
+#ifdef CONFIG_PARTITION_UUIDS
+       strcpy(ptable[ptable_index].uuid, (const char *)info.uuid);
+#endif
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+       if (!strcmp((const char *)info.name, FASTBOOT_PARTITION_SYSTEM_A) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_SYSTEM_B) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_OEM_A) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_VENDOR_A) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_OEM_B) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_VENDOR_B) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_DATA))
+#else
+       if (!strcmp((const char *)info.name, FASTBOOT_PARTITION_SYSTEM) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_DATA) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_DEVICE) ||
+           !strcmp((const char *)info.name, FASTBOOT_PARTITION_CACHE))
+#endif
+               strcpy(ptable[ptable_index].fstype, "ext4");
+       else
+               strcpy(ptable[ptable_index].fstype, "raw");
+       return 0;
+}
+
+static int _fastboot_parts_load_from_ptable(void)
+{
+       int i;
+
+       /* mmc boot partition: -1 means no partition, 0 user part., 1 boot part.
+        * default is no partition, for emmc default user part, except emmc*/
+       int boot_partition = FASTBOOT_MMC_NONE_PARTITION_ID;
+       int user_partition = FASTBOOT_MMC_NONE_PARTITION_ID;
+
+       struct mmc *mmc;
+       struct blk_desc *dev_desc;
+       struct fastboot_ptentry ptable[MAX_PTN];
+
+       /* sata case in env */
+       if (fastboot_devinfo.type == DEV_SATA) {
+#ifdef CONFIG_SATA
+               int sata_device_no = fastboot_devinfo.dev_id;
+               puts("flash target is SATA\n");
+               if (sata_initialize())
+                       return -1;
+               if (sata_device_no >= CONFIG_SYS_SATA_MAX_DEVICE) {
+                       printf("Unknown SATA(%d) device for fastboot\n",
+                               sata_device_no);
+                       return -1;
+               }
+               dev_desc = sata_get_dev(sata_device_no);
+#else /*! CONFIG_SATA*/
+               puts("SATA isn't buildin\n");
+               return -1;
+#endif /*! CONFIG_SATA*/
+       } else if (fastboot_devinfo.type == DEV_MMC) {
+               int mmc_no = fastboot_devinfo.dev_id;
+
+               printf("flash target is MMC:%d\n", mmc_no);
+               mmc = find_mmc_device(mmc_no);
+
+               if (mmc == NULL) {
+                       printf("invalid mmc device %d\n", mmc_no);
+                       return -1;
+               }
+
+               /* Force to init mmc */
+               mmc->has_init = 0;
+               if (mmc_init(mmc))
+                       printf("MMC card init failed!\n");
+
+               dev_desc = blk_get_dev("mmc", mmc_no);
+               if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
+                       printf("** Block device MMC %d not supported\n",
+                               mmc_no);
+                       return -1;
+               }
+
+               /* multiple boot paritions for eMMC 4.3 later */
+               if (mmc->part_config != MMCPART_NOAVAILABLE) {
+                       boot_partition = FASTBOOT_MMC_BOOT_PARTITION_ID;
+                       user_partition = FASTBOOT_MMC_USER_PARTITION_ID;
+               }
+       } else {
+               printf("Can't setup partition table on this device %d\n",
+                       fastboot_devinfo.type);
+               return -1;
+       }
+
+       memset((char *)ptable, 0,
+                   sizeof(struct fastboot_ptentry) * (MAX_PTN));
+       /* GPT */
+       strcpy(ptable[PTN_GPT_INDEX].name, FASTBOOT_PARTITION_GPT);
+       ptable[PTN_GPT_INDEX].start = ANDROID_GPT_OFFSET / dev_desc->blksz;
+       ptable[PTN_GPT_INDEX].length = ANDROID_GPT_SIZE  / dev_desc->blksz;
+       ptable[PTN_GPT_INDEX].partition_id = user_partition;
+       ptable[PTN_GPT_INDEX].flags = FASTBOOT_PTENTRY_FLAGS_UNERASEABLE;
+       strcpy(ptable[PTN_GPT_INDEX].fstype, "raw");
+
+#ifndef CONFIG_ARM64
+       /* Trusty OS */
+       strcpy(ptable[PTN_TEE_INDEX].name, FASTBOOT_PARTITION_TEE);
+       ptable[PTN_TEE_INDEX].start = 0;
+       ptable[PTN_TEE_INDEX].length = TRUSTY_OS_MMC_BLKS;
+       ptable[PTN_TEE_INDEX].partition_id = TEE_HWPARTITION_ID;
+       strcpy(ptable[PTN_TEE_INDEX].fstype, "raw");
+#endif
+
+       /* Add m4_os partition if we support mcu firmware image flash */
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+       strcpy(ptable[PTN_M4_OS_INDEX].name, FASTBOOT_MCU_FIRMWARE_PARTITION);
+       ptable[PTN_M4_OS_INDEX].start = ANDROID_MCU_FIRMWARE_START / dev_desc->blksz;
+       ptable[PTN_M4_OS_INDEX].length = ANDROID_MCU_FIRMWARE_SIZE / dev_desc->blksz;
+       ptable[PTN_M4_OS_INDEX].flags = FASTBOOT_PTENTRY_FLAGS_UNERASEABLE;
+       ptable[PTN_M4_OS_INDEX].partition_id = user_partition;
+       strcpy(ptable[PTN_M4_OS_INDEX].fstype, "raw");
+#endif
+
+       strcpy(ptable[PTN_ALL_INDEX].name, FASTBOOT_PARTITION_ALL);
+       ptable[PTN_ALL_INDEX].start = 0;
+       ptable[PTN_ALL_INDEX].length = dev_desc->lba;
+       ptable[PTN_ALL_INDEX].partition_id = user_partition;
+       strcpy(ptable[PTN_ALL_INDEX].fstype, "device");
+
+       /* Bootloader */
+       strcpy(ptable[PTN_BOOTLOADER_INDEX].name, FASTBOOT_PARTITION_BOOTLOADER);
+       ptable[PTN_BOOTLOADER_INDEX].start =
+                               bootloader_mmc_offset() / dev_desc->blksz;
+       ptable[PTN_BOOTLOADER_INDEX].length =
+                                ANDROID_BOOTLOADER_SIZE / dev_desc->blksz;
+       ptable[PTN_BOOTLOADER_INDEX].partition_id = boot_partition;
+       ptable[PTN_BOOTLOADER_INDEX].flags = FASTBOOT_PTENTRY_FLAGS_UNERASEABLE;
+       strcpy(ptable[PTN_BOOTLOADER_INDEX].fstype, "raw");
+
+       int tbl_idx;
+       int part_idx = 1;
+       int ret;
+       for (tbl_idx = PTN_BOOTLOADER_INDEX + 1; tbl_idx < MAX_PTN; tbl_idx++) {
+               ret = _fastboot_parts_add_ptable_entry(tbl_idx,
+                               part_idx++,
+                               user_partition,
+                               NULL,
+                               NULL,
+                               dev_desc, ptable);
+               if (ret)
+                       break;
+       }
+       for (i = 0; i < tbl_idx; i++)
+               fastboot_flash_add_ptn(&ptable[i]);
+
+       return 0;
+}
+
+void fastboot_load_partitions(void)
+{
+       g_pcount = 0;
+       _fastboot_parts_load_from_ptable();
+}
+
+/*
+ * Android style flash utilties */
+void fastboot_flash_add_ptn(struct fastboot_ptentry *ptn)
+{
+       if (g_pcount < MAX_PTN) {
+               memcpy(g_ptable + g_pcount, ptn, sizeof(struct fastboot_ptentry));
+               g_pcount++;
+       }
+}
+
+void fastboot_flash_dump_ptn(void)
+{
+       unsigned int n;
+       for (n = 0; n < g_pcount; n++) {
+               struct fastboot_ptentry *ptn = g_ptable + n;
+               printf("idx %d, ptn %d name='%s' start=%d len=%d\n",
+                       n, ptn->partition_index, ptn->name, ptn->start, ptn->length);
+       }
+}
+
+
+struct fastboot_ptentry *fastboot_flash_find_ptn(const char *name)
+{
+       unsigned int n;
+
+       for (n = 0; n < g_pcount; n++) {
+               /* Make sure a substring is not accepted */
+               if (strlen(name) == strlen(g_ptable[n].name)) {
+                       if (0 == strcmp(g_ptable[n].name, name))
+                               return g_ptable + n;
+               }
+       }
+
+       return 0;
+}
+
+int fastboot_flash_find_index(const char *name)
+{
+       struct fastboot_ptentry *ptentry = fastboot_flash_find_ptn(name);
+       if (ptentry == NULL) {
+               printf("cannot get the partion info for %s\n",name);
+               fastboot_flash_dump_ptn();
+               return -1;
+       }
+       return ptentry->partition_index;
+}
+
+struct fastboot_ptentry *fastboot_flash_get_ptn(unsigned int n)
+{
+       if (n < g_pcount)
+               return g_ptable + n;
+       else
+               return 0;
+}
+
+unsigned int fastboot_flash_get_ptn_count(void)
+{
+       return g_pcount;
+}
+
+bool fastboot_parts_is_raw(struct fastboot_ptentry *ptn)
+{
+       if (ptn) {
+               if (!strncmp(ptn->name, FASTBOOT_PARTITION_BOOTLOADER,
+                       strlen(FASTBOOT_PARTITION_BOOTLOADER)))
+                       return true;
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+               else if (!strncmp(ptn->name, FASTBOOT_PARTITION_GPT,
+                       strlen(FASTBOOT_PARTITION_GPT)) ||
+                       !strncmp(ptn->name, FASTBOOT_PARTITION_BOOT_A,
+                       strlen(FASTBOOT_PARTITION_BOOT_A)) ||
+                       !strncmp(ptn->name, FASTBOOT_PARTITION_BOOT_B,
+                       strlen(FASTBOOT_PARTITION_BOOT_B)))
+                       return true;
+#else
+               else if (!strncmp(ptn->name, FASTBOOT_PARTITION_BOOT,
+                       strlen(FASTBOOT_PARTITION_BOOT)))
+                       return true;
+#endif
+#if defined(CONFIG_FASTBOOT_LOCK)
+               else if (!strncmp(ptn->name, FASTBOOT_PARTITION_FBMISC,
+                       strlen(FASTBOOT_PARTITION_FBMISC)))
+                       return true;
+#endif
+               else if (!strncmp(ptn->name, FASTBOOT_PARTITION_MISC,
+                       strlen(FASTBOOT_PARTITION_MISC)))
+                       return true;
+       }
+
+        return false;
+}
+
+static bool is_exist(char (*partition_base_name)[20], char *buffer, int count)
+{
+       int n;
+
+       for (n = 0; n < count; n++) {
+               if (!strcmp(partition_base_name[n],buffer))
+                       return true;
+       }
+       return false;
+}
+
+/*get partition base name from gpt without "_a/_b"*/
+int fastboot_parts_get_name(char (*partition_base_name)[20])
+{
+       int n = 0;
+       int count = 0;
+       char *ptr1, *ptr2;
+       char buffer[20];
+
+       for (n = 0; n < g_pcount; n++) {
+               strcpy(buffer,g_ptable[n].name);
+               ptr1 = strstr(buffer, "_a");
+               ptr2 = strstr(buffer, "_b");
+               if (ptr1 != NULL) {
+                       *ptr1 = '\0';
+                       if (!is_exist(partition_base_name,buffer,count)) {
+                               strcpy(partition_base_name[count++],buffer);
+                       }
+               } else if (ptr2 != NULL) {
+                       *ptr2 = '\0';
+                       if (!is_exist(partition_base_name,buffer,count)) {
+                               strcpy(partition_base_name[count++],buffer);
+                       }
+               } else {
+                       strcpy(partition_base_name[count++],buffer);
+               }
+       }
+       return count;
+}
+
+bool fastboot_parts_is_slot(void)
+{
+       char slot_suffix[2][5] = {"_a","_b"};
+       int n;
+
+       for (n = 0; n < g_pcount; n++) {
+               if (strstr(g_ptable[n].name, slot_suffix[0]) ||
+               strstr(g_ptable[n].name, slot_suffix[1]))
+                       return true;
+       }
+       return false;
+}
+
index 8ba55aa..e8444cb 100644 (file)
  * that expect bulk OUT requests to be divisible by maxpacket size.
  */
 
+typedef struct usb_req usb_req;
+struct usb_req {
+       struct usb_request *in_req;
+       usb_req *next;
+};
+
 struct f_fastboot {
        struct usb_function usb_function;
 
        /* IN/OUT EP's and corresponding requests */
        struct usb_ep *in_ep, *out_ep;
        struct usb_request *in_req, *out_req;
+
+       usb_req *front, *rear;
 };
 
 static char fb_ext_prop_name[] = "DeviceInterfaceGUID";
@@ -194,6 +202,24 @@ static struct usb_gadget_strings *fastboot_strings[] = {
 
 static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
 
+static void fastboot_fifo_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       int status = req->status;
+       usb_req *request;
+
+       if (!status) {
+               if (fastboot_func->front != NULL) {
+                       request = fastboot_func->front;
+                       fastboot_func->front = fastboot_func->front->next;
+                       usb_ep_free_request(ep, request->in_req);
+                       free(request);
+               } else {
+                       printf("fail free request\n");
+               }
+               return;
+       }
+}
+
 static void fastboot_complete(struct usb_ep *ep, struct usb_request *req)
 {
        int status = req->status;
@@ -397,11 +423,57 @@ static int fastboot_add(struct usb_configuration *c)
 }
 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
 
-static int fastboot_tx_write(const char *buffer, unsigned int buffer_size)
+int fastboot_tx_write_more(const char *buffer)
+{
+       int ret = 0;
+
+       /* alloc usb request FIFO node */
+       usb_req *req = (usb_req *)malloc(sizeof(usb_req));
+       if (!req) {
+               printf("failed alloc usb req!\n");
+               return -ENOMEM;
+       }
+
+       /* usb request node FIFO enquene */
+       if ((fastboot_func->front == NULL) && (fastboot_func->rear == NULL)) {
+               fastboot_func->front = fastboot_func->rear = req;
+               req->next = NULL;
+       } else {
+               fastboot_func->rear->next = req;
+               fastboot_func->rear = req;
+               req->next = NULL;
+       }
+
+       /* alloc in request for current node */
+       req->in_req = fastboot_start_ep(fastboot_func->in_ep);
+       if (!req->in_req) {
+               printf("failed alloc req in\n");
+               fastboot_disable(&(fastboot_func->usb_function));
+               return  -EINVAL;
+       }
+       req->in_req->complete = fastboot_fifo_complete;
+
+       memcpy(req->in_req->buf, buffer, strlen(buffer));
+       req->in_req->length = strlen(buffer);
+
+       ret = usb_ep_queue(fastboot_func->in_ep, req->in_req, 0);
+       if (ret) {
+               printf("Error %d on queue\n", ret);
+               return -EINVAL;
+       }
+
+       ret = 0;
+       return ret;
+}
+
+int fastboot_tx_write(const char *buffer, unsigned int buffer_size)
 {
        struct usb_request *in_req = fastboot_func->in_req;
        int ret;
 
+       if (!buffer_size)
+               return 0;
+
        memcpy(in_req->buf, buffer, buffer_size);
        in_req->length = buffer_size;
 
@@ -512,6 +584,10 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
        char response[FASTBOOT_RESPONSE_LEN] = {0};
        int cmd = -1;
 
+       /* init in request FIFO pointer */
+       fastboot_func->front = NULL;
+       fastboot_func->rear  = NULL;
+
        if (req->status != 0 || req->length == 0)
                return;
 
index 54d25af..ef6ecc2 100644 (file)
 
 /* The bootloader expects the structure of andr_img_hdr with header
  * version 0 to be as follows: */
+/* Boot metric variables (in millisecond) */
+struct boot_metric
+{
+       u32 bll_1;      /* 1th bootloader load duration */
+       u32 ble_1;      /* 1th bootloader exec duration */
+       u32 kl;         /* kernel image load duration */
+       u32 kd;         /* kernel image decompress duration */
+       u32 avb;        /* avb verify boot.img duration */
+       u32 odt;        /* overlay device tree duration */
+       u32 sw;         /* system wait for UI interaction duration*/
+};
+typedef struct boot_metric boot_metric;
+
 struct andr_img_hdr {
     /* Must be ANDR_BOOT_MAGIC. */
     char magic[ANDR_BOOT_MAGIC_SIZE];
@@ -73,16 +86,19 @@ struct andr_img_hdr {
  * +-----------------+
  * | boot header     | 1 page
  * +-----------------+
- * | kernel          | n pages
+ * | kernel          | i pages
  * +-----------------+
  * | ramdisk         | m pages
  * +-----------------+
- * | second stage    | o pages
+ * | second stage    | n pages
+ * +-----------------+
+ * | recovery dtbo   | o pages
  * +-----------------+
  *
- * n = (kernel_size + page_size - 1) / page_size
+ * i = (kernel_size + page_size - 1) / page_size
  * m = (ramdisk_size + page_size - 1) / page_size
- * o = (second_size + page_size - 1) / page_size
+ * n = (second_size + page_size - 1) / page_size
+ * o = (recovery_dtbo_size + page_size - 1) / page_size
  *
  * 0. all entities are page_size aligned in flash
  * 1. kernel and ramdisk are required (size != 0)
@@ -136,4 +152,16 @@ struct andr_img_hdr {
  *    else: jump to kernel_addr
  */
 
+struct header_image {
+       uint32_t        code0;          /* Executable code */
+       uint32_t        code1;          /* Executable code */
+       uint64_t        text_offset;    /* Image load offset, LE */
+       uint64_t        image_size;     /* Effective Image size, LE */
+       uint64_t        res1;           /* reserved */
+       uint64_t        res2;           /* reserved */
+       uint64_t        res3;           /* reserved */
+       uint64_t        res4;           /* reserved */
+       uint32_t        magic;          /* Magic number */
+       uint32_t        res5;
+};
 #endif
index 747f8f8..1498fc2 100644 (file)
@@ -203,6 +203,10 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
 int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size,
                      const char *r, const char *s, bool global);
 
+#ifdef CONFIG_CMD_READ
+int do_raw_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+#endif
+
 /*
  * Error codes that commands return to cmd_process(). We use the standard 0
  * and 1 for success and failure, but add one more case - failure with a
index 57daaf1..5671cba 100644 (file)
@@ -48,7 +48,20 @@ enum {
        FASTBOOT_COMMAND_ACMD,
        FASTBOOT_COMMAND_UCMD,
 #endif
-
+#ifdef CONFIG_FSL_FASTBOOT
+       FASTBOOT_COMMAND_UPLOAD,
+       FASTBOOT_COMMAND_GETSTAGED,
+#ifdef CONFIG_FASTBOOT_LOCK
+       FASTBOOT_COMMAND_FLASHING,
+       FASTBOOT_COMMAND_OEM,
+#endif
+#ifdef CONFIG_AVB_SUPPORT
+       FASTBOOT_COMMAND_SETACTIVE,
+#endif
+#ifdef CONFIG_AVB_ATX
+       FASTBOOT_COMMAND_STAGE,
+#endif
+#endif
        FASTBOOT_COMMAND_COUNT
 };
 
@@ -176,4 +189,9 @@ void fastboot_data_complete(char *response);
 #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
 void fastboot_acmd_complete(void);
 #endif
+
+int fastboot_tx_write_more(const char *buffer);
+
+int fastboot_tx_write(const char *buffer, unsigned int buffer_size);
+
 #endif /* _FASTBOOT_H_ */
diff --git a/include/fb_fsl.h b/include/fb_fsl.h
new file mode 100644 (file)
index 0000000..dbd3701
--- /dev/null
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ */
+
+#ifndef FB_FSL_H
+#define FB_FSL_H
+#include <stdbool.h>
+#include <linux/types.h>
+
+#define FASTBOOT_PTENTRY_FLAGS_REPEAT(n)              (n & 0x0f)
+#define FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK            0x0000000F
+
+/* Writes happen a block at a time.
+   If the write fails, go to next block
+   NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK  0x00000010
+
+/* Find a contiguous block big enough for a the whole file
+   NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK 0x00000020
+
+/* Write the file with write.i */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_I                0x00000100
+
+/* Write the file with write.trimffs */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_TRIMFFS          0x00000200
+
+/* Write the file as a series of variable/value pairs
+   using the setenv and saveenv commands */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_ENV              0x00000400
+
+/* Uneraseable partition */
+#define FASTBOOT_PTENTRY_FLAGS_UNERASEABLE            0x00000800
+
+#define FASTBOOT_MMC_BOOT_PARTITION_ID  1
+#define FASTBOOT_MMC_USER_PARTITION_ID  0
+#define FASTBOOT_MMC_NONE_PARTITION_ID -1
+#define FASTBOOT_MMC_BOOT1_PARTITION_ID  2
+
+#define FASTBOOT_PARTITION_TEE "tos"
+#define FASTBOOT_PARTITION_PRDATA "presistdata"
+
+#ifdef CONFIG_AVB_SUPPORT
+#define FASTBOOT_PARTITION_AVBKEY "avbkey"
+#endif
+
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+#define FASTBOOT_MCU_FIRMWARE_PARTITION "m4_os"
+#endif
+
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+#define FASTBOOT_PARTITION_BOOT_A "boot_a"
+#define FASTBOOT_PARTITION_RECOVERY "recovery"
+#define FASTBOOT_PARTITION_SYSTEM_A "system_a"
+#define FASTBOOT_PARTITION_BOOTLOADER "bootloader0"
+#define FASTBOOT_PARTITION_DATA "userdata"
+#define FASTBOOT_PARTITION_BOOT_B "boot_b"
+#define FASTBOOT_PARTITION_SYSTEM_B "system_b"
+#define FASTBOOT_PARTITION_OEM_A "oem_a"
+#define FASTBOOT_PARTITION_VENDOR_A "vendor_a"
+#define FASTBOOT_PARTITION_OEM_B "oem_b"
+#define FASTBOOT_PARTITION_VENDOR_B "vendor_b"
+#ifdef CONFIG_AVB_SUPPORT
+#define FASTBOOT_PARTITION_VBMETA_A "vbmeta_a"
+#define FASTBOOT_PARTITION_VBMETA_B "vbmeta_b"
+#endif
+#define FASTBOOT_PARTITION_MISC "misc"
+#define FASTBOOT_PARTITION_GPT "gpt"
+#define FASTBOOT_PARTITION_FBMISC "fbmisc"
+#else
+#define FASTBOOT_PARTITION_BOOT "boot"
+#define FASTBOOT_PARTITION_RECOVERY "recovery"
+#define FASTBOOT_PARTITION_SYSTEM "system"
+#define FASTBOOT_PARTITION_CACHE "cache"
+#define FASTBOOT_PARTITION_DEVICE "device"
+#define FASTBOOT_PARTITION_BOOTLOADER "bootloader"
+#define FASTBOOT_PARTITION_DATA "userdata"
+#define FASTBOOT_PARTITION_GPT "gpt"
+#define FASTBOOT_PARTITION_MISC "misc"
+#define FASTBOOT_PARTITION_FBMISC "fbmisc"
+#endif
+
+#ifdef CONFIG_IMX_TRUSTY_OS
+#ifndef CONFIG_AVB_ATX
+#define FASTBOOT_SET_RPMB_KEY "set-rpmb-key"
+#define FASTBOOT_SET_RPMB_RANDOM_KEY "set-rpmb-random-key"
+#define FASTBOOT_SET_VBMETA_PUBLIC_KEY "set-public-key"
+#endif
+
+#define FASTBOOT_SET_CA_RESP "at-set-ca-response"
+#define FASTBOOT_GET_CA_REQ  "at-get-ca-request"
+#define FASTBOOT_SET_RSA_ATTESTATION_KEY  "set-rsa-atte-key"
+#define FASTBOOT_SET_EC_ATTESTATION_KEY  "set-ec-atte-key"
+#define FASTBOOT_APPEND_RSA_ATTESTATION_CERT  "append-rsa-atte-cert"
+#define FASTBOOT_APPEND_EC_ATTESTATION_CERT  "append-ec-atte-cert"
+#endif
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+#define FASTBOOT_BOOTLOADER_VBOOT_KEY "fuse at-bootloader-vboot-key"
+#ifdef CONFIG_AVB_ATX
+#define FASTBOOT_AVB_AT_PERM_ATTR "fuse at-perm-attr"
+#define FASTBOOT_AT_UNLOCK_VBOOT "at-unlock-vboot"
+#define FASTBOOT_AT_LOCK_VBOOT "at-lock-vboot"
+#define FASTBOOT_AT_DISABLE_UNLOCK_VBOOT "at-disable-unlock-vboot"
+#define FASTBOOT_AT_GET_UNLOCK_CHALLENGE "at-get-vboot-unlock-challenge"
+#endif /* CONFIG_AVB_ATX */
+#endif /* CONFIG_ANDROID_THINGS_SUPPORT */
+
+#ifndef TEE_HWPARTITION_ID
+#define TEE_HWPARTITION_ID 2
+#endif
+
+#define FASTBOOT_PARTITION_ALL "all"
+
+#define MMC_SATA_BLOCK_SIZE 512
+
+#define ANDROID_MBR_OFFSET         0
+#define ANDROID_MBR_SIZE           0x200
+#define ANDROID_BOOTLOADER_SIZE            0x400000
+
+#define ANDROID_GPT_OFFSET         0
+#define ANDROID_GPT_SIZE           0x100000
+#define ANDROID_GPT_END                   0x4400
+
+/* To support the Android-style naming of flash */
+#define MAX_PTN                    32
+
+enum {
+    DEV_SATA,
+    DEV_MMC,
+    DEV_NAND,
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+    /* SPI Flash */
+    DEV_SF
+#endif
+};
+
+typedef enum {
+#ifdef CONFIG_ANDROID_RECOVERY
+       /* Revoery boot due to combo keys pressed */
+       BOOTMODE_RECOVERY_KEY_PRESSED,
+       /* Recovery boot due to boot-recovery cmd in misc parition */
+       BOOTMODE_RECOVERY_BCB_CMD,
+#endif
+       /* Fastboot boot due to bootonce-bootloader cmd in misc parition */
+       BOOTMODE_FASTBOOT_BCB_CMD,
+       /* Normal boot */
+       BOOTMODE_NORMAL
+}FbBootMode;
+
+/* flash partitions are defined in terms of blocks
+** (flash erase units)
+*/
+struct fastboot_ptentry {
+       /* The logical name for this partition, null terminated */
+       char name[20];
+       /* The start wrt the nand part, must be multiple of nand block size */
+       unsigned int start;
+       /* The length of the partition, must be multiple of nand block size */
+       unsigned int length;
+       /* Controls the details of how operations are done on the partition
+          See the FASTBOOT_PTENTRY_FLAGS_*'s defined below */
+       unsigned int flags;
+       /* partition id: 0 - normal partition; 1 - boot partition */
+       unsigned int partition_id;
+       /* partition number in block device */
+       unsigned int partition_index;
+       /* partition file system type in string */
+       char fstype[16];
+       /* filesystem UUID as string, if exists */
+#ifdef CONFIG_PARTITION_UUIDS
+       char uuid[37];
+#endif
+};
+
+struct fastboot_device_info {
+       unsigned char type;
+       unsigned char dev_id;
+};
+
+extern struct fastboot_device_info fastboot_devinfo;
+
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+extern struct fastboot_device_info fastboot_firmwareinfo;
+#endif
+
+extern struct fastboot_ptentry g_ptable[MAX_PTN];
+extern unsigned int g_pcount;
+
+/* Prepare the fastboot environments,
+  * should be executed before "fastboot" cmd
+  */
+void fastboot_setup(void);
+
+
+/* The Android-style flash handling */
+
+/* tools to populate and query the partition table */
+void fastboot_flash_add_ptn(struct fastboot_ptentry *ptn);
+struct fastboot_ptentry *fastboot_flash_find_ptn(const char *name);
+struct fastboot_ptentry *fastboot_flash_get_ptn(unsigned n);
+unsigned int fastboot_flash_get_ptn_count(void);
+void fastboot_flash_dump_ptn(void);
+
+/* Make board into special boot mode  */
+void fastboot_run_bootmode(void);
+
+/*Setup board-relative fastboot environment */
+void board_fastboot_setup(void);
+
+/*return partition index according name*/
+int fastboot_flash_find_index(const char *name);
+
+bool fastboot_parts_is_slot(void);
+
+bool fastboot_parts_is_raw(struct fastboot_ptentry *ptn);
+
+/*get partition base name from gpt without "_a/_b"*/
+int fastboot_parts_get_name(char (*partition_base_name)[20]);
+
+void fastboot_load_partitions(void);
+
+void fastboot_none_resp(char *response);
+
+void fastboot_process_erase(const char *cmdbuf, char *response);
+
+void fastboot_process_flash(const char *cmdbuf, void *download_buffer,
+                             u32 download_bytes, char *response);
+
+/*check whether bootloader is overlay with GPT table*/
+bool bootloader_gpt_overlay(void);
+/* Check whether the combo keys pressed
+ * Return 1 if combo keys pressed for recovery boot
+ * Return 0 if no combo keys pressed
+ */
+int is_recovery_key_pressing(void);
+
+/* Reads |num_bytes| from offset |offset| from partition with name
+ * |partition| (NUL-terminated UTF-8 string). If |offset| is
+ * negative, its absolute value should be interpreted as the number
+ * of bytes from the end of the partition.
+ * It's basically copied from fsl_read_from_partition_multi() because
+ * we may want to read partition when AVB is not enabled. */
+int read_from_partition_multi(const char* partition,
+               int64_t offset, size_t num_bytes,void* buffer, size_t* out_num_read);
+#endif /* FB_FSL_H */
index b4b284d..05266b4 100644 (file)
@@ -1539,6 +1539,7 @@ void android_print_contents(const struct andr_img_hdr *hdr);
 #if !defined(CONFIG_SPL_BUILD)
 bool android_image_print_dtb_contents(ulong hdr_addr);
 #endif
+bool image_arm64(void *images);
 
 #endif /* CONFIG_ANDROID_BOOT_IMAGE */
 #endif /* !USE_HOSTCC */
index fd51d7f..7a32b57 100644 (file)
@@ -278,6 +278,10 @@ int init_func_vid(void);
 int checkboard(void);
 int show_board_info(void);
 
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+void get_reboot_reason(char *ret);
+#endif
+
 /**
  * Get the uppermost pointer that is valid to access
  *
index 8600881..5f92622 100644 (file)
@@ -956,6 +956,7 @@ int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
 extern uint mmc_get_env_part(struct mmc *mmc);
 # endif
 int mmc_get_env_dev(void);
+int mmc_map_to_kernel_blk(int dev_no);
 
 /* Minimum partition switch timeout in units of 10-milliseconds */
 #define MMC_MIN_PART_SWITCH_TIME       30 /* 300 ms */
index 6a88758..40c72f7 100644 (file)
@@ -410,6 +410,15 @@ int is_valid_gpt_buf(struct blk_desc *dev_desc, void *buf);
  */
 int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf);
 
+/**
+ * write_backup_gpt_partitions - write MBR, backup gpt table.
+ * @param dev_desc - block device descriptor
+ * @param buf - buffer which contains the MBR and Primary GPT info
+ *
+ * @return - '0' on success, otherwise error
+ */
+int write_backup_gpt_partitions(struct blk_desc *dev_desc, void *buf);
+
 /**
  * gpt_verify_headers() - Function to read and CRC32 check of the GPT's header
  *                        and partition table entries (PTE)
diff --git a/include/recovery.h b/include/recovery.h
new file mode 100644 (file)
index 0000000..c6b097e
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __RECOVERY_H_
+#define __RECOVERY_H_
+
+struct reco_envs {
+       char *cmd;
+       char *args;
+};
+
+void board_recovery_setup(void);
+
+#endif
index ff92654..cd70eba 100644 (file)
@@ -8,8 +8,8 @@
 #include <part.h>
 #include <stdlib.h>
 
-#include <fsl_fastboot.h>
-#include "../../../drivers/usb/gadget/fastboot_lock_unlock.h"
+#include <fb_fsl.h>
+#include "../../../drivers/fastboot/fb_fsl/fastboot_lock_unlock.h"
 
 #include <fsl_avb.h>
 #include "fsl_avbkey.h"
index 8f853bc..1143c3f 100755 (executable)
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <stdlib.h>
 #include <linux/string.h>
-#include <fsl_fastboot.h>
+#include <fb_fsl.h>
 #include <fsl_avb.h>
 
 /* as libavb's bootctl doesn't have the get_var support
index 730ee0e..201c8a3 100644 (file)
@@ -28,6 +28,10 @@ CONFIG_AM335X_USB1_MODE
 CONFIG_AM437X_USB2PHY2_HOST
 CONFIG_ANDES_PCU
 CONFIG_ANDES_PCU_BASE
+CONFIG_ANDROID_AB_SUPPORT
+CONFIG_ANDROID_AUTO_SUPPORT
+CONFIG_ANDROID_SUPPORT
+CONFIG_ANDROID_THINGS_SUPPORT
 CONFIG_APER_0_BASE
 CONFIG_APER_1_BASE
 CONFIG_APER_SIZE
@@ -85,6 +89,10 @@ CONFIG_ATMEL_MCI_8BIT
 CONFIG_ATMEL_SPI0
 CONFIG_AT_TRANS
 CONFIG_AUTO_ZRELADDR
+CONFIG_AVB_FUSE
+CONFIG_AVB_FUSE_BANK_END
+CONFIG_AVB_FUSE_BANK_SIZEW
+CONFIG_AVB_FUSE_BANK_START
 CONFIG_BACKSIDE_L2_CACHE
 CONFIG_BAT_PAIR
 CONFIG_BAT_RW
@@ -380,6 +388,7 @@ CONFIG_EHCI_MXS_PORT0
 CONFIG_EHCI_MXS_PORT1
 CONFIG_EMU
 CONFIG_ENABLE_36BIT_PHYS
+CONFIG_ENABLE_LOCKSTATUS_SUPPORT
 CONFIG_ENABLE_MMU
 CONFIG_ENABLE_MUST_CHECK
 CONFIG_ENV_ADDR_FLEX
@@ -1639,6 +1648,7 @@ CONFIG_SXNI855T
 CONFIG_SYSFLAGS_ADDR
 CONFIG_SYSFS
 CONFIG_SYSMGR_ISWGRP_HANDOFF
+CONFIG_SYSTEM_RAMDISK_SUPPORT
 CONFIG_SYS_33MHZ
 CONFIG_SYS_64BIT
 CONFIG_SYS_64BIT_LBA