summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/arch-imx8/sys_proto.h1
-rw-r--r--arch/arm/include/asm/arch-mx6/sys_proto.h1
-rw-r--r--arch/arm/mach-imx/Kconfig6
-rw-r--r--arch/arm/mach-imx/imx8/cpu.c3
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c13
-rw-r--r--arch/arm/mach-imx/mx6/soc.c5
-rw-r--r--arch/arm/mach-imx/mx7/soc.c5
-rw-r--r--arch/arm/mach-imx/mx7ulp/soc.c21
-rw-r--r--board/freescale/common/Makefile3
-rw-r--r--board/freescale/common/recovery_keypad.c60
-rw-r--r--board/freescale/common/recovery_keypad.h13
-rw-r--r--cmd/fastboot.c4
-rw-r--r--cmd/fastboot/Kconfig42
-rw-r--r--cmd/read.c4
-rw-r--r--common/autoboot.c4
-rw-r--r--common/board_r.c23
-rw-r--r--common/image-android.c136
-rw-r--r--common/image-fdt.c31
-rw-r--r--disk/part_efi.c77
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/bcb.c169
-rw-r--r--drivers/usb/gadget/bcb.h58
-rw-r--r--drivers/usb/gadget/command.c62
-rw-r--r--drivers/usb/gadget/f_fastboot.c2952
-rw-r--r--drivers/usb/gadget/fastboot_lock_unlock.c467
-rw-r--r--drivers/usb/gadget/fastboot_lock_unlock.h71
-rw-r--r--include/android_image.h25
-rw-r--r--include/common.h4
-rw-r--r--include/fsl_fastboot.h250
-rw-r--r--include/image.h1
-rw-r--r--include/mmc.h1
-rw-r--r--include/part.h8
-rw-r--r--include/recovery.h18
-rw-r--r--scripts/config_whitelist.txt14
34 files changed, 4446 insertions, 108 deletions
diff --git a/arch/arm/include/asm/arch-imx8/sys_proto.h b/arch/arm/include/asm/arch-imx8/sys_proto.h
index 816040c5e9..26078fcfc1 100644
--- a/arch/arm/include/asm/arch-imx8/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8/sys_proto.h
@@ -19,3 +19,4 @@ struct pass_over_info_t {
int print_bootinfo(void);
int init_otg_power(void);
void power_off_pd_devices(const char* permanent_on_devices[], int size);
+enum boot_device get_boot_device(void);
diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h
index 75159a140c..ebb52f8388 100644
--- a/arch/arm/include/asm/arch-mx6/sys_proto.h
+++ b/arch/arm/include/asm/arch-mx6/sys_proto.h
@@ -35,6 +35,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);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 3470700137..16bcdea089 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -100,3 +100,9 @@ config NXP_BOARD_REVISION
NXP boards based on i.MX6/7 contain the board revision information
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.
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index 3630d9f006..fdaa30c3ca 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -26,6 +26,7 @@
#include <fdtdec.h>
#include <asm/arch/cpu.h>
#include <generated/version_autogenerated.h>
+#include <asm/setup.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -1392,4 +1393,4 @@ void disconnect_from_pc(void)
printf("conn_usb0 finding failed!\n");
return;
}
-} \ No newline at end of file
+}
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index c31f75b1e9..d507584faf 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -20,6 +20,7 @@
#include <fsl_wdog.h>
#include <imx_sip.h>
#include <generated/version_autogenerated.h>
+#include <asm/setup.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -196,6 +197,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
static int ft_add_optee_node(void *fdt, bd_t *bd)
diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c
index 72cde0eeb7..4dd14d7a20 100644
--- a/arch/arm/mach-imx/mx6/soc.c
+++ b/arch/arm/mach-imx/mx6/soc.c
@@ -23,6 +23,7 @@
#include <dm.h>
#include <imx_thermal.h>
#include <mmc.h>
+#include <asm/setup.h>
enum ldo_reg {
LDO_ARM,
@@ -805,6 +806,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;
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c
index 96eb782ed9..f9deb3c272 100644
--- a/arch/arm/mach-imx/mx7/soc.c
+++ b/arch/arm/mach-imx/mx7/soc.c
@@ -20,6 +20,7 @@
#include <imx_thermal.h>
#include <fsl_sec.h>
#include <fsl_wdog.h>
+#include <asm/setup.h>
#if defined(CONFIG_IMX_THERMAL)
static const struct imx_thermal_plat imx7_thermal_plat = {
@@ -293,6 +294,10 @@ void s_init(void)
/* clock configuration. */
clock_init();
+#if defined(CONFIG_ANDROID_SUPPORT)
+ /* Enable RTC */
+ writel(0x21, 0x30370038);
+#endif
return;
}
diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c
index 1cf783aa35..d04f91de24 100644
--- a/arch/arm/mach-imx/mx7ulp/soc.c
+++ b/arch/arm/mach-imx/mx7ulp/soc.c
@@ -12,6 +12,7 @@
#include <asm/mach-imx/hab.h>
#include <asm/mach-imx/boot_mode.h>
#include <fdt_support.h>
+#include <asm/setup.h>
static char *get_reset_cause(char *);
@@ -155,6 +156,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
}
return;
}
@@ -370,3 +376,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*/
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile
index b659ed3bae..dfe4ac6cf9 100644
--- a/board/freescale/common/Makefile
+++ b/board/freescale/common/Makefile
@@ -65,6 +65,9 @@ obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze.o
obj-$(CONFIG_POWER_MC34VR500) += mc34vr500.o
obj-$(CONFIG_MXC_EPDC) += epdc_setup.o
obj-y += mmc.o
+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
index 0000000000..fb15626b03
--- /dev/null
+++ b/board/freescale/common/recovery_keypad.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#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
index 0000000000..d315cea780
--- /dev/null
+++ b/board/freescale/common/recovery_keypad.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __RECOVERY_KEYPAD_H_
+#define __RECOVERY_KEYPAD_H_
+
+int is_recovery_keypad_pressing(void);
+
+#endif
diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index 8adcca592d..be4a11f9b7 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -23,7 +23,11 @@ static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
return CMD_RET_USAGE;
usb_controller = argv[1];
+#ifdef CONFIG_FASTBOOT_USB_DEV
+ controller_index = CONFIG_FASTBOOT_USB_DEV;
+#else
controller_index = simple_strtoul(usb_controller, NULL, 0);
+#endif
ret = board_usb_init(controller_index, USB_INIT_DEVICE);
if (ret) {
diff --git a/cmd/fastboot/Kconfig b/cmd/fastboot/Kconfig
index 0d2c2f131e..63b65b6ab9 100644
--- a/cmd/fastboot/Kconfig
+++ b/cmd/fastboot/Kconfig
@@ -26,6 +26,48 @@ config CMD_FASTBOOT
See doc/README.android-fastboot for more information.
+config FSL_FASTBOOT
+ bool "Enable FSL fastboot support"
+ select BCB_SUPPORT
+ help
+ This enables FSL implementation for Android fastboot.
+
+if FSL_FASTBOOT
+
+config ANDROID_RECOVERY
+ bool "Enable the recovery boot function"
+ help
+ This enables the Android Recovery boot function.
+
+config CMD_BOOTA
+ bool "Enable the boota command"
+ help
+ This enables the boota command for booting android images.
+
+config BCB_SUPPORT
+ bool
+
+choice
+ prompt "Android Image Storage select"
+ default FASTBOOT_STORAGE_MMC
+
+config FASTBOOT_STORAGE_MMC
+ bool "Using eMMC/SD for Android fastboot storage media"
+
+config FASTBOOT_STORAGE_NAND
+ bool "Using NAND flash for Android fastboot storage media"
+
+config FASTBOOT_STORAGE_SATA
+ bool "Using SATA disk for Android fastboot storage media"
+
+endchoice
+
+config FASTBOOT_SATA_NO
+ int "Sata device index"
+ depends on FASTBOOT_STORAGE_SATA
+
+endif #FSL_FASTBOOT
+
if USB_FUNCTION_FASTBOOT
config FASTBOOT_BUF_ADDR
diff --git a/cmd/read.c b/cmd/read.c
index 82c2d9ad99..7011d2869e 100644
--- a/cmd/read.c
+++ b/cmd/read.c
@@ -12,7 +12,7 @@
#include <command.h>
#include <part.h>
-int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_raw_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
char *ep;
struct blk_desc *dev_desc = NULL;
@@ -75,7 +75,7 @@ int do_read(cmd_tbl_t *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"
);
diff --git a/common/autoboot.c b/common/autoboot.c
index 1b52e44939..0d826e81df 100644
--- a/common/autoboot.c
+++ b/common/autoboot.c
@@ -311,7 +311,7 @@ const char *bootdelay_process(void)
s = env_get("bootdelay");
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
-#ifdef is_boot_from_usb
+#if !defined(CONFIG_FSL_FASTBOOT) && defined(is_boot_from_usb)
if (is_boot_from_usb()) {
disconnect_from_pc();
printf("Boot from USB for mfgtools\n");
@@ -349,7 +349,7 @@ const char *bootdelay_process(void)
#endif /* CONFIG_BOOTCOUNT_LIMIT */
s = env_get("bootcmd");
-#ifdef is_boot_from_usb
+#if !defined(CONFIG_FSL_FASTBOOT) && defined(is_boot_from_usb)
if (is_boot_from_usb()) {
s = env_get("bootcmd_mfg");
printf("Run bootcmd_mfg: %s\n", s);
diff --git a/common/board_r.c b/common/board_r.c
index 84d2b251f8..6d6adc13a9 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -54,6 +54,9 @@
#include <linux/compiler.h>
#include <linux/err.h>
#include <efi_loader.h>
+#ifdef CONFIG_FSL_FASTBOOT
+#include <fsl_fastboot.h>
+#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -659,6 +662,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
@@ -831,6 +848,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,
@@ -873,6 +893,9 @@ static init_fnc_t init_sequence_r[] = {
#ifdef AVB_RPMB
initr_avbkey,
#endif
+#ifdef CONFIG_FSL_FASTBOOT
+ initr_check_fastboot,
+#endif
run_main_loop,
};
diff --git a/common/image-android.c b/common/image-android.c
index 5ad3a1fa38..07d82d5459 100644
--- a/common/image-android.c
+++ b/common/image-android.c
@@ -1,6 +1,9 @@
/*
* Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -9,6 +12,11 @@
#include <android_image.h>
#include <malloc.h>
#include <errno.h>
+#include <asm/bootm.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/arch/sys_proto.h>
+#include <fsl_fastboot.h>
+#include <asm/setup.h>
#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000
@@ -51,6 +59,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);
/*
@@ -66,31 +75,110 @@ 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};
+ 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 if (*hdr->cmdline) {
+ if (strlen(hdr->cmdline) + 1 > sizeof(commandline)) {
+ printf("cmdline in bootimg is too long!\n");
+ return -1;
+ }
+ else
+ strncpy(commandline, hdr->cmdline, strlen(commandline) - 1);
}
- char *bootargs = env_get("bootargs");
- if (bootargs)
- len += strlen(bootargs);
+#ifdef CONFIG_SERIAL_TAG
+ struct tag_serialnr serialnr;
+ get_board_serial(&serialnr);
- char *newbootargs = malloc(len + 2);
- if (!newbootargs) {
- puts("Error: malloc in android_image_get_kernel failed!\n");
- return -ENOMEM;
+ sprintf(newbootargs,
+ " androidboot.serialno=%08x%08x",
+ serialnr.high,
+ serialnr.low);
+ strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+#endif
+
+ /* 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, " ");
+ 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));
+
+#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
+
+ /* 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));
+ }
+ }
+
+ printf("Kernel command line: %s\n", commandline);
+ env_set("bootargs", commandline);
if (os_data) {
*os_data = (ulong)hdr;
@@ -202,3 +290,15 @@ void android_print_contents(const struct andr_img_hdr *hdr)
printf("%scmdline: %s\n", p, hdr->cmdline);
}
#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;
+}
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 25103ba3b5..5691e964f5 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -6,6 +6,8 @@
* (C) Copyright 2000-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ *
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -413,7 +415,34 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
debug("## No Flattened Device Tree\n");
goto no_fdt;
}
- } else {
+ }
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+ else if (genimg_get_format((void *)images->os.start) ==
+ IMAGE_FORMAT_ANDROID) {
+ ulong fdt_data, fdt_len;
+ android_image_get_second((void *)images->os.start,
+ &fdt_data, &fdt_len);
+
+ if (fdt_len) {
+ fdt_blob = (char *)fdt_data;
+ printf(" Booting using the fdt at 0x%p\n", fdt_blob);
+
+ if (fdt_check_header(fdt_blob) != 0) {
+ fdt_error("image is not a fdt");
+ goto error;
+ }
+
+ if (fdt_totalsize(fdt_blob) != fdt_len) {
+ fdt_error("fdt size != image size");
+ goto error;
+ }
+ } else {
+ debug("## No Flattened Device Tree\n");
+ goto no_fdt;
+ }
+ }
+#endif
+ else {
debug("## No Flattened Device Tree\n");
goto no_fdt;
}
diff --git a/disk/part_efi.c b/disk/part_efi.c
index fb221eec09..ee9d64703d 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -135,6 +135,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;
@@ -145,7 +164,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);
@@ -281,14 +300,14 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
/* This function validates AND fills in the GPT header and PTE */
if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
gpt_head, &gpt_pte) != 1) {
- 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, &gpt_pte) != 1) {
printf("%s: *** ERROR: Invalid Backup GPT ***\n",
__func__);
return -1;
} else {
- printf("%s: *** Using Backup GPT ***\n",
+ debug("%s: *** Using Backup GPT ***\n",
__func__);
}
}
@@ -869,6 +888,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
/*
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 748366fb9f..becdc559ab 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,8 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
obj-$(CONFIG_DFU_OVER_USB) += f_dfu.o
obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
+obj-$(CONFIG_FASTBOOT_LOCK) += fastboot_lock_unlock.o
+obj-$(CONFIG_BCB_SUPPORT) += command.o bcb.o
obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
endif
diff --git a/drivers/usb/gadget/bcb.c b/drivers/usb/gadget/bcb.c
new file mode 100644
index 0000000000..645bc88a41
--- /dev/null
+++ b/drivers/usb/gadget/bcb.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <fsl_fastboot.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;
+ disk_partition_t 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/usb/gadget/bcb.h b/drivers/usb/gadget/bcb.h
new file mode 100644
index 0000000000..b5a2491014
--- /dev/null
+++ b/drivers/usb/gadget/bcb.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#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/usb/gadget/command.c b/drivers/usb/gadget/command.c
new file mode 100644
index 0000000000..e9f7d29173
--- /dev/null
+++ b/drivers/usb/gadget/command.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#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/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 7acffb6c87..9d91ab93b8 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -8,11 +8,15 @@
* Copyright 2014 Linaro, Ltd.
* Rob Herring <robh@kernel.org>
*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
* SPDX-License-Identifier: GPL-2.0+
*/
#include <config.h>
#include <common.h>
#include <errno.h>
+#include <stdlib.h>
#include <fastboot.h>
#include <malloc.h>
#include <linux/usb/ch9.h>
@@ -21,6 +25,7 @@
#include <linux/compiler.h>
#include <version.h>
#include <g_dnl.h>
+#include "../lib/avb/fsl/utils.h"
#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
#include <fb_mmc.h>
#endif
@@ -28,8 +33,43 @@
#include <fb_nand.h>
#endif
+#ifdef CONFIG_FSL_FASTBOOT
+#include <asm/mach-imx/sys_proto.h>
+#include <fsl_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 <environment.h>
+#ifdef CONFIG_ANDROID_RECOVERY
+#include <recovery.h>
+#endif
+
+#ifdef CONFIG_BCB_SUPPORT
+#include "bcb.h"
+#endif
+
+#ifdef CONFIG_AVB_SUPPORT
+#include <fsl_avb.h>
+#endif
+
+#ifdef CONFIG_FASTBOOT_LOCK
+#include "fastboot_lock_unlock.h"
+#endif
+#endif
+
#define FASTBOOT_VERSION "0.4"
+#define FASTBOOT_COMMON_VAR_NUM 13
+#define FASTBOOT_VAR_YES "yes"
+#define FASTBOOT_VAR_NO "no"
#define FASTBOOT_INTERFACE_CLASS 0xff
#define FASTBOOT_INTERFACE_SUB_CLASS 0x42
#define FASTBOOT_INTERFACE_PROTOCOL 0x03
@@ -39,18 +79,69 @@
#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040)
#define EP_BUFFER_SIZE 4096
+
+#ifdef CONFIG_FSL_FASTBOOT
+
+#define ANDROID_GPT_OFFSET 0
+#define ANDROID_GPT_SIZE 0x100000
+#define ANDROID_GPT_END 0x4400
+
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+struct fastboot_device_info fastboot_firmwareinfo;
+#endif
+
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+#define DST_DECOMPRESS_LEN 1024*1024*32
+#endif
+
+#endif
/*
* EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
* (64 or 512 or 1024), else we break on certain controllers like DWC3
* that expect bulk OUT requests to be divisible by maxpacket size.
*/
+/* 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"
+};
+
+/* Boot metric variables */
+boot_metric metrics = {
+ .bll_1 = 0,
+ .ble_1 = 0,
+ .kl = 0,
+ .kd = 0,
+ .avb = 0,
+ .odt = 0,
+ .sw = 0
+};
+
+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 inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
@@ -153,6 +244,1960 @@ static int strcmp_l1(const char *s1, const char *s2);
static char *fb_response_str;
+#ifdef CONFIG_FSL_FASTBOOT
+
+#define ANDROID_MBR_OFFSET 0
+#define ANDROID_MBR_SIZE 0x200
+#ifdef CONFIG_BOOTLOADER_OFFSET_33K
+#define ANDROID_BOOTLOADER_OFFSET 0x8400
+/* The Bootloader offset of imx8qxp B0 board is set to 32K */
+#elif defined(CONFIG_BOOTLOADER_OFFSET_32K)
+#define ANDROID_BOOTLOADER_OFFSET 0x8000
+#else
+#define ANDROID_BOOTLOADER_OFFSET 0x400
+#endif
+#define ANDROID_BOOTLOADER_SIZE 0x1FFC00
+
+#define MMC_SATA_BLOCK_SIZE 512
+#define FASTBOOT_FBPARTS_ENV_MAX_LEN 1024
+/* To support the Android-style naming of flash */
+#define MAX_PTN 32
+struct fastboot_ptentry g_ptable[MAX_PTN];
+unsigned int g_pcount;
+struct fastboot_device_info fastboot_devinfo;
+
+
+enum {
+ PTN_GPT_INDEX = 0,
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+ PTN_M4_OS_INDEX,
+#endif
+ PTN_BOOTLOADER_INDEX,
+};
+static unsigned int download_bytes_unpadded;
+
+static struct cmd_fastboot_interface interface = {
+ .rx_handler = NULL,
+ .reset_handler = NULL,
+ .product_name = NULL,
+ .serial_no = NULL,
+ .nand_block_size = 0,
+ .transfer_buffer = (unsigned char *)0xffffffff,
+ .transfer_buffer_size = 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);
+ 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;
+}
+
+static void save_env(struct fastboot_ptentry *ptn,
+ char *var, char *val)
+{
+ env_set(var, val);
+ env_save();
+}
+
+/* When save = 0, just parse. The input is unchanged
+ When save = 1, parse and do the save. The input is changed */
+static int parse_env(void *ptn, char *err_string, int save, int debug)
+{
+ int ret = 1;
+ unsigned int sets = 0;
+ unsigned int comment_start = 0;
+ char *var = NULL;
+ char *var_end = NULL;
+ char *val = NULL;
+ char *val_end = NULL;
+ unsigned int i;
+
+ char *buff = (char *)interface.transfer_buffer;
+ unsigned int size = download_bytes_unpadded;
+
+ /* The input does not have to be null terminated.
+ This will cause a problem in the corner case
+ where the last line does not have a new line.
+ Put a null after the end of the input.
+
+ WARNING : Input buffer is assumed to be bigger
+ than the size of the input */
+ if (save)
+ buff[size] = 0;
+
+ for (i = 0; i < size; i++) {
+
+ if (NULL == var) {
+
+ /*
+ * Check for comments, comment ok only on
+ * mostly empty lines
+ */
+ if (buff[i] == '#')
+ comment_start = 1;
+
+ if (comment_start) {
+ if ((buff[i] == '\r') ||
+ (buff[i] == '\n')) {
+ comment_start = 0;
+ }
+ } else {
+ if (!((buff[i] == ' ') ||
+ (buff[i] == '\t') ||
+ (buff[i] == '\r') ||
+ (buff[i] == '\n'))) {
+ /*
+ * Normal whitespace before the
+ * variable
+ */
+ var = &buff[i];
+ }
+ }
+
+ } else if (((NULL == var_end) || (NULL == val)) &&
+ ((buff[i] == '\r') || (buff[i] == '\n'))) {
+
+ /* This is the case when a variable
+ is unset. */
+
+ if (save) {
+ /* Set the var end to null so the
+ normal string routines will work
+
+ WARNING : This changes the input */
+ buff[i] = '\0';
+
+ save_env(ptn, var, val);
+
+ if (debug)
+ printf("Unsetting %s\n", var);
+ }
+
+ /* Clear the variable so state is parse is back
+ to initial. */
+ var = NULL;
+ var_end = NULL;
+ sets++;
+ } else if (NULL == var_end) {
+ if ((buff[i] == ' ') ||
+ (buff[i] == '\t'))
+ var_end = &buff[i];
+ } else if (NULL == val) {
+ if (!((buff[i] == ' ') ||
+ (buff[i] == '\t')))
+ val = &buff[i];
+ } else if (NULL == val_end) {
+ if ((buff[i] == '\r') ||
+ (buff[i] == '\n')) {
+ /* look for escaped cr or ln */
+ if ('\\' == buff[i - 1]) {
+ /* check for dos */
+ if ((buff[i] == '\r') &&
+ (buff[i+1] == '\n'))
+ buff[i + 1] = ' ';
+ buff[i - 1] = buff[i] = ' ';
+ } else {
+ val_end = &buff[i];
+ }
+ }
+ } else {
+ sprintf(err_string, "Internal Error");
+
+ if (debug)
+ printf("Internal error at %s %d\n",
+ __FILE__, __LINE__);
+ return 1;
+ }
+ /* Check if a var / val pair is ready */
+ if (NULL != val_end) {
+ if (save) {
+ /* Set the end's with nulls so
+ normal string routines will
+ work.
+
+ WARNING : This changes the input */
+ *var_end = '\0';
+ *val_end = '\0';
+
+ save_env(ptn, var, val);
+
+ if (debug)
+ printf("Setting %s %s\n", var, val);
+ }
+
+ /* Clear the variable so state is parse is back
+ to initial. */
+ var = NULL;
+ var_end = NULL;
+ val = NULL;
+ val_end = NULL;
+
+ sets++;
+ }
+ }
+
+ /* Corner case
+ Check for the case that no newline at end of the input */
+ if ((NULL != var) &&
+ (NULL == val_end)) {
+ if (save) {
+ /* case of val / val pair */
+ if (var_end)
+ *var_end = '\0';
+ /* else case handled by setting 0 past
+ the end of buffer.
+ Similar for val_end being null */
+ save_env(ptn, var, val);
+
+ if (debug) {
+ if (var_end)
+ printf("Trailing Setting %s %s\n", var, val);
+ else
+ printf("Trailing Unsetting %s\n", var);
+ }
+ }
+ sets++;
+ }
+ /* Did we set anything ? */
+ if (0 == sets)
+ sprintf(err_string, "No variables set");
+ else
+ ret = 0;
+
+ return ret;
+}
+
+static int saveenv_to_ptn(struct fastboot_ptentry *ptn, char *err_string)
+{
+ int ret = 1;
+ int save = 0;
+ int debug = 0;
+
+ /* err_string is only 32 bytes
+ Initialize with a generic error message. */
+ sprintf(err_string, "%s", "Unknown Error");
+
+ /* Parse the input twice.
+ Only save to the enviroment if the entire input if correct */
+ save = 0;
+ if (0 == parse_env(ptn, err_string, save, debug)) {
+ save = 1;
+ ret = parse_env(ptn, err_string, save, debug);
+ }
+ return ret;
+}
+
+static int get_block_size(void);
+#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
+static void process_flash_sf(const char *cmdbuf)
+{
+ 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");
+ } else if ((download_bytes > ptn->length * blksz)) {
+ fastboot_fail("image too large for partition");
+ /* 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");
+ 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");
+ return;
+ }
+ /* Write image */
+ sprintf(sf_command, "sf write 0x%x 0x%x 0x%x",
+ (unsigned int)(ulong)interface.transfer_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");
+ return;
+ }
+ printf("sf write finished '%s'\n", ptn->name);
+ fastboot_okay("");
+ }
+ } else {
+ fastboot_fail("no image downloaded");
+ }
+}
+
+#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;
+}
+
+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
+#endif /* CONFIG_FLASH_MCUFIRMWARE_SUPPORT */
+
+#if defined(CONFIG_FASTBOOT_STORAGE_SATA)
+static void process_flash_sata(const char *cmdbuf)
+{
+ 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");
+ } 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");
+ } else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV) {
+ /* Since the response can only be 64 bytes,
+ there is no point in having a large error message. */
+ char err_string[32];
+ if (saveenv_to_ptn(ptn, &err_string[0])) {
+ printf("savenv '%s' failed : %s\n", ptn->name, err_string);
+ fastboot_fail(err_string);
+ } else {
+ printf("partition '%s' saveenv-ed\n", ptn->name);
+ fastboot_okay("");
+ }
+ } else {
+ unsigned int temp;
+ char sata_write[128];
+
+ /* block count */
+ temp = (download_bytes +
+ MMC_SATA_BLOCK_SIZE - 1) /
+ MMC_SATA_BLOCK_SIZE;
+
+ sprintf(sata_write, "sata write 0x%x 0x%x 0x%x",
+ (unsigned int)interface.transfer_buffer,
+ ptn->start,
+ temp);
+
+ if (run_command(sata_write, 0)) {
+ printf("Writing '%s' FAILED!\n",
+ ptn->name);
+ fastboot_fail("Write partition failed");
+ } else {
+ printf("Writing '%s' DONE!\n",
+ ptn->name);
+ fastboot_okay("");
+ }
+ }
+ } else {
+ fastboot_fail("no image downloaded");
+ }
+
+}
+#endif
+
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+static int is_raw_partition(struct fastboot_ptentry *ptn)
+{
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+ if (ptn && (!strncmp(ptn->name, FASTBOOT_PARTITION_BOOTLOADER,
+ strlen(FASTBOOT_PARTITION_BOOTLOADER)) ||
+ !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)) ||
+#ifdef CONFIG_FASTBOOT_LOCK
+ !strncmp(ptn->name, FASTBOOT_PARTITION_FBMISC,
+ strlen(FASTBOOT_PARTITION_FBMISC)) ||
+#endif
+ !strncmp(ptn->name, FASTBOOT_PARTITION_MISC,
+ strlen(FASTBOOT_PARTITION_MISC)))) {
+#else
+ if (ptn && (!strncmp(ptn->name, FASTBOOT_PARTITION_BOOTLOADER,
+ strlen(FASTBOOT_PARTITION_BOOTLOADER)) ||
+ !strncmp(ptn->name, FASTBOOT_PARTITION_BOOT,
+ strlen(FASTBOOT_PARTITION_BOOT)) ||
+#ifdef CONFIG_FASTBOOT_LOCK
+ !strncmp(ptn->name, FASTBOOT_PARTITION_FBMISC,
+ strlen(FASTBOOT_PARTITION_FBMISC)) ||
+#endif
+ !strncmp(ptn->name, FASTBOOT_PARTITION_MISC,
+ strlen(FASTBOOT_PARTITION_MISC)))) {
+#endif
+ printf("support sparse flash partition for %s\n", ptn->name);
+ return 1;
+ } else
+ return 0;
+}
+
+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;
+}
+
+/*judge wether the gpt image and bootloader image are overlay*/
+bool bootloader_gpt_overlay(void)
+{
+ return (g_ptable[PTN_GPT_INDEX].partition_id == g_ptable[PTN_BOOTLOADER_INDEX].partition_id &&
+ ANDROID_BOOTLOADER_OFFSET < ANDROID_GPT_END);
+}
+
+int write_backup_gpt(void)
+{
+ 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);
+
+ /* write backup get partition */
+ if (write_backup_gpt_partitions(dev_desc, interface.transfer_buffer)) {
+ printf("writing GPT image fail\n");
+ return -1;
+ }
+
+ printf("flash backup gpt image successfully\n");
+ return 0;
+}
+
+static void process_flash_mmc(const char *cmdbuf)
+{
+ if (download_bytes) {
+ struct fastboot_ptentry *ptn;
+#ifdef CONFIG_AVB_SUPPORT
+ if (!strcmp_l1(FASTBOOT_PARTITION_AVBKEY, cmdbuf)) {
+ printf("pubkey len %d\n", download_bytes);
+ if (avbkey_init(interface.transfer_buffer, download_bytes) != 0) {
+ fastboot_fail("fail to Write partition");
+ } else {
+ printf("init 'avbkey' DONE!\n");
+ fastboot_okay("OKAY");
+ }
+ return;
+ }
+#endif
+
+ /* Next is the partition name */
+ ptn = fastboot_flash_find_ptn(cmdbuf);
+ if (ptn == NULL) {
+ fastboot_fail("partition does not exist");
+ } 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");
+ } else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV) {
+ /* Since the response can only be 64 bytes,
+ there is no point in having a large error message. */
+ char err_string[32];
+ if (saveenv_to_ptn(ptn, &err_string[0])) {
+ printf("savenv '%s' failed : %s\n", ptn->name, err_string);
+ fastboot_fail(err_string);
+ } else {
+ printf("partition '%s' saveenv-ed\n", ptn->name);
+ fastboot_okay("");
+ }
+ } else {
+ unsigned int temp;
+
+ char mmc_dev[128];
+ char mmc_write[128];
+ int mmcret;
+
+ printf("writing to partition '%s'\n", ptn->name);
+
+ 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*/);
+
+ if (!is_raw_partition(ptn) &&
+ is_sparse_image(interface.transfer_buffer)) {
+ int mmc_no = 0;
+ struct mmc *mmc;
+ struct blk_desc *dev_desc;
+ disk_partition_t info;
+ struct sparse_storage sparse;
+
+ mmc_no = fastboot_devinfo.dev_id;
+
+ printf("sparse flash target is MMC:%d\n", mmc_no);
+ mmc = find_mmc_device(mmc_no);
+ if (mmc && 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;
+ }
+
+ 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;
+ printf("Flashing sparse image at offset " LBAFU "\n",
+ sparse.start);
+
+ sparse.priv = dev_desc;
+ write_sparse_image(&sparse, ptn->name, interface.transfer_buffer,
+ download_bytes);
+
+ } 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(mmc_write, "mmc write 0x%x 0x%x 0x%x",
+ (unsigned int)(uintptr_t)interface.transfer_buffer, /*source*/
+ ptn->start, /*dest*/
+ temp /*length*/);
+
+ printf("Initializing '%s'\n", ptn->name);
+
+ mmcret = run_command(mmc_dev, 0);
+ if (mmcret)
+ fastboot_fail("Init of MMC card failed");
+ else
+ fastboot_okay("");
+
+ printf("Writing '%s'\n", ptn->name);
+ if (run_command(mmc_write, 0)) {
+ printf("Writing '%s' FAILED!\n", ptn->name);
+ fastboot_fail("Write partition failed");
+ } else {
+ printf("Writing '%s' DONE!\n", ptn->name);
+ fastboot_okay("");
+ }
+ }
+ /* Write backup gpt image */
+ if (strncmp(ptn->name, "gpt", 3) == 0) {
+ if (write_backup_gpt())
+ fastboot_fail("write backup GPT image fail");
+ else
+ fastboot_okay("");
+
+ /* will force scan the device,
+ * so dev_desc can be re-inited
+ * with the latest data */
+ run_command(mmc_dev, 0);
+ }
+ }
+ }
+ } else {
+ fastboot_fail("no image downloaded");
+ }
+}
+
+#endif
+
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+static 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;
+ disk_partition_t info;
+
+ ptn = fastboot_flash_find_ptn(cmdbuf);
+ if ((ptn == NULL) || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) {
+ sprintf(response, "FAILpartition does not exist or uneraseable");
+ 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;
+}
+#endif
+
+#if defined(CONFIG_FASTBOOT_STORAGE_SATA)
+static void process_erase_sata(const char *cmdbuf, char *response)
+{
+ return;
+}
+#endif
+
+static void rx_process_erase(const char *cmdbuf, char *response)
+{
+ switch (fastboot_devinfo.type) {
+#if defined(CONFIG_FASTBOOT_STORAGE_SATA)
+ case DEV_SATA:
+ process_erase_sata(cmdbuf, response);
+ break;
+#endif
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ case DEV_MMC:
+ process_erase_mmc(cmdbuf, response);
+ break;
+#endif
+ default:
+ printf("Not support flash command for current device %d\n",
+ fastboot_devinfo.type);
+ sprintf(response,
+ "FAILfailed to flash device");
+ break;
+ }
+}
+
+static void rx_process_flash(const char *cmdbuf)
+{
+/* 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);
+ break;
+#ifdef CONFIG_ARCH_IMX8M
+ case DEV_MMC:
+ if (is_tcm_image(interface.transfer_buffer))
+ process_flash_mmc(cmdbuf);
+ break;
+#endif
+ default:
+ printf("Don't support flash firmware\n");
+ }
+ return;
+ }
+#endif
+ /* Normal case */
+ switch (fastboot_devinfo.type) {
+#if defined(CONFIG_FASTBOOT_STORAGE_SATA)
+ case DEV_SATA:
+ process_flash_sata(cmdbuf);
+ break;
+#endif
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ case DEV_MMC:
+ process_flash_mmc(cmdbuf);
+ break;
+#endif
+ default:
+ printf("Not support flash command for current device %d\n",
+ fastboot_devinfo.type);
+ fastboot_fail("failed to flash device");
+ break;
+ }
+}
+
+
+static void parameters_setup(void)
+{
+ interface.nand_block_size = 0;
+ interface.transfer_buffer =
+ (unsigned char *)CONFIG_FASTBOOT_BUF_ADDR;
+ interface.transfer_buffer_size =
+ CONFIG_FASTBOOT_BUF_SIZE;
+}
+
+static int _fastboot_setup_dev(void)
+{
+ char *fastboot_env;
+ fastboot_env = env_get("fastboot_dev");
+
+ if (fastboot_env) {
+ if (!strcmp(fastboot_env, "sata")) {
+ fastboot_devinfo.type = DEV_SATA;
+ fastboot_devinfo.dev_id = 0;
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ } else if (!strncmp(fastboot_env, "mmc", 3)) {
+ fastboot_devinfo.type = DEV_MMC;
+ fastboot_devinfo.dev_id = mmc_get_env_dev();
+#endif
+ }
+ } 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
+
+ return 0;
+}
+
+#if defined(CONFIG_FASTBOOT_STORAGE_SATA) \
+ || defined(CONFIG_FASTBOOT_STORAGE_MMC)
+/**
+ @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)
+{
+ disk_partition_t 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_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;
+#ifdef CONFIG_CMD_SATA
+ int sata_device_no;
+#endif
+
+ /* 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_CMD_SATA
+ puts("flash target is SATA\n");
+ if (sata_initialize())
+ return -1;
+ sata_device_no = CONFIG_FASTBOOT_SATA_NO;
+ 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_CMD_SATA*/
+ puts("SATA isn't buildin\n");
+ return -1;
+#endif /*! CONFIG_CMD_SATA*/
+ } else if (fastboot_devinfo.type == DEV_MMC) {
+ int mmc_no = 0;
+ mmc_no = fastboot_devinfo.dev_id;
+
+ printf("flash target is MMC:%d\n", mmc_no);
+ mmc = find_mmc_device(mmc_no);
+ if (mmc && 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");
+
+ /* 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
+
+ /* Bootloader */
+ strcpy(ptable[PTN_BOOTLOADER_INDEX].name, FASTBOOT_PARTITION_BOOTLOADER);
+ ptable[PTN_BOOTLOADER_INDEX].start =
+ ANDROID_BOOTLOADER_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;
+}
+#endif /*CONFIG_FASTBOOT_STORAGE_SATA || CONFIG_FASTBOOT_STORAGE_MMC*/
+
+static void _fastboot_load_partitions(void)
+{
+ g_pcount = 0;
+#if defined(CONFIG_FASTBOOT_STORAGE_SATA) \
+ || defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ _fastboot_parts_load_from_ptable();
+#endif
+}
+
+/*
+ * 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;
+ }
+ }
+
+ printf("can't find partition: %s, dump the partition table\n", name);
+ fastboot_flash_dump_ptn();
+ 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);
+ 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;
+}
+
+#ifdef CONFIG_FSL_FASTBOOT
+void board_fastboot_setup(void)
+{
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ static char boot_dev_part[32];
+ u32 dev_no;
+#endif
+ switch (get_boot_device()) {
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ 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;
+#endif /*CONFIG_FASTBOOT_STORAGE_MMC*/
+ default:
+ 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");
+ }
+}
+
+#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
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ static char boot_dev_part[32];
+ u32 dev_no;
+#endif
+ int bootdev = get_boot_device();
+ switch (bootdev) {
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ 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;
+#endif /*CONFIG_FASTBOOT_STORAGE_MMC*/
+ 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", "run bootcmd_android_recovery");
+}
+#endif /*CONFIG_ANDROID_RECOVERY*/
+#endif /*CONFIG_FSL_FASTBOOT*/
+
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
+static 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
+static AvbAtxOps fsl_avb_atx_ops = {
+ .ops = NULL,
+ .read_permanent_attributes = fsl_read_permanent_attributes,
+ .read_permanent_attributes_hash = fsl_read_permanent_attributes_hash
+};
+#endif
+static 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
+
+void fastboot_setup(void)
+{
+#ifdef CONFIG_USB_GADGET
+ struct tag_serialnr serialnr;
+ char serial[17];
+
+ get_board_serial(&serialnr);
+ sprintf(serial, "%08x%08x", serialnr.high, serialnr.low);
+ g_dnl_set_serialnumber(serial);
+#endif
+ /*execute board relevant initilizations for preparing fastboot */
+ board_fastboot_setup();
+
+ /*get the fastboot dev*/
+ _fastboot_setup_dev();
+
+
+ /*load partitions information for the fastboot dev*/
+ _fastboot_load_partitions();
+
+ parameters_setup();
+#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
+}
+
+/* Write the bcb with fastboot bootloader commands */
+static void enable_fastboot_command(void)
+{
+ char fastboot_command[32] = {0};
+ strncpy(fastboot_command, FASTBOOT_BCB_CMD, 31);
+ bcb_write_command(fastboot_command);
+}
+
+/* Get the Boot mode from BCB cmd or Key pressed */
+static FbBootMode fastboot_get_bootmode(void)
+{
+ int ret = 0;
+ int boot_mode = BOOTMODE_NORMAL;
+ char command[32];
+#ifdef CONFIG_ANDROID_RECOVERY
+ if(is_recovery_key_pressing()) {
+ boot_mode = BOOTMODE_RECOVERY_KEY_PRESSED;
+ return boot_mode;
+ }
+#endif
+ 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);
+ return boot_mode;
+}
+
+#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;
+ 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;
+ }
+ struct fastboot_ptentry *ptentry = fastboot_flash_find_ptn(system_part_name);
+ if(ptentry != NULL) {
+ char bootargs_3rd[ANDR_BOOT_ARGS_SIZE];
+#if defined(CONFIG_FASTBOOT_STORAGE_MMC)
+ 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);
+#endif
+ }
+}
+#endif
+/* 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;
+ }
+}
+
+#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
+}
+
+static struct andr_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN);
+
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
+
+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;
+
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+ size_t lz4_len = DST_DECOMPRESS_LEN;
+#endif
+ AvbABFlowResult avb_result;
+ AvbSlotVerifyData *avb_out_data;
+ AvbPartitionData *avb_loadpart;
+
+ /* get bootmode, default to boot "boot" */
+ if (argc > 1) {
+ is_recovery_mode =
+ (strncmp(argv[1], "recovery", sizeof("recovery")) != 0) ? false: true;
+ }
+
+#ifdef CONFIG_FASTBOOT_LOCK
+ /* check lock state */
+ FbLockState 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);
+ lock_status = FASTBOOT_LOCK;
+ }
+ bool allow_fail = (lock_status == FASTBOOT_UNLOCK ? true : false);
+ avb_metric = get_timer(0);
+ /* 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 */
+ const char *requested_partitions[] = {"boot", 0};
+ avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
+#else /* CONFIG_ANDROID_AB_SUPPORT */
+ if (!is_recovery_mode) {
+ const char *requested_partitions[] = {"boot", 0};
+ avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
+ AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+ } else {
+ const char *requested_partitions[] = {"recovery", 0};
+ avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
+ AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+ }
+#endif /* CONFIG_ANDROID_AB_SUPPORT */
+ /* 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);
+ /* load the first partition */
+ avb_loadpart = avb_out_data->loaded_partitions;
+ 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_ARGS_SIZE];
+ if (lock_status == FASTBOOT_LOCK) {
+ sprintf(bootargs_sec,
+ "androidboot.verifiedbootstate=green androidboot.slot_suffix=%s %s",
+ avb_out_data->ab_suffix, avb_out_data->cmdline);
+ } else {
+ sprintf(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
+ 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 if (lock_status == FASTBOOT_LOCK) { /* && verify fail */
+ /* if in lock state, verify enforce fail */
+ printf(" verify FAIL, state: LOCK\n");
+ goto fail;
+ } else { /* lock_status == FASTBOOT_UNLOCK && get unacceptable verify fail */
+ /* if in unlock state, log the verify state */
+ printf(" verify FAIL, state: UNLOCK\n");
+#endif
+ /* if lock/unlock not enabled or verify fail
+ * in unlock state, will try boot */
+ size_t num_read;
+ hdr = &boothdr;
+
+ char bootimg[10];
+ /* we don't have a/b slot for imx6 on normal Android*/
+#ifndef CONFIG_ANDROID_AB_SUPPORT
+ char *slot = "";
+ if (!is_recovery_mode) {
+ sprintf(bootimg, "boot");
+ } else {
+ sprintf(bootimg, "recovery");
+ }
+ printf("boot '%s' still\n", bootimg);
+#else
+ char *slot = select_slot(&fsl_avb_ab_ops);
+ if (slot == NULL) {
+ printf("boota: no bootable slot\n");
+ goto fail;
+ }
+ sprintf(bootimg, "boot%s", slot);
+ printf(" boot '%s' still\n", bootimg);
+#endif
+ /* maybe we should use bootctl to select a/b
+ * but libavb doesn't export a/b select */
+ if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
+ 0, sizeof(boothdr), hdr, &num_read) != AVB_IO_RESULT_OK &&
+ num_read != sizeof(boothdr)) {
+ printf("boota: read bootimage head error\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;
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+ boot_buf = malloc(image_size);
+ /* Load boot image */
+ if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
+ 0, image_size, boot_buf, &num_read) != AVB_IO_RESULT_OK
+ && num_read != image_size) {
+ printf("boota: read boot image error\n");
+ goto fail;
+ }
+ /* 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)boot_buf + hdr->page_size))) {
+ memcpy((void *)(ulong)hdr->kernel_addr,
+ (void *)((ulong)boot_buf + hdr->page_size), hdr->kernel_size);
+ } else {
+#ifdef CONFIG_LZ4
+ if (ulz4fn((void *)((ulong)boot_buf + 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 */
+ }
+ hdr = (struct andr_img_hdr *)boot_buf;
+#else /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+ if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
+ 0, image_size, (void *)(ulong)(hdr->kernel_addr - hdr->page_size), &num_read) != AVB_IO_RESULT_OK
+ && num_read != image_size) {
+ printf("boota: read boot image error\n");
+ goto fail;
+ }
+ hdr = (struct andr_img_hdr *)(ulong)(hdr->kernel_addr - hdr->page_size);
+#endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+ char bootargs_sec[ANDR_BOOT_ARGS_SIZE];
+ sprintf(bootargs_sec,
+ "androidboot.verifiedbootstate=orange androidboot.slot_suffix=%s", slot);
+ env_set("bootargs_sec", bootargs_sec);
+#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+ if(!is_recovery_mode)
+ fastboot_setup_system_boot_args(slot, true);
+#endif /* CONFIG_SYSTEM_RAMDISK_SUPPORT */
+#ifdef CONFIG_FASTBOOT_LOCK
+ }
+#endif
+
+ flush_cache((ulong)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 */
+ 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 (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
+ 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);
+ if (boot_buf != NULL)
+ free(boot_buf);
+
+ 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;
+ disk_partition_t info;
+ struct blk_desc *dev_desc = NULL;
+ unsigned bootimg_sectors;
+
+ memset((void *)&info, 0 , sizeof(disk_partition_t));
+ /* 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);
+ 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);
+#ifdef CONFIG_FASTBOOT_LOCK
+ int verifyresult = -1;
+#endif
+
+#ifdef 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
+ /* load the dtb file */
+ if (hdr->second_size && hdr->second_addr) {
+ memcpy((void *)hdr->second_addr, (void *)hdr->kernel_addr
+ + ALIGN(hdr->kernel_size, hdr->page_size)
+ + ALIGN(hdr->ramdisk_size, hdr->page_size), hdr->second_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 (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 ) {
+ 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 */
+#endif
+
void fastboot_fail(const char *reason)
{
strncpy(fb_response_str, "FAIL\0", 5);
@@ -165,6 +2210,24 @@ void fastboot_okay(const char *reason)
strncat(fb_response_str, reason, FASTBOOT_RESPONSE_LEN - 4 - 1);
}
+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;
@@ -226,6 +2289,7 @@ static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f)
static void fastboot_disable(struct usb_function *f)
{
+ usb_req *req;
struct f_fastboot *f_fb = func_to_fastboot(f);
usb_ep_disable(f_fb->out_ep);
@@ -239,6 +2303,17 @@ static void fastboot_disable(struct usb_function *f)
if (f_fb->in_req) {
free(f_fb->in_req->buf);
usb_ep_free_request(f_fb->in_ep, f_fb->in_req);
+
+ /* disable usb request FIFO */
+ while(f_fb->front != NULL) {
+ req = f_fb->front;
+ f_fb->front = f_fb->front->next;
+ free(req->in_req->buf);
+ usb_ep_free_request(f_fb->in_ep, req->in_req);
+ free(req);
+ }
+
+ f_fb->rear = NULL;
f_fb->in_req = NULL;
}
}
@@ -302,8 +2377,19 @@ static int fastboot_set_alt(struct usb_function *f,
ret = -EINVAL;
goto err;
}
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+ /*
+ * fastboot host end implement to get data in one bulk package so need
+ * large buffer for the "fastboot upload" and "fastboot get_staged".
+ */
+ if (f_fb->in_req->buf)
+ free(f_fb->in_req->buf);
+ f_fb->in_req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE * 32);
+#endif
f_fb->in_req->complete = fastboot_complete;
+ f_fb->front = f_fb->rear = NULL;
+
ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0);
if (ret)
goto err;
@@ -340,13 +2426,56 @@ static int fastboot_add(struct usb_configuration *c)
status = usb_add_function(c, &f_fb->usb_function);
if (status) {
free(f_fb);
- fastboot_func = f_fb;
+ fastboot_func = NULL;
}
return status;
}
DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
+static 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;
+}
+
static int fastboot_tx_write(const char *buffer, unsigned int buffer_size)
{
struct usb_request *in_req = fastboot_func->in_req;
@@ -398,6 +2527,608 @@ static int strcmp_l1(const char *s1, const char *s2)
return strncmp(s1, s2, strlen(s1));
}
+#ifdef CONFIG_FSL_FASTBOOT
+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
+
+static int get_block_size(void) {
+ int mmc_no = 0;
+ struct blk_desc *dev_desc;
+ mmc_no = fastboot_devinfo.dev_id;
+ dev_desc = blk_get_dev("mmc", mmc_no);
+ if (NULL == dev_desc) {
+ printf("** Block device MMC %d not supported\n",
+ mmc_no);
+ return 0;
+ }
+ return dev_desc->blksz;
+}
+
+static bool is_exist(char (*partition_base_name)[16], 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"*/
+static int get_partition_base_name(char (*partition_base_name)[16])
+{
+ int n = 0;
+ int count = 0;
+ char *ptr1, *ptr2;
+ char buffer[16];
+
+ 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;
+}
+
+static bool 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;
+}
+
+static int get_single_var(char *cmd, char *response)
+{
+ char *str = cmd;
+ size_t 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);
+ return -1;
+ } else {
+ snprintf(response + strlen(response), chars_left, "0x%x", 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);
+ 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);
+ 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_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
+ }
+ else {
+ char envstr[32];
+
+ snprintf(envstr, sizeof(envstr) - 1, "fastboot.%s", cmd);
+ s = env_get(envstr);
+ if (s) {
+ strncat(response, s, chars_left);
+ } else {
+ sprintf(response,"FAILunknow variable:%s",cmd);
+ printf("WARNING: unknown variable: %s\n", cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
+{
+ int n = 0;
+ int status = 0;
+ int count = 0;
+ char *cmd = req->buf;
+ char var_name[FASTBOOT_RESPONSE_LEN - 1];
+ char partition_base_name[MAX_PTN][16];
+ char slot_suffix[2][5] = {"a","b"};
+ char response[FASTBOOT_RESPONSE_LEN - 1];
+
+ strsep(&cmd, ":");
+ if (!cmd) {
+ pr_err("missing variable");
+ fastboot_tx_write_str("FAILmissing var");
+ return;
+ }
+
+ if (!strcmp_l1("all", cmd)) {
+
+ memset(response, '\0', FASTBOOT_RESPONSE_LEN - 1);
+
+
+ /* get common variables */
+ for (n = 0; n < FASTBOOT_COMMON_VAR_NUM; n++) {
+ snprintf(response, sizeof(response), "INFO%s:", fastboot_common_var[n]);
+ get_single_var(fastboot_common_var[n], response);
+ fastboot_tx_write_more(response);
+ }
+
+ /* get partition type */
+ for (n = 0; n < g_pcount; n++) {
+ snprintf(response, sizeof(response), "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, sizeof(response), "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 (is_slot()) {
+ /* get has-slot variables */
+ count = get_partition_base_name(partition_base_name);
+ for (n = 0; n < count; n++) {
+ snprintf(response, sizeof(response), "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:", sizeof(response));
+ get_single_var("current-slot", response);
+ fastboot_tx_write_more(response);
+ /* get slot count */
+ strncpy(response, "INFOslot-count:", sizeof(response));
+ get_single_var("slot-count", response);
+ fastboot_tx_write_more(response);
+ /* get slot-successful variable */
+ for (n = 0; n < 2; n++) {
+ snprintf(response, sizeof(response), "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, sizeof(response), "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, sizeof(response), "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);
+
+ return;
+ } else {
+
+ strncpy(response, "OKAY", 5);
+ status = get_single_var(cmd, response);
+ if (status != 0) {
+ strncpy(response, "FAIL", 5);
+ }
+ fastboot_tx_write_str(response);
+ return;
+ }
+}
+
+#ifdef 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");
+
+static FbLockState do_fastboot_unlock(bool force)
+{
+ int status;
+ if (force)
+ set_fastboot_lock_disable();
+ if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) {
+ printf("It is able to unlock device. %d\n",fastboot_lock_enable());
+ if (fastboot_get_lock_stat() == FASTBOOT_UNLOCK) {
+ printf("The device is already unlocked\n");
+ return FASTBOOT_UNLOCK;
+ }
+ status = fastboot_set_lock_stat(FASTBOOT_UNLOCK);
+ if (status < 0)
+ return FASTBOOT_LOCK_ERROR;
+
+ printf("Start /data wipe process....\n");
+ fastboot_wipe_data_partition();
+ printf("Wipe /data completed.\n");
+
+#ifdef CONFIG_AVB_SUPPORT
+ printf("Start stored_rollback_index wipe process....\n");
+ rbkidx_erase();
+ printf("Wipe stored_rollback_index completed.\n");
+#endif
+ } 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;
+
+ printf("Start /data wipe process....\n");
+ fastboot_wipe_data_partition();
+ printf("Wipe /data completed.\n");
+
+ return FASTBOOT_LOCK;
+}
+
+static void cb_flashing(struct usb_ep *ep, struct usb_request *req)
+{
+ char *cmd = req->buf;
+ char response[FASTBOOT_RESPONSE_LEN];
+ unsigned char len = strlen(cmd);
+ FbLockState status;
+ FbLockEnableResult result;
+
+#ifdef CONFIG_ANDROID_THINGS_SUPPORT
+ if (!strncmp(cmd + len - strlen(FASTBOOT_BOOTLOADER_VBOOT_KEY),
+ FASTBOOT_BOOTLOADER_VBOOT_KEY,
+ strlen(FASTBOOT_BOOTLOADER_VBOOT_KEY))) {
+ strcpy(response, "OKAY");
+ } else if (!strncmp(cmd + len - strlen("unlock_critical"),
+ "unlock_critical", strlen("unlock_critical"))) {
+#else
+ if (!strncmp(cmd + len - strlen("unlock_critical"),
+ "unlock_critical", strlen("unlock_critical"))) {
+#endif
+ strcpy(response, "OKAY");
+ } else if (!strncmp(cmd + len - strlen("lock_critical"),
+ "lock_critical", strlen("lock_critical"))) {
+ strcpy(response, "OKAY");
+ } else if (!strncmp(cmd + len - strlen("unlock"),
+ "unlock", strlen("unlock"))) {
+ printf("flashing unlock.\n");
+ status = do_fastboot_unlock(false);
+ if (status != FASTBOOT_LOCK_ERROR)
+ strcpy(response, "OKAY");
+ else
+ strcpy(response, "FAIL unlock device failed.");
+ } else if (!strncmp(cmd + len - strlen("lock"), "lock", strlen("lock"))) {
+ printf("flashing lock.\n");
+ status = do_fastboot_lock();
+ if (status != FASTBOOT_LOCK_ERROR)
+ strcpy(response, "OKAY");
+ else
+ strcpy(response, "FAIL lock device failed.");
+ } else if (!strncmp(cmd + len - strlen("get_unlock_ability"),
+ "get_unlock_ability", strlen("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, "FAIL get unlock ability failed.");
+ }
+ } else {
+ printf("Unknown flashing command:%s\n", cmd);
+ strcpy(response, "FAIL command not defined");
+ }
+ fastboot_tx_write_more(response);
+}
+
+static int partition_table_valid(void)
+{
+ int status, mmc_no;
+ struct blk_desc *dev_desc;
+ disk_partition_t 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);
+}
+
+#endif /* CONFIG_FASTBOOT_LOCK */
+
+#ifdef CONFIG_FASTBOOT_FLASH
+static void cb_flash(struct usb_ep *ep, struct usb_request *req)
+{
+ char *cmd = req->buf;
+ char response[FASTBOOT_RESPONSE_LEN];
+
+ strsep(&cmd, ":");
+ if (!cmd) {
+ pr_err("missing partition name");
+ fastboot_tx_write_str("FAILmissing partition name");
+ return;
+ }
+
+ /* initialize the response buffer */
+ fb_response_str = response;
+
+#ifdef CONFIG_FASTBOOT_LOCK
+ int status;
+ status = fastboot_get_lock_stat();
+
+ if (status == FASTBOOT_LOCK) {
+ pr_err("device is LOCKed!\n");
+ strcpy(response, "FAIL device is locked.");
+ fastboot_tx_write_str(response);
+ return;
+
+ } else if (status == FASTBOOT_LOCK_ERROR) {
+ pr_err("write lock status into device!\n");
+ fastboot_set_lock_stat(FASTBOOT_LOCK);
+ strcpy(response, "FAIL device is locked.");
+ fastboot_tx_write_str(response);
+ return;
+ }
+#endif
+ fastboot_fail("no flash device defined");
+
+#ifdef CONFIG_FASTBOOT_LOCK
+ int gpt_valid_pre = 0;
+ int gpt_valid_pst = 0;
+ if (strncmp(cmd, "gpt", 3) == 0)
+ gpt_valid_pre = partition_table_valid();
+#endif
+ rx_process_flash(cmd);
+#ifdef CONFIG_FASTBOOT_LOCK
+ if (strncmp(cmd, "gpt", 3) == 0) {
+ gpt_valid_pst = 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_pst)
+ _fastboot_load_partitions();
+ /* If gpt invalid -> valid, write unlock status, also wipe data. */
+ if ((gpt_valid_pre == 0) && (gpt_valid_pst == 1))
+ do_fastboot_unlock(true);
+ }
+
+#endif
+ fastboot_tx_write_str(response);
+}
+#endif
+
+#ifdef CONFIG_FASTBOOT_FLASH
+static void cb_erase(struct usb_ep *ep, struct usb_request *req)
+{
+ char *cmd = req->buf;
+ char response[FASTBOOT_RESPONSE_LEN];
+
+ strsep(&cmd, ":");
+ if (!cmd) {
+ pr_err("missing partition name");
+ fastboot_tx_write_str("FAILmissing partition name");
+ return;
+ }
+
+ /* initialize the response buffer */
+ fb_response_str = response;
+
+#ifdef CONFIG_FASTBOOT_LOCK
+ FbLockState status;
+ status = fastboot_get_lock_stat();
+ if (status == FASTBOOT_LOCK) {
+ pr_err("device is LOCKed!\n");
+ strcpy(response, "FAIL device is locked.");
+ fastboot_tx_write_str(response);
+ return;
+ } else if (status == FASTBOOT_LOCK_ERROR) {
+ pr_err("write lock status into device!\n");
+ fastboot_set_lock_stat(FASTBOOT_LOCK);
+ strcpy(response, "FAIL device is locked.");
+ fastboot_tx_write_str(response);
+ return;
+ }
+#endif
+ rx_process_erase(cmd, response);
+ fastboot_tx_write_str(response);
+}
+#endif
+
+#ifdef CONFIG_AVB_SUPPORT
+static void cb_set_active_avb(struct usb_ep *ep, struct usb_request *req)
+{
+ AvbIOResult ret;
+ int slot = 0;
+ char *cmd = req->buf;
+
+ strsep(&cmd, ":");
+ if (!cmd) {
+ pr_err("missing slot suffix\n");
+ fastboot_tx_write_str("FAILmissing slot suffix");
+ return;
+ }
+
+ slot = slotidx_from_suffix(cmd);
+
+ if (slot < 0) {
+ fastboot_tx_write_str("FAILerr slot suffix");
+ return;
+ }
+
+ ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot);
+ if (ret != AVB_IO_RESULT_OK)
+ fastboot_tx_write_str("avb IO error");
+ else
+ fastboot_tx_write_str("OKAY");
+
+ return;
+}
+#endif /*CONFIG_AVB_SUPPORT*/
+
+static void cb_reboot_bootloader(struct usb_ep *ep, struct usb_request *req)
+{
+ fastboot_tx_write_str("OKAY");
+
+ udelay(1000000);
+ enable_fastboot_command();
+ do_reset(NULL, 0, 0, NULL);
+}
+
+#else /* CONFIG_FSL_FASTBOOT */
+
static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
{
char *cmd = req->buf;
@@ -454,6 +3185,87 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
fastboot_tx_write_str(response);
}
+#ifdef CONFIG_FASTBOOT_FLASH
+static void cb_flash(struct usb_ep *ep, struct usb_request *req)
+{
+ char *cmd = req->buf;
+ char response[FASTBOOT_RESPONSE_LEN];
+
+ strsep(&cmd, ":");
+ if (!cmd) {
+ pr_err("missing partition name");
+ fastboot_tx_write_str("FAILmissing partition name");
+ return;
+ }
+
+ /* initialize the response buffer */
+ fb_response_str = response;
+
+ fastboot_fail("no flash device defined");
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+ fb_mmc_flash_write(cmd, (void *)CONFIG_FASTBOOT_BUF_ADDR,
+ download_bytes);
+#endif
+#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
+ fb_nand_flash_write(cmd,
+ (void *)CONFIG_FASTBOOT_BUF_ADDR,
+ download_bytes);
+#endif
+ fastboot_tx_write_str(response);
+}
+#endif
+
+static void cb_oem(struct usb_ep *ep, struct usb_request *req)
+{
+ char *cmd = req->buf;
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+ if (strncmp("format", cmd + 4, 6) == 0) {
+ char cmdbuf[32];
+ sprintf(cmdbuf, "gpt write mmc %x $partitions",
+ CONFIG_FASTBOOT_FLASH_MMC_DEV);
+ if (run_command(cmdbuf, 0))
+ fastboot_tx_write_str("FAIL");
+ else
+ fastboot_tx_write_str("OKAY");
+ } else
+#endif
+ if (strncmp("unlock", cmd + 4, 8) == 0) {
+ fastboot_tx_write_str("FAILnot implemented");
+ }
+ else {
+ fastboot_tx_write_str("FAILunknown oem command");
+ }
+}
+
+#ifdef CONFIG_FASTBOOT_FLASH
+static void cb_erase(struct usb_ep *ep, struct usb_request *req)
+{
+ char *cmd = req->buf;
+ char response[FASTBOOT_RESPONSE_LEN];
+
+ strsep(&cmd, ":");
+ if (!cmd) {
+ pr_err("missing partition name");
+ fastboot_tx_write_str("FAILmissing partition name");
+ return;
+ }
+
+ /* initialize the response buffer */
+ fb_response_str = response;
+
+ fastboot_fail("no flash device defined");
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+ fb_mmc_erase(cmd);
+#endif
+#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
+ fb_nand_erase(cmd);
+#endif
+ fastboot_tx_write_str(response);
+}
+#endif
+
+#endif /* CONFIG_FSL_FASTBOOT*/
+
static unsigned int rx_bytes_expected(struct usb_ep *ep)
{
int rx_remain = download_size - download_bytes;
@@ -530,6 +3342,26 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
usb_ep_queue(ep, req, 0);
}
+static void cb_upload(struct usb_ep *ep, struct usb_request *req)
+{
+ char response[FASTBOOT_RESPONSE_LEN];
+
+ if (!download_bytes || download_bytes > (EP_BUFFER_SIZE * 32)) {
+ sprintf(response, "FAIL");
+ fastboot_tx_write_str(response);
+ return;
+ }
+
+ printf("Will upload %d bytes.\n", download_bytes);
+ snprintf(response, FASTBOOT_RESPONSE_LEN, "DATA%08x", download_bytes);
+ fastboot_tx_write_more(response);
+
+ fastboot_tx_write((const char *)(interface.transfer_buffer), download_bytes);
+
+ snprintf(response,FASTBOOT_RESPONSE_LEN, "OKAY");
+ fastboot_tx_write_more(response);
+}
+
static void cb_download(struct usb_ep *ep, struct usb_request *req)
{
char *cmd = req->buf;
@@ -557,11 +3389,16 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req)
static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
{
char boot_addr_start[12];
+#ifdef CONFIG_FSL_FASTBOOT
+ char *bootm_args[] = { "boota", boot_addr_start, NULL };
+ sprintf(boot_addr_start, "0x%lx", load_addr);
+#else
char *bootm_args[] = { "bootm", boot_addr_start, NULL };
+ sprintf(boot_addr_start, "0x%lx", (long)CONFIG_FASTBOOT_BUF_ADDR);
+#endif
puts("Booting kernel..\n");
- sprintf(boot_addr_start, "0x%lx", (long)CONFIG_FASTBOOT_BUF_ADDR);
do_bootm(NULL, 0, 2, bootm_args);
/* This only happens if image is somehow faulty so we start over */
@@ -585,91 +3422,38 @@ static void cb_continue(struct usb_ep *ep, struct usb_request *req)
fastboot_tx_write_str("OKAY");
}
-#ifdef CONFIG_FASTBOOT_FLASH
-static void cb_flash(struct usb_ep *ep, struct usb_request *req)
-{
- char *cmd = req->buf;
- char response[FASTBOOT_RESPONSE_LEN];
-
- strsep(&cmd, ":");
- if (!cmd) {
- pr_err("missing partition name");
- fastboot_tx_write_str("FAILmissing partition name");
- return;
- }
-
- /* initialize the response buffer */
- fb_response_str = response;
-
- fastboot_fail("no flash device defined");
-#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
- fb_mmc_flash_write(cmd, (void *)CONFIG_FASTBOOT_BUF_ADDR,
- download_bytes);
-#endif
-#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
- fb_nand_flash_write(cmd,
- (void *)CONFIG_FASTBOOT_BUF_ADDR,
- download_bytes);
-#endif
- fastboot_tx_write_str(response);
-}
-#endif
-
-static void cb_oem(struct usb_ep *ep, struct usb_request *req)
-{
- char *cmd = req->buf;
-#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
- if (strncmp("format", cmd + 4, 6) == 0) {
- char cmdbuf[32];
- sprintf(cmdbuf, "gpt write mmc %x $partitions",
- CONFIG_FASTBOOT_FLASH_MMC_DEV);
- if (run_command(cmdbuf, 0))
- fastboot_tx_write_str("FAIL");
- else
- fastboot_tx_write_str("OKAY");
- } else
-#endif
- if (strncmp("unlock", cmd + 4, 8) == 0) {
- fastboot_tx_write_str("FAILnot implemented");
- }
- else {
- fastboot_tx_write_str("FAILunknown oem command");
- }
-}
-
-#ifdef CONFIG_FASTBOOT_FLASH
-static void cb_erase(struct usb_ep *ep, struct usb_request *req)
-{
- char *cmd = req->buf;
- char response[FASTBOOT_RESPONSE_LEN];
-
- strsep(&cmd, ":");
- if (!cmd) {
- pr_err("missing partition name");
- fastboot_tx_write_str("FAILmissing partition name");
- return;
- }
-
- /* initialize the response buffer */
- fb_response_str = response;
-
- fastboot_fail("no flash device defined");
-#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
- fb_mmc_erase(cmd);
-#endif
-#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
- fb_nand_erase(cmd);
-#endif
- fastboot_tx_write_str(response);
-}
-#endif
-
struct cmd_dispatch_info {
char *cmd;
void (*cb)(struct usb_ep *ep, struct usb_request *req);
};
static const struct cmd_dispatch_info cmd_dispatch_info[] = {
+#ifdef CONFIG_FSL_FASTBOOT
+ {
+ .cmd = "reboot-bootloader",
+ .cb = cb_reboot_bootloader,
+ },
+ {
+ .cmd = "upload",
+ .cb = cb_upload,
+ },
+#ifdef CONFIG_FASTBOOT_LOCK
+ {
+ .cmd = "flashing",
+ .cb = cb_flashing,
+ },
+ {
+ .cmd = "oem",
+ .cb = cb_flashing,
+ },
+#endif
+#ifdef CONFIG_AVB_SUPPORT
+ {
+ .cmd = "set_active",
+ .cb = cb_set_active_avb,
+ },
+#endif
+#endif
{
.cmd = "reboot",
.cb = cb_reboot,
@@ -695,10 +3479,12 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = {
.cb = cb_erase,
},
#endif
+#ifndef CONFIG_FSL_FASTBOOT
{
.cmd = "oem",
.cb = cb_oem,
},
+#endif
};
static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
@@ -707,6 +3493,10 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
int i;
+ /* init in request FIFO pointer */
+ fastboot_func->front = NULL;
+ fastboot_func->rear = NULL;
+
if (req->status != 0 || req->length == 0)
return;
diff --git a/drivers/usb/gadget/fastboot_lock_unlock.c b/drivers/usb/gadget/fastboot_lock_unlock.c
new file mode 100644
index 0000000000..230f892f67
--- /dev/null
+++ b/drivers/usb/gadget/fastboot_lock_unlock.c
@@ -0,0 +1,467 @@
+/*
+ * 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.
+ */
+#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 <fsl_fastboot.h>
+
+#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);
+
+#ifndef FASTBOOT_ENCRYPT_LOCK
+
+/*
+ * This will return FASTBOOT_LOCK, FASTBOOT_UNLOCK or FASTBOOT_ERROR
+ */
+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;
+}
+#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) {
+ unsigned char plain_data[ENDATA_LEN];
+ int p = 0, ret;
+
+ caam_open();
+ ret = caam_decap_blob((uint32_t)plain_data,
+ (uint32_t)bdata + ENDATA_LEN, 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)bdata, (uint32_t)(bdata + ENDATA_LEN), 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;
+/*
+ * 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;
+ disk_partition_t fs_partition;
+ unsigned char *bdata;
+ int mmc_id;
+ int status, ret;
+
+ bdata = (unsigned char *)memalign(ALIGN_BYTES, 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;
+ disk_partition_t fs_partition;
+ unsigned char *bdata;
+ int mmc_id;
+ FbLockState ret;
+
+ bdata = (unsigned char *)memalign(ALIGN_BYTES, 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;
+}
+
+
+/* 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;
+ disk_partition_t 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;
+ disk_partition_t 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;
+ disk_partition_t 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;
+}
diff --git a/drivers/usb/gadget/fastboot_lock_unlock.h b/drivers/usb/gadget/fastboot_lock_unlock.h
new file mode 100644
index 0000000000..f08ab269bb
--- /dev/null
+++ b/drivers/usb/gadget/fastboot_lock_unlock.h
@@ -0,0 +1,71 @@
+/*
+ * 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);
+
+FbLockEnableResult fastboot_lock_enable(void);
+void set_fastboot_lock_disable(void);
+
+int display_lock(FbLockState lock, int verify);
+#endif
diff --git a/include/android_image.h b/include/android_image.h
index dfd4d9d72c..ffe50d3b9d 100644
--- a/include/android_image.h
+++ b/include/android_image.h
@@ -20,6 +20,19 @@ typedef struct andr_img_hdr andr_img_hdr;
#define ANDR_BOOT_ARGS_SIZE 512
#define ANDR_BOOT_EXTRA_ARGS_SIZE 1024
+/* 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 {
char magic[ANDR_BOOT_MAGIC_SIZE];
@@ -80,4 +93,16 @@ struct andr_img_hdr {
* 6. if second_size != 0: jump to second_addr
* 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
diff --git a/include/common.h b/include/common.h
index 71c2e39f21..eed03c33d5 100644
--- a/include/common.h
+++ b/include/common.h
@@ -685,6 +685,10 @@ int cpu_disable(int nr);
int cpu_release(int nr, int argc, char * const argv[]);
#endif
+#ifdef CONFIG_CMD_READ
+int do_raw_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+#endif
+
#else /* __ASSEMBLY__ */
/* Drop a C type modifier (like in 3UL) for constants used in assembly. */
diff --git a/include/fsl_fastboot.h b/include/fsl_fastboot.h
new file mode 100644
index 0000000000..8deac211d3
--- /dev/null
+++ b/include/fsl_fastboot.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef FSL_FASTBOOT_H
+#define FSL_FASTBOOT_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_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"
+#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_ANDROID_THINGS_SUPPORT
+#define FASTBOOT_BOOTLOADER_VBOOT_KEY "fuse at-bootloader-vboot-key"
+#endif
+
+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;
+
+
+struct cmd_fastboot_interface {
+ /* This function is called when a buffer has been
+ recieved from the client app.
+ The buffer is a supplied by the board layer and must be unmodified.
+ The buffer_size is how much data is passed in.
+ Returns 0 on success
+ Returns 1 on failure
+
+ Set by cmd_fastboot */
+ int (*rx_handler)(const unsigned char *buffer,
+ unsigned int buffer_size);
+
+ /* This function is called when an exception has
+ occurred in the device code and the state
+ off fastboot needs to be reset
+
+ Set by cmd_fastboot */
+ void (*reset_handler)(void);
+
+ /* A getvar string for the product name
+ It can have a maximum of 60 characters
+
+ Set by board */
+ char *product_name;
+
+ /* A getvar string for the serial number
+ It can have a maximum of 60 characters
+
+ Set by board */
+ char *serial_no;
+
+ /* Nand block size
+ Supports the write option WRITE_NEXT_GOOD_BLOCK
+
+ Set by board */
+ unsigned int nand_block_size;
+
+ /* Nand oob size
+ Set by board */
+ unsigned int nand_oob_size;
+
+ /* Transfer buffer, for handling flash updates
+ Should be multiple of the nand_block_size
+ Care should be take so it does not overrun bootloader memory
+ Controlled by the configure variable CFG_FASTBOOT_TRANSFER_BUFFER
+
+ Set by board */
+ unsigned char *transfer_buffer;
+
+ /* How big is the transfer buffer
+ Controlled by the configure variable
+ CFG_FASTBOOT_TRANSFER_BUFFER_SIZE
+
+ Set by board */
+ unsigned int transfer_buffer_size;
+
+};
+
+/* flash partitions are defined in terms of blocks
+** (flash erase units)
+*/
+struct fastboot_ptentry {
+ /* The logical name for this partition, null terminated */
+ char name[16];
+ /* 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;
+
+/* 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);
+
+/*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);
+
+#ifdef CONFIG_FASTBOOT_STORAGE_NAND
+/*Save parameters for NAND storage partitions */
+void save_parts_values(struct fastboot_ptentry *ptn,
+ unsigned int offset, unsigned int size);
+
+/* Checks parameters for NAND storage partitions
+ * Return 1 if the parameter is not set
+ * Return 0 if the parameter has been set
+ */
+int check_parts_values(struct fastboot_ptentry *ptn);
+#endif /*CONFIG_FASTBOOT_STORAGE_NAND*/
+
+/* 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 /* FSL_FASTBOOT_H */
diff --git a/include/image.h b/include/image.h
index dbdaecbfdd..bb54b4cc56 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1277,6 +1277,7 @@ int android_image_get_second(const struct andr_img_hdr *hdr,
ulong android_image_get_end(const struct andr_img_hdr *hdr);
ulong android_image_get_kload(const struct andr_img_hdr *hdr);
void android_print_contents(const struct andr_img_hdr *hdr);
+bool image_arm64(void *images);
#endif /* CONFIG_ANDROID_BOOT_IMAGE */
diff --git a/include/mmc.h b/include/mmc.h
index b39ebdcb0f..9ec452cd7d 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -814,6 +814,7 @@ int board_mmc_init(bd_t *bis);
int cpu_mmc_init(bd_t *bis);
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
int mmc_get_env_dev(void);
+int mmc_map_to_kernel_blk(int dev_no);
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
diff --git a/include/part.h b/include/part.h
index c129699bad..5678dab3f5 100644
--- a/include/part.h
+++ b/include/part.h
@@ -375,6 +375,14 @@ 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
index 0000000000..4519cffcb7
--- /dev/null
+++ b/include/recovery.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __RECOVERY_H_
+#define __RECOVERY_H_
+
+struct reco_envs {
+ char *cmd;
+ char *args;
+};
+
+void board_recovery_setup(void);
+
+#endif
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 7ca0c555d0..5acb18885a 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -31,6 +31,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
@@ -106,6 +110,10 @@ CONFIG_ATMEL_NAND_HW_PMECC
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
@@ -141,6 +149,8 @@ CONFIG_BOARD_TYPES
CONFIG_BOOGER
CONFIG_BOOTBLOCK
CONFIG_BOOTFILE
+CONFIG_BOOTLOADER_OFFSET_32K
+CONFIG_BOOTLOADER_OFFSET_33K
CONFIG_BOOTMAPSZ
CONFIG_BOOTMODE
CONFIG_BOOTM_LINUX
@@ -493,6 +503,7 @@ CONFIG_ELBC_NAND_SPL_STATIC_PGSIZE
CONFIG_EMMC_BOOT
CONFIG_EMU
CONFIG_ENABLE_36BIT_PHYS
+CONFIG_ENABLE_LOCKSTATUS_SUPPORT
CONFIG_ENABLE_MMU
CONFIG_ENABLE_MUST_CHECK
CONFIG_ENABLE_WARN_DEPRECATED
@@ -603,6 +614,7 @@ CONFIG_EXYNOS_TMU
CONFIG_FACTORYSET
CONFIG_FASTBOOT_FLASH_FILLBUF_SIZE
CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS
+CONFIG_FASTBOOT_LOCK
CONFIG_FAST_FLASH_BIT
CONFIG_FB_ADDR
CONFIG_FB_BACKLIGHT
@@ -656,6 +668,7 @@ CONFIG_FPGA_COUNT
CONFIG_FPGA_DELAY
CONFIG_FPGA_STRATIX_V
CONFIG_FSLDMAFEC
+CONFIG_FSL_CAAM_KB
CONFIG_FSL_CADMUS
CONFIG_FSL_CORENET
CONFIG_FSL_CPLD
@@ -2089,6 +2102,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