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