From 806c9ba15e8742a23b1b9147d9b85219133b6f10 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 14 May 2019 22:49:31 -0700 Subject: [PATCH] MLK-18591-3 android: Add FSL android fastboot support Porting the FSL android fastboot features from imx u-boot v2018.03 to support all SoCs: imx6/imx7/imx7ulp/imx8/imx8m. The UUU commands like UCmd and ACmd are also added. Users need set CONFIG_FASTBOOT_UUU_SUPPORT=y to enable the feature. Signed-off-by: Frank Li Signed-off-by: Ye Li (cherry picked from commit 65120b06a7f750b9b1a6e0db3d2082cc7088d5a8) (cherry picked from commit 9b149c2a28829fe7017f83981d634157bc31cc94) (cherry picked from commit 9f99e9de1d37e9f6c02c1b27348ea3dcdab94569) (cherry picked from commit 6ae1c043431a4987f563026b179b33945a5880ee) --- arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + arch/arm/mach-imx/Kconfig | 6 + arch/arm/mach-imx/cpu.c | 16 +- arch/arm/mach-imx/imx8m/soc.c | 19 +- arch/arm/mach-imx/mx6/soc.c | 5 + arch/arm/mach-imx/mx7/soc.c | 6 +- arch/arm/mach-imx/mx7ulp/soc.c | 37 + board/freescale/common/Makefile | 3 + board/freescale/common/recovery_keypad.c | 60 + board/freescale/common/recovery_keypad.h | 13 + board/freescale/mx6sabreauto/mx6sabreauto.c | 2 +- board/freescale/mx6sabresd/mx6sabresd.c | 2 +- cmd/fastboot.c | 3 + cmd/read.c | 4 +- common/board_r.c | 23 + common/image-android.c | 216 +++- disk/part_efi.c | 77 +- drivers/fastboot/Kconfig | 43 +- drivers/fastboot/Makefile | 6 +- drivers/fastboot/fb_common.c | 16 + drivers/fastboot/fb_fsl/Makefile | 13 + drivers/fastboot/fb_fsl/bcb.c | 168 +++ drivers/fastboot/fb_fsl/bcb.h | 57 + drivers/fastboot/fb_fsl/command.c | 61 + .../fastboot/fb_fsl/fastboot_lock_unlock.c | 583 +++++++++ .../fastboot/fb_fsl/fastboot_lock_unlock.h | 74 ++ drivers/fastboot/fb_fsl/fb_fsl_boot.c | 1051 +++++++++++++++++ drivers/fastboot/fb_fsl/fb_fsl_command.c | 898 ++++++++++++++ drivers/fastboot/fb_fsl/fb_fsl_common.c | 378 ++++++ drivers/fastboot/fb_fsl/fb_fsl_common.h | 50 + drivers/fastboot/fb_fsl/fb_fsl_dev.c | 552 +++++++++ drivers/fastboot/fb_fsl/fb_fsl_getvar.c | 572 +++++++++ drivers/fastboot/fb_fsl/fb_fsl_partitions.c | 413 +++++++ drivers/usb/gadget/f_fastboot.c | 78 +- include/android_image.h | 36 +- include/command.h | 4 + include/fastboot.h | 20 +- include/fb_fsl.h | 248 ++++ include/image.h | 1 + include/init.h | 4 + include/mmc.h | 1 + include/part.h | 9 + include/recovery.h | 17 + lib/avb/fsl/fsl_avb.c | 4 +- lib/avb/fsl/fsl_bootctl.c | 2 +- scripts/config_whitelist.txt | 10 + 46 files changed, 5822 insertions(+), 40 deletions(-) create mode 100644 board/freescale/common/recovery_keypad.c create mode 100644 board/freescale/common/recovery_keypad.h create mode 100644 drivers/fastboot/fb_fsl/Makefile create mode 100644 drivers/fastboot/fb_fsl/bcb.c create mode 100644 drivers/fastboot/fb_fsl/bcb.h create mode 100644 drivers/fastboot/fb_fsl/command.c create mode 100644 drivers/fastboot/fb_fsl/fastboot_lock_unlock.c create mode 100644 drivers/fastboot/fb_fsl/fastboot_lock_unlock.h create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_boot.c create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_command.c create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_common.c create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_common.h create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_dev.c create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_getvar.c create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_partitions.c create mode 100644 include/fb_fsl.h create mode 100644 include/recovery.h diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h index 688aabfb35..75ba38716c 100644 --- a/arch/arm/include/asm/arch-mx6/sys_proto.h +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h @@ -39,6 +39,7 @@ static inline void iomuxc_set_rgmii_io_voltage(int io_vol) } void set_wdog_reset(struct wdog_regs *wdog); +enum boot_device get_boot_device(void); #ifdef CONFIG_LDO_BYPASS_CHECK int check_ldo_bypass(void); diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index be95f1b062..af6ef6eb81 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -147,6 +147,12 @@ config NXP_BOARD_REVISION stored in the fuses. Select this option if you want to be able to retrieve the board revision information. +config FLASH_MCUFIRMWARE_SUPPORT + bool "Enable mcu firmware flash support" + depends on ARCH_MX7ULP || ARCH_IMX8M + help + This enables the mcu firmware flash support for some SOCs. + config DDRMC_VF610_CALIBRATION bool "Enable DDRMC (DDR3) on-chip calibration" depends on ARCH_VF610 diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index 08e9ca07ef..6c6ae7860d 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -44,7 +44,10 @@ u32 get_imx_reset_cause(void) if (reset_cause == -1) { reset_cause = readl(&src_regs->srsr); /* preserve the value for U-Boot proper */ -#if !defined(CONFIG_SPL_BUILD) +#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_ANDROID_BOOT_IMAGE) + /* We will read the ssrs states later for android so we don't + * clear the states here. + */ writel(reset_cause, &src_regs->srsr); #endif } @@ -95,6 +98,17 @@ static char *get_reset_cause(void) return "unknown reset"; } } + +#ifdef CONFIG_ANDROID_BOOT_IMAGE +void get_reboot_reason(char *ret) +{ + struct src *src_regs = (struct src *)SRC_BASE_ADDR; + + strcpy(ret, (const char *)get_reset_cause()); + /* clear the srsr here, its state has been recorded in reset_cause */ + writel(reset_cause, &src_regs->srsr); +} +#endif #endif #if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_SPL_BUILD) diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 01e65dacac..4b6715c081 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -29,13 +29,14 @@ #include #include #include +#include #ifdef CONFIG_IMX_SEC_INIT #include #endif DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_IMX_HAB) +#if defined(CONFIG_IMX_HAB) || defined(CONFIG_AVB_ATX) struct imx_sec_config_fuse_t const imx_sec_config_fuse = { .bank = 1, .word = 3, @@ -493,6 +494,10 @@ int arch_cpu_init(void) /* Secure init function such RNG */ imx_sec_init(); #endif +#if defined(CONFIG_ANDROID_SUPPORT) + /* Enable RTC */ + writel(0x21, 0x30370038); +#endif if (is_imx8mq()) { clock_enable(CCGR_OCOTP, 1); @@ -555,6 +560,18 @@ bool is_usb_boot(void) { return get_boot_device() == USB_BOOT; } +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + + serialnr->low = fuse->uid_low; + serialnr->high = fuse->uid_high; +} +#endif #ifdef CONFIG_OF_SYSTEM_SETUP bool check_fdt_new_path(void *blob) diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c index 7e28a55fc1..c0b2ece31e 100644 --- a/arch/arm/mach-imx/mx6/soc.c +++ b/arch/arm/mach-imx/mx6/soc.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef CONFIG_IMX_SEC_INIT #include #endif @@ -854,6 +855,10 @@ void s_init(void) u32 mask528; u32 reg, periph1, periph2; +#if defined(CONFIG_ANDROID_SUPPORT) + /* Enable RTC */ + writel(0x21, 0x020cc038); +#endif if (is_mx6sx() || is_mx6ul() || is_mx6ull() || is_mx6sll()) return; diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c index 19e11e57f4..3e00de6abd 100644 --- a/arch/arm/mach-imx/mx7/soc.c +++ b/arch/arm/mach-imx/mx7/soc.c @@ -130,7 +130,7 @@ static void isolate_resource(void) } #endif -#if defined(CONFIG_IMX_HAB) +#if defined(CONFIG_IMX_HAB) || defined(CONFIG_AVB_ATX) struct imx_sec_config_fuse_t const imx_sec_config_fuse = { .bank = 1, .word = 3, @@ -443,6 +443,10 @@ void s_init(void) /* clock configuration. */ clock_init(); +#if defined(CONFIG_ANDROID_SUPPORT) + /* Enable RTC */ + writel(0x21, 0x30370038); +#endif return; } diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c index 253d8f2522..63002e42df 100644 --- a/arch/arm/mach-imx/mx7ulp/soc.c +++ b/arch/arm/mach-imx/mx7ulp/soc.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef CONFIG_IMX_SEC_INIT #include #endif @@ -250,6 +251,11 @@ void s_init(void) if (soc_rev() < CHIP_REV_2_0) { /* enable dumb pmic */ writel((readl(SNVS_LP_LPCR) | SNVS_LPCR_DPEN), SNVS_LP_LPCR); + +#if defined(CONFIG_ANDROID_SUPPORT) + /* Enable RTC */ + writel((readl(SNVS_LP_LPCR) | SNVS_LPCR_SRTC_ENV), SNVS_LP_LPCR); +#endif } #if defined(CONFIG_LDO_ENABLED_MODE) @@ -343,7 +349,12 @@ static char *get_reset_cause(char *ret) srs = readl(reg_srs); cause1 = readl(reg_ssrs); +#ifndef CONFIG_ANDROID_BOOT_IMAGE + /* We will read the ssrs states later for android so we don't + * clear the states here. + */ writel(cause1, reg_ssrs); +#endif reset_cause = cause1; @@ -383,6 +394,17 @@ static char *get_reset_cause(char *ret) return ret; } +#ifdef CONFIG_ANDROID_BOOT_IMAGE +void get_reboot_reason(char *ret) +{ + u32 *reg_ssrs = (u32 *)(SRC_BASE_ADDR + 0x28); + + get_reset_cause(ret); + /* clear the ssrs here, its state has been recorded in reset_cause */ + writel(reset_cause, reg_ssrs); +} +#endif + void arch_preboot_os(void) { scg_disable_pll_pfd(SCG_APLL_PFD1_CLK); @@ -437,3 +459,18 @@ enum boot_device get_boot_device(void) return boot_dev; } + +#ifdef CONFIG_FSL_FASTBOOT +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ + + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[1]; + struct fuse_bank1_regs *fuse = + (struct fuse_bank1_regs *)bank->fuse_regs; + serialnr->low = (fuse->cfg0 & 0xFFFF) + ((fuse->cfg1 & 0xFFFF) << 16); + serialnr->high = (fuse->cfg2 & 0xFFFF) + ((fuse->cfg3 & 0xFFFF) << 16); +} +#endif /*CONFIG_SERIAL_TAG*/ +#endif /*CONFIG_FSL_FASTBOOT*/ diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index 26085e504c..a8efadaacc 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -63,6 +63,9 @@ obj-$(CONFIG_MXC_EPDC) += epdc_setup.o ifneq (,$(filter $(SOC), mx25 mx31 mx35 mx5 mx6 mx7 mx7ulp imx8 imx8m vf610)) obj-y += mmc.o endif +ifdef CONFIG_FSL_FASTBOOT +obj-${CONFIG_ANDROID_RECOVERY} += recovery_keypad.o +endif obj-$(CONFIG_LS102XA_STREAM_ID) += ls102xa_stream_id.o diff --git a/board/freescale/common/recovery_keypad.c b/board/freescale/common/recovery_keypad.c new file mode 100644 index 0000000000..2f5a58a92d --- /dev/null +++ b/board/freescale/common/recovery_keypad.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2017 NXP + * + */ +#include +#include +#include +#ifdef CONFIG_MXC_KPD +#include +#endif +#include + +#ifdef CONFIG_MXC_KPD +#define PRESSED_VOL_DOWN 0x01 +#define PRESSED_POWER 0x02 +#define RECOVERY_KEY_MASK (PRESSED_VOL_DOWN | PRESSED_POWER) + +inline int test_key(int value, struct kpp_key_info *ki) +{ + return (ki->val == value) && (ki->evt == KDepress); +} + +int is_recovery_keypad_pressing(void) +{ + struct kpp_key_info *key_info = NULL; + int state = 0, keys, i; + + int ret = 0; + + mxc_kpp_init(); + /* due to glitch suppression circuit, + wait sometime to let all keys scanned. */ + udelay(1000); + keys = mxc_kpp_getc(&key_info); + + printf("Detecting VOL_DOWN+POWER key for recovery(%d:%d) ...\n", + keys, keys ? key_info->val : 0); + if (keys > 1) { + for (i = 0; i < keys; i++) { + if (test_key(CONFIG_POWER_KEY, &key_info[i])) + state |= PRESSED_POWER; + else if (test_key(CONFIG_VOL_DOWN_KEY, &key_info[i])) + state |= PRESSED_VOL_DOWN; + } + } + if ((state & RECOVERY_KEY_MASK) == RECOVERY_KEY_MASK) + ret = 1; + if (key_info) + free(key_info); + return ret; +} +#else +/* If not using mxc keypad, currently we will detect power key on board */ +int is_recovery_keypad_pressing(void) +{ + return 0; +} +#endif diff --git a/board/freescale/common/recovery_keypad.h b/board/freescale/common/recovery_keypad.h new file mode 100644 index 0000000000..9adf2243e8 --- /dev/null +++ b/board/freescale/common/recovery_keypad.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2017 NXP + * + */ + +#ifndef __RECOVERY_KEYPAD_H_ +#define __RECOVERY_KEYPAD_H_ + +int is_recovery_keypad_pressing(void); + +#endif diff --git a/board/freescale/mx6sabreauto/mx6sabreauto.c b/board/freescale/mx6sabreauto/mx6sabreauto.c index fe5fa8a32a..a71303ef3e 100644 --- a/board/freescale/mx6sabreauto/mx6sabreauto.c +++ b/board/freescale/mx6sabreauto/mx6sabreauto.c @@ -41,7 +41,7 @@ #include #endif #ifdef CONFIG_FSL_FASTBOOT -#include +#include #ifdef CONFIG_ANDROID_RECOVERY #include #endif diff --git a/board/freescale/mx6sabresd/mx6sabresd.c b/board/freescale/mx6sabresd/mx6sabresd.c index bc0266d3ba..d7e56e4651 100644 --- a/board/freescale/mx6sabresd/mx6sabresd.c +++ b/board/freescale/mx6sabresd/mx6sabresd.c @@ -46,7 +46,7 @@ #include #endif #ifdef CONFIG_FSL_FASTBOOT -#include +#include #ifdef CONFIG_ANDROID_RECOVERY #include #endif diff --git a/cmd/fastboot.c b/cmd/fastboot.c index ad5c064911..a547645eab 100644 --- a/cmd/fastboot.c +++ b/cmd/fastboot.c @@ -52,6 +52,9 @@ static int do_fastboot_usb(int argc, char *const argv[], pr_err("Error: Wrong USB controller index format\n"); return CMD_RET_FAILURE; } +#ifdef CONFIG_FASTBOOT_USB_DEV + controller_index = CONFIG_FASTBOOT_USB_DEV; +#endif ret = usb_gadget_initialize(controller_index); if (ret) { diff --git a/cmd/read.c b/cmd/read.c index 34f53f9a29..daea30a478 100644 --- a/cmd/read.c +++ b/cmd/read.c @@ -12,7 +12,7 @@ #include #include -int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +int do_raw_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { char *ep; struct blk_desc *dev_desc = NULL; @@ -75,7 +75,7 @@ int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } U_BOOT_CMD( - read, 6, 0, do_read, + read, 6, 0, do_raw_read, "Load binary data from a partition", " addr blk# cnt" ); diff --git a/common/board_r.c b/common/board_r.c index 2fde0a1359..904cc999e2 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -77,6 +77,9 @@ #ifdef CONFIG_EFI_SETUP_EARLY #include #endif +#ifdef CONFIG_FSL_FASTBOOT +#include +#endif DECLARE_GLOBAL_DATA_PTR; @@ -586,6 +589,20 @@ static int initr_avbkey(void) } #endif +#ifdef CONFIG_FSL_FASTBOOT +static int initr_fastboot_setup(void) +{ + fastboot_setup(); + return 0; +} + +static int initr_check_fastboot(void) +{ + fastboot_run_bootmode(); + return 0; +} +#endif + static int run_main_loop(void) { #ifdef CONFIG_SANDBOX @@ -767,6 +784,9 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif +#ifdef CONFIG_FSL_FASTBOOT + initr_fastboot_setup, +#endif #if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI) INIT_FUNC_WATCHDOG_RESET initr_scsi, @@ -808,6 +828,9 @@ static init_fnc_t init_sequence_r[] = { #endif #if defined(AVB_RPMB) && !defined(CONFIG_SPL) initr_avbkey, +#endif +#ifdef CONFIG_FSL_FASTBOOT + initr_check_fastboot, #endif run_main_loop, }; diff --git a/common/image-android.c b/common/image-android.c index d07b0e0f09..048eac7aab 100644 --- a/common/image-android.c +++ b/common/image-android.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2011 Sebastian Andrzej Siewior + * + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP */ #include @@ -13,6 +16,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 @@ -62,6 +72,7 @@ static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, ulong *os_data, ulong *os_len) { + extern boot_metric metrics; u32 kernel_addr = android_image_get_kernel_addr(hdr); const struct image_header *ihdr = (const struct image_header *) ((uintptr_t)hdr + hdr->page_size); @@ -79,31 +90,188 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, printf("Kernel load addr 0x%08x size %u KiB\n", kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); - int len = 0; - if (*hdr->cmdline) { - printf("Kernel command line: %s\n", hdr->cmdline); - len += strlen(hdr->cmdline); + char newbootargs[512] = {0}; + char commandline[2048] = {0}; + int offset; + char *bootargs = env_get("bootargs"); + + if (bootargs) { + if (strlen(bootargs) + 1 > sizeof(commandline)) { + printf("bootargs is too long!\n"); + return -1; + } + else + strncpy(commandline, bootargs, sizeof(commandline) - 1); + } else { + offset = fdt_path_offset(gd->fdt_blob, "/chosen"); + if (offset > 0) { + bootargs = (char *)fdt_getprop(gd->fdt_blob, offset, + "bootargs", NULL); + if (bootargs) + sprintf(commandline, "%s ", bootargs); + } + + if (*hdr->cmdline) { + if (strlen(hdr->cmdline) + 1 > + sizeof(commandline) - strlen(commandline)) { + printf("cmdline in bootimg is too long!\n"); + return -1; + } + else + strncat(commandline, hdr->cmdline, sizeof(commandline) - strlen(commandline)); + } } - char *bootargs = env_get("bootargs"); - if (bootargs) - len += strlen(bootargs); + /* Add 'bootargs_ram_capacity' to hold the parameters based on different ram capacity */ + char *bootargs_ram_capacity = env_get("bootargs_ram_capacity"); + if (bootargs_ram_capacity) { + strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, bootargs_ram_capacity, + sizeof(commandline) - strlen(commandline)); + } + +#ifdef CONFIG_SERIAL_TAG + struct tag_serialnr serialnr; + get_board_serial(&serialnr); + + sprintf(newbootargs, + " androidboot.serialno=%08x%08x", + serialnr.high, + serialnr.low); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + + char bd_addr[16]={0}; + sprintf(bd_addr, + "%08x%08x", + serialnr.high, + serialnr.low); + sprintf(newbootargs, + " androidboot.btmacaddr=%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],bd_addr[5], + bd_addr[6],bd_addr[7],bd_addr[8],bd_addr[9],bd_addr[10],bd_addr[11]); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); +#endif - char *newbootargs = malloc(len + 2); - if (!newbootargs) { - puts("Error: malloc in android_image_get_kernel failed!\n"); - return -ENOMEM; + /* append soc type into bootargs */ + char *soc_type = env_get("soc_type"); + if (soc_type) { + sprintf(newbootargs, + " androidboot.soc_type=%s", + soc_type); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); } - *newbootargs = '\0'; - if (bootargs) { - strcpy(newbootargs, bootargs); - strcat(newbootargs, " "); + char *storage_type = env_get("storage_type"); + if (storage_type) { + sprintf(newbootargs, + " androidboot.storage_type=%s", + storage_type); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + } else { + int bootdev = get_boot_device(); + if (bootdev == SD1_BOOT || bootdev == SD2_BOOT || + bootdev == SD3_BOOT || bootdev == SD4_BOOT) { + sprintf(newbootargs, + " androidboot.storage_type=sd"); + } else if (bootdev == MMC1_BOOT || bootdev == MMC2_BOOT || + bootdev == MMC3_BOOT || bootdev == MMC4_BOOT) { + sprintf(newbootargs, + " androidboot.storage_type=emmc"); + } else if (bootdev == NAND_BOOT) { + sprintf(newbootargs, + " androidboot.storage_type=nand"); + } else + printf("boot device type is incorrect.\n"); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + if (bootloader_gpt_overlay()) { + sprintf(newbootargs, " gpt"); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + } } - if (*hdr->cmdline) - strcat(newbootargs, hdr->cmdline); - env_set("bootargs", newbootargs); + /* boot metric variables */ + metrics.ble_1 = get_timer(0); + sprintf(newbootargs, + " androidboot.boottime=1BLL:%d,1BLE:%d,KL:%d,KD:%d,AVB:%d,ODT:%d,SW:%d", + metrics.bll_1, metrics.ble_1, metrics.kl, metrics.kd, metrics.avb, + metrics.odt, metrics.sw); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + +#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \ + defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M) + char cause[18]; + + memset(cause, '\0', sizeof(cause)); + get_reboot_reason(cause); + if (strstr(cause, "POR")) + sprintf(newbootargs," androidboot.bootreason=cold,powerkey"); + else if (strstr(cause, "WDOG") || strstr(cause, "WDG")) + sprintf(newbootargs," androidboot.bootreason=watchdog"); + else + sprintf(newbootargs," androidboot.bootreason=reboot"); +#else + sprintf(newbootargs," androidboot.bootreason=reboot"); +#endif + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + +#ifdef CONFIG_AVB_SUPPORT + /* secondary cmdline added by avb */ + char *bootargs_sec = env_get("bootargs_sec"); + if (bootargs_sec) { + strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, bootargs_sec, sizeof(commandline) - strlen(commandline)); + } +#endif +#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT + /* Normal boot: + * cmdline to bypass ramdisk in boot.img, but use the system.img + * Recovery boot: + * Use the ramdisk in boot.img + */ + char *bootargs_3rd = env_get("bootargs_3rd"); + if (bootargs_3rd) { + strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, bootargs_3rd, sizeof(commandline) - strlen(commandline)); + } +#endif + + /* VTS need this commandline to verify fdt overlay. Pass the + * dtb index as "0" here since we only have one dtb in dtbo + * partition and haven't enabled the dtb overlay. + */ +#if defined(CONFIG_ANDROID_SUPPORT) || defined(CONFIG_ANDROID_AUTO_SUPPORT) + sprintf(newbootargs," androidboot.dtbo_idx=0"); + strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); +#endif + + char *keystore = env_get("keystore"); + if ((keystore == NULL) || strncmp(keystore, "trusty", sizeof("trusty"))) { + char *bootargs_trusty = "androidboot.keystore=software"; + strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline)); + } else { + char *bootargs_trusty = "androidboot.keystore=trusty"; + strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline)); + } + +#ifdef CONFIG_APPEND_BOOTARGS + /* Add 'append_bootargs' to hold some paramemters which need to be appended + * to bootargs */ + char *append_bootargs = env_get("append_bootargs"); + if (append_bootargs) { + if (strlen(append_bootargs) + 2 > + (sizeof(commandline) - strlen(commandline))) { + printf("The 'append_bootargs' is too long to be appended to bootargs\n"); + } else { + strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, append_bootargs, sizeof(commandline) - strlen(commandline)); + } + } +#endif + + debug("Kernel command line: %s\n", commandline); + env_set("bootargs", commandline); if (os_data) { if (image_get_magic(ihdr) == IH_MAGIC) { @@ -537,3 +705,15 @@ bool android_image_print_dtb_contents(ulong hdr_addr) return true; } #endif + +#define ARM64_IMAGE_MAGIC 0x644d5241 +bool image_arm64(void *images) +{ + struct header_image *ih; + + ih = (struct header_image *)images; + debug("image magic: %x\n", ih->magic); + if (ih->magic == le32_to_cpu(ARM64_IMAGE_MAGIC)) + return true; + return false; +} diff --git a/disk/part_efi.c b/disk/part_efi.c index e5636ea7e6..49a871b8d5 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -151,6 +151,25 @@ static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba, return 0; } +static void prepare_last_lba_gpt_header(struct blk_desc *dev_desc, gpt_header *gpt_h) +{ + uint32_t calc_crc32; + uint64_t val; + + /* recalculate the values for the Backup GPT Header */ + val = le64_to_cpu(gpt_h->my_lba); + gpt_h->my_lba = cpu_to_le64(dev_desc->lba - 1);; + gpt_h->alternate_lba = cpu_to_le64(val); + gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34); + gpt_h->partition_entry_lba = + cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1); + gpt_h->header_crc32 = 0; + + calc_crc32 = efi_crc32((const unsigned char *)gpt_h, + le32_to_cpu(gpt_h->header_size)); + gpt_h->header_crc32 = cpu_to_le32(calc_crc32); +} + static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e) { uint32_t calc_crc32; @@ -161,7 +180,7 @@ static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e) le32_to_cpu(gpt_h->sizeof_partition_entry)); if (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) { - printf("%s: 0x%x != 0x%x\n", + debug("%s: 0x%x != 0x%x\n", "GUID Partition Table Entry Array CRC is wrong", le32_to_cpu(gpt_h->partition_entry_array_crc32), calc_crc32); @@ -873,6 +892,58 @@ int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf) return 0; } +int write_backup_gpt_partitions(struct blk_desc *dev_desc, void *buf) +{ + gpt_header *gpt_h; + gpt_entry *gpt_e; + int gpt_e_blk_cnt; + lbaint_t lba; + int cnt; + + if (is_valid_gpt_buf(dev_desc, buf)) + return -1; + + /* determine start of GPT Header in the buffer */ + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA * + dev_desc->blksz); + + /* determine start of GPT Entries in the buffer */ + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) * + dev_desc->blksz); + gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) * + le32_to_cpu(gpt_h->sizeof_partition_entry)), + dev_desc); + + /* write MBR */ + lba = 0; /* MBR is always at 0 */ + cnt = 1; /* MBR (1 block) */ + if (blk_dwrite(dev_desc, lba, cnt, buf) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "MBR", cnt, lba); + return 1; + } + + prepare_last_lba_gpt_header(dev_desc, gpt_h); + + /* write Backup GPT */ + lba = le64_to_cpu(gpt_h->partition_entry_lba); + cnt = gpt_e_blk_cnt; + if (blk_dwrite(dev_desc, lba, cnt, gpt_e) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "Backup GPT Entries", cnt, lba); + return 1; + } + + lba = le64_to_cpu(gpt_h->my_lba); + cnt = 1; /* GPT Header (1 block) */ + if (blk_dwrite(dev_desc, lba, cnt, gpt_h) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "Backup GPT Header", cnt, lba); + return 1; + } + + return 0; +} #endif /* @@ -1005,7 +1076,7 @@ static int find_valid_gpt(struct blk_desc *dev_desc, gpt_header *gpt_head, if (r != 1) { if (r != 2) - printf("%s: *** ERROR: Invalid GPT ***\n", __func__); + debug("%s: *** ERROR: Invalid GPT ***\n", __func__); if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), gpt_head, pgpt_pte) != 1) { @@ -1014,7 +1085,7 @@ static int find_valid_gpt(struct blk_desc *dev_desc, gpt_header *gpt_head, return 0; } if (r != 2) - printf("%s: *** Using Backup GPT ***\n", + debug("%s: *** Using Backup GPT ***\n", __func__); } return 1; diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 2d1836a80e..04d630ed47 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -74,16 +74,55 @@ config FASTBOOT_FLASH config FASTBOOT_UUU_SUPPORT bool "Enable FASTBOOT i.MX UUU special command" - default n + default y if ARCH_MX7 || ARCH_MX6 || ARCH_IMX8 || ARCH_IMX8M || ARCH_MX7ULP + select FSL_FASTBOOT help The fastboot protocol includes "UCmd" and "ACmd" command. Be aware that you provide full access to any U-Boot command, including working with memory and may open a huge backdoor, when enabling this option. +config FSL_FASTBOOT + bool "Enable FSL fastboot support" + depends on FASTBOOT_FLASH + help + This enables FSL implementation for Android fastboot. + +config ANDROID_RECOVERY + bool "Enable the recovery boot function" + depends on FSL_FASTBOOT + help + This enables the Android Recovery boot function. + +config CMD_BOOTA + bool "Enable the boota command" + depends on FSL_FASTBOOT + help + This enables the boota command for booting android images. + +config BCB_SUPPORT + bool "Enable the boot control block support" + depends on FSL_FASTBOOT + help + This enables the boot control block support for android reboot command + +config FASTBOOT_LOCK + bool "Enable the lock and unlock feature to the partitions" + depends on FSL_FASTBOOT + help + This enables the lock support for android flashing command + +config FASTBOOT_USB_DEV + int "USB controller number" + default 0 + help + Some boards have USB OTG controller other than 0. Define this + option so it can be used in compiled environment (e.g. in + CONFIG_BOOTCOMMAND). + choice prompt "Flash provider for FASTBOOT" - depends on FASTBOOT_FLASH + depends on FASTBOOT_FLASH && !FSL_FASTBOOT config FASTBOOT_FLASH_MMC bool "FASTBOOT on MMC" diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile index 048af5aa82..902da22e67 100644 --- a/drivers/fastboot/Makefile +++ b/drivers/fastboot/Makefile @@ -1,7 +1,11 @@ # SPDX-License-Identifier: GPL-2.0+ obj-y += fb_common.o -obj-y += fb_getvar.o +ifndef CONFIG_FSL_FASTBOOT obj-y += fb_command.o +obj-y += fb_getvar.o obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o +else +obj-y += fb_fsl/ +endif diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index cbcc3683c4..140f949837 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -16,6 +16,7 @@ #include #include #include +#include /** * fastboot_buf_addr - base address of the fastboot download buffer @@ -136,12 +137,22 @@ void fastboot_boot(void) run_command(s, CMD_FLAG_ENV); } else { static char boot_addr_start[20]; +#ifdef CONFIG_FSL_FASTBOOT + static char *const bootm_args[] = { + "boota", boot_addr_start, NULL + }; + + snprintf(boot_addr_start, sizeof(boot_addr_start) - 1, + "0x%p", (void *)image_load_addr); +#else static char *const bootm_args[] = { "bootm", boot_addr_start, NULL }; snprintf(boot_addr_start, sizeof(boot_addr_start) - 1, "0x%p", fastboot_buf_addr); +#endif + printf("Booting kernel at %s...\n\n\n", boot_addr_start); do_bootm(NULL, 0, 2, bootm_args); @@ -178,8 +189,13 @@ void fastboot_set_progress_callback(void (*progress)(const char *msg)) */ void fastboot_init(void *buf_addr, u32 buf_size) { +#ifdef CONFIG_FSL_FASTBOOT + fastboot_buf_addr = buf_addr ? buf_addr : + (void *)env_get_ulong("fastboot_buffer", 16, CONFIG_FASTBOOT_BUF_ADDR); +#else fastboot_buf_addr = buf_addr ? buf_addr : (void *)CONFIG_FASTBOOT_BUF_ADDR; +#endif fastboot_buf_size = buf_size ? buf_size : CONFIG_FASTBOOT_BUF_SIZE; fastboot_set_progress_callback(NULL); } diff --git a/drivers/fastboot/fb_fsl/Makefile b/drivers/fastboot/fb_fsl/Makefile new file mode 100644 index 0000000000..34f90c721c --- /dev/null +++ b/drivers/fastboot/fb_fsl/Makefile @@ -0,0 +1,13 @@ +# +# Copyright 2019 NXP +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ccflags-y += -I./lib/avb + +ifndef CONFIG_SPL_BUILD +obj-y += fb_fsl_dev.o fb_fsl_boot.o fb_fsl_command.o fb_fsl_common.o fb_fsl_getvar.o fb_fsl_partitions.o +obj-$(CONFIG_FASTBOOT_LOCK) += fastboot_lock_unlock.o +obj-$(CONFIG_BCB_SUPPORT) += command.o bcb.o +endif diff --git a/drivers/fastboot/fb_fsl/bcb.c b/drivers/fastboot/fb_fsl/bcb.c new file mode 100644 index 0000000000..58073219e5 --- /dev/null +++ b/drivers/fastboot/fb_fsl/bcb.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + */ + +#include +#include +#include +#include +#include +#include +#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", + " addr blk# cnt" +); + +int bcb_rw_block(bool bread, char **ppblock, + uint *pblksize, char *pblock_write, uint offset, uint size) +{ + int ret; + char *argv[6]; + char addr_str[20]; + char cnt_str[8]; + char devpart_str[8]; + char block_begin_str[8]; + ulong blk_size = 0; + uint blk_begin = 0; + uint blk_end = 0; + uint block_cnt = 0; + char *p_block = NULL; + unsigned int mmc_id; + + if (bread && ((ppblock == NULL) || (pblksize == NULL))) + return -1; + + if (!bread && (pblock_write == NULL)) + return -1; + + mmc_id = mmc_get_env_dev(); + blk_size = get_block_size("mmc", mmc_id); + if (blk_size == 0) { + printf("bcb_rw_block, get_block_size return 0\n"); + return -1; + } + + blk_begin = offset/blk_size; + blk_end = (offset + size)/blk_size; + block_cnt = 1 + (blk_end - blk_begin); + + sprintf(devpart_str, "0x%x:0x%x", mmc_id, + fastboot_flash_find_index(FASTBOOT_PARTITION_MISC)); + sprintf(block_begin_str, "0x%x", blk_begin); + sprintf(cnt_str, "0x%x", block_cnt); + + argv[0] = "rw"; /* not care */ + argv[1] = "mmc"; + argv[2] = devpart_str; + argv[3] = addr_str; + argv[4] = block_begin_str; + argv[5] = cnt_str; + + if (bread) { + p_block = (char *)memalign(ALIGN_BYTES, blk_size * block_cnt); + if (NULL == p_block) { + printf("bcb_rw_block, memalign %d bytes failed\n", + (int)(blk_size * block_cnt)); + return -1; + } + sprintf(addr_str, "0x%x", (unsigned int)(uintptr_t)p_block); + ret = do_raw_read(NULL, 0, 6, argv); + if (ret) { + free(p_block); + printf("do_raw_read failed, ret %d\n", ret); + return -1; + } + + *ppblock = p_block; + *pblksize = (uint)blk_size; + } else { + sprintf(addr_str, "0x%x", (unsigned int)(uintptr_t)pblock_write); + ret = do_write(NULL, 0, 6, argv); + if (ret) { + printf("do_write failed, ret %d\n", ret); + return -1; + } + } + return 0; +} diff --git a/drivers/fastboot/fb_fsl/bcb.h b/drivers/fastboot/fb_fsl/bcb.h new file mode 100644 index 0000000000..af01c19201 --- /dev/null +++ b/drivers/fastboot/fb_fsl/bcb.h @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + */ + +#ifndef BCB_H +#define BCB_H +#include +#include + +#define FASTBOOT_BCB_CMD "bootonce-bootloader" +#ifdef CONFIG_ANDROID_RECOVERY +#define RECOVERY_BCB_CMD "boot-recovery" +#endif +/* keep same as bootable/recovery/bootloader.h */ +struct bootloader_message { + char command[32]; + char status[32]; + char recovery[768]; + + /* The 'recovery' field used to be 1024 bytes. It has only ever + been used to store the recovery command line, so 768 bytes + should be plenty. We carve off the last 256 bytes to store the + stage string (for multistage packages) and possible future + expansion. */ + char stage[32]; + + /* The 'reserved' field used to be 224 bytes when it was initially + carved off from the 1024-byte recovery field. Bump it up to + 1184-byte so that the entire bootloader_message struct rounds up + to 2048-byte. + */ + char reserved[1184]; +}; + +struct bootloader_message_ab { + struct bootloader_message message; + char slot_suffix[32]; + + /* Round up the entire struct to 4096-byte. */ + char reserved[2016]; +}; + +/* start from bootloader_message_ab.slot_suffix[BOOTCTRL_IDX] */ +#define BOOTCTRL_IDX 0 +#define MISC_COMMAND_IDX 0 +#define BOOTCTRL_OFFSET \ + (u32)(&(((struct bootloader_message_ab *)0)->slot_suffix[BOOTCTRL_IDX])) +#define MISC_COMMAND \ + (u32)(uintptr_t)(&(((struct bootloader_message *)0)->command[MISC_COMMAND_IDX])) +int bcb_rw_block(bool bread, char **ppblock, + uint *pblksize, char *pblock_write, uint offset, uint size); + +int bcb_write_command(char *bcb_command); +int bcb_read_command(char *command); + +#endif diff --git a/drivers/fastboot/fb_fsl/command.c b/drivers/fastboot/fb_fsl/command.c new file mode 100644 index 0000000000..349a014ead --- /dev/null +++ b/drivers/fastboot/fb_fsl/command.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + */ + +#include +#include +#include "bcb.h" + +int bcb_read_command(char *command) +{ + int ret = 0; + char *p_block = NULL; + uint offset_in_block = 0; + uint blk_size = 0; + + if (command == NULL) + return -1; + + ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); + if (ret) { + printf("read_bootctl, bcb_rw_block read failed\n"); + return -1; + } + + offset_in_block = MISC_COMMAND%blk_size; + memcpy(command, p_block + offset_in_block, 32); + free(p_block); + + return 0; +} +int bcb_write_command(char *bcb_command) +{ + int ret = 0; + char *p_block = NULL; + uint offset_in_block = 0; + uint blk_size = 0; + + if (bcb_command == NULL) + return -1; + + + ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); + if (ret) { + printf("write_bootctl, bcb_rw_block read failed\n"); + return -1; + } + + offset_in_block = MISC_COMMAND%blk_size; + memcpy(p_block + offset_in_block, bcb_command, 32); + + ret = bcb_rw_block(false, NULL, NULL, p_block, MISC_COMMAND, 32); + if (ret) { + free(p_block); + printf("write_bootctl, bcb_rw_block write failed\n"); + return -1; + } + + free(p_block); + return 0; +} diff --git a/drivers/fastboot/fb_fsl/fastboot_lock_unlock.c b/drivers/fastboot/fb_fsl/fastboot_lock_unlock.c new file mode 100644 index 0000000000..e5caced764 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fastboot_lock_unlock.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "fastboot_lock_unlock.h" +#include +#include +#include +#ifdef CONFIG_IMX_TRUSTY_OS +#include +#include +#endif + +#ifdef FASTBOOT_ENCRYPT_LOCK + +#include +#include + +//Encrypted data is 80bytes length. +#define ENDATA_LEN 80 + +#endif + +int fastboot_flash_find_index(const char *name); + +#if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_ARM64) +#define IVT_HEADER_MAGIC 0xD1 +#define IVT_HDR_LEN 0x20 +#define HAB_MAJ_VER 0x40 +#define HAB_MAJ_MASK 0xF0 + +bool tos_flashed; + +static bool tos_ivt_check(ulong start_addr, int ivt_offset) { + const struct ivt *ivt_initial = NULL; + const uint8_t *start = (const uint8_t *)start_addr; + + if (start_addr & 0x3) { + puts("Error: tos's start address is not 4 byte aligned\n"); + return false; + } + + ivt_initial = (const struct ivt *)(start + ivt_offset); + + const struct ivt_header *ivt_hdr = &ivt_initial->hdr; + + if ((ivt_hdr->magic == IVT_HEADER_MAGIC && \ + (be16_to_cpu(ivt_hdr->length) == IVT_HDR_LEN) && \ + (ivt_hdr->version & HAB_MAJ_MASK) == HAB_MAJ_VER) && \ + (ivt_initial->entry != 0x0) && \ + (ivt_initial->reserved1 == 0x0) && \ + (ivt_initial->self == (uint32_t)ivt_initial) && \ + (ivt_initial->csf != 0x0) && \ + (ivt_initial->reserved2 == 0x0)) { + if (ivt_initial->dcd != 0x0) + return false; + else + return true; + } + + return false; +} + +bool valid_tos() { + /* + * If enabled SECURE_BOOT then use HAB to verify tos. + * Or check the IVT only. + */ + bool valid = false; +#ifdef CONFIG_IMX_HAB + if (is_hab_enabled()) { + valid = authenticate_image(TRUSTY_OS_ENTRY, TRUSTY_OS_PADDED_SZ); + } else +#endif + valid = tos_ivt_check(TRUSTY_OS_ENTRY, TRUSTY_OS_PADDED_SZ); + + if (valid) { + tos_flashed = true; + return true; + } else { + tos_flashed = false; + return false; + } +} + +#endif + +#if !defined(FASTBOOT_ENCRYPT_LOCK) || defined(NON_SECURE_FASTBOOT) + +/* + * This will return FASTBOOT_LOCK, FASTBOOT_UNLOCK or FASTBOOT_ERROR + */ +#ifndef CONFIG_IMX_TRUSTY_OS +static FbLockState decrypt_lock_store(unsigned char* bdata) { + if (!strncmp((const char *)bdata, "locked", strlen("locked"))) + return FASTBOOT_LOCK; + else if (!strncmp((const char *)bdata, "unlocked", strlen("unlocked"))) + return FASTBOOT_UNLOCK; + else + return FASTBOOT_LOCK_ERROR; +} +static inline int encrypt_lock_store(FbLockState lock, unsigned char* bdata) { + if (FASTBOOT_LOCK == lock) + strncpy((char *)bdata, "locked", strlen("locked")); + else if (FASTBOOT_UNLOCK == lock) + strncpy((char *)bdata, "unlocked", strlen("unlocked")); + else + return -1; + return 0; +} +#endif +#else + +static int sha1sum(unsigned char* data, int len, unsigned char* output) { + struct hash_algo *algo; + void *buf; + if (hash_lookup_algo("sha1", &algo)) { + printf("error in lookup sha1 algo!\n"); + return -1; + } + buf = map_sysmem((ulong)data, len); + algo->hash_func_ws(buf, len, output, algo->chunk_size); + unmap_sysmem(buf); + + return algo->digest_size; + +} + +static int generate_salt(unsigned char* salt) { + unsigned long time = get_timer(0); + return sha1sum((unsigned char *)&time, sizeof(unsigned long), salt); + +} + +static FbLockState decrypt_lock_store(unsigned char *bdata) { + int p = 0, ret; + ALLOC_CACHE_ALIGN_BUFFER(uint8_t, plain_data, ENDATA_LEN); + + caam_open(); + ret = caam_decap_blob((uint32_t)(ulong)plain_data, + (uint32_t)(ulong)bdata + ROUND(ENDATA_LEN, ARCH_DMA_MINALIGN), + ENDATA_LEN); + if (ret != 0) { + printf("Error during blob decap operation: 0x%x\n",ret); + return FASTBOOT_LOCK_ERROR; + } +#ifdef FASTBOOT_LOCK_DEBUG + FB_DEBUG("Decrypt data block are:\n \t=======\t\n"); + for (p = 0; p < ENDATA_LEN; p++) { + FB_DEBUG("0x%2x ", *(bdata + p)); + if (p % 16 == 0) + FB_DEBUG("\n"); + } + FB_DEBUG("\n \t========\t\n"); + for (p = ENDATA_LEN; p < (ENDATA_LEN + ENDATA_LEN + 48 ); p++) { + FB_DEBUG("0x%2x ", *(bdata + p)); + if (p % 16 == 0) + FB_DEBUG("\n"); + } + + FB_DEBUG("\n plain text are:\n"); + for (p = 0; p < ENDATA_LEN; p++) { + FB_DEBUG("0x%2x ", plain_data[p]); + if (p % 16 == 0) + FB_DEBUG("\n"); + } + FB_DEBUG("\n"); +#endif + + for (p = 0; p < ENDATA_LEN-1; p++) { + if (*(bdata+p) != plain_data[p]) { + FB_DEBUG("Verify salt in decrypt error on pointer %d\n", p); + return FASTBOOT_LOCK_ERROR; + } + } + + if (plain_data[ENDATA_LEN - 1] >= FASTBOOT_LOCK_NUM) + return FASTBOOT_LOCK_ERROR; + else + return plain_data[ENDATA_LEN-1]; +} + +static int encrypt_lock_store(FbLockState lock, unsigned char* bdata) { + unsigned int p = 0; + int ret; + int salt_len = generate_salt(bdata); + if (salt_len < 0) + return -1; + + //salt_len cannot be longer than endata block size. + if (salt_len >= ENDATA_LEN) + salt_len = ENDATA_LEN - 1; + + p = ENDATA_LEN - 1; + + //Set lock value + *(bdata + p) = lock; + + caam_open(); + ret = caam_gen_blob((uint32_t)(ulong)bdata, + (uint32_t)(ulong)bdata + ROUND(ENDATA_LEN, ARCH_DMA_MINALIGN), + ENDATA_LEN); + if (ret != 0) { + printf("error in caam_gen_blob:0x%x\n", ret); + return -1; + } + + +#ifdef FASTBOOT_LOCK_DEBUG + int i = 0; + FB_DEBUG("encrypt plain_text:\n"); + for (i = 0; i < ENDATA_LEN; i++) { + FB_DEBUG("0x%2x\t", *(bdata+i)); + if (i % 16 == 0) + printf("\n"); + } + printf("\nto:\n"); + for (i=0; i < ENDATA_LEN + 48; i++) { + FB_DEBUG("0x%2x\t", *(bdata + ENDATA_LEN + i)); + if (i % 16 == 0) + printf("\n"); + } + printf("\n"); + +#endif + //protect value + *(bdata + p) = 0xff; + return 0; +} + +#endif + +static char mmc_dev_part[16]; +static char* get_mmc_part(int part) { + u32 dev_no = mmc_get_env_dev(); + sprintf(mmc_dev_part,"%x:%x",dev_no, part); + return mmc_dev_part; +} + +static inline void set_lock_disable_data(unsigned char* bdata) { + *(bdata + SECTOR_SIZE -1) = 0; +} + +/* + * The enabling value is stored in the last byte of target partition. + */ +static inline unsigned char lock_enable_parse(unsigned char* bdata) { + FB_DEBUG("lock_enable_parse: 0x%x\n", *(bdata + SECTOR_SIZE -1)); + if (*(bdata + SECTOR_SIZE -1) >= FASTBOOT_UL_NUM) + return FASTBOOT_UL_ERROR; + else + return *(bdata + SECTOR_SIZE -1); +} + +static FbLockState g_lockstat = FASTBOOT_UNLOCK; + +#ifdef CONFIG_IMX_TRUSTY_OS +FbLockState fastboot_get_lock_stat(void) { + uint8_t l_status; + int ret; + /* + * If Trusty OS not flashed, then must return + * unlock status to make device been able + * to flash Trusty OS binary. + */ +#ifndef CONFIG_ARM64 + if (!tos_flashed) + return FASTBOOT_UNLOCK; +#endif + ret = trusty_read_lock_state(&l_status); + if (ret < 0) + return g_lockstat; + else + return l_status; + +} + +int fastboot_set_lock_stat(FbLockState lock) { + int ret; + /* + * If Trusty OS not flashed, we must prevent set lock + * status. Due the Trusty IPC won't work here. + */ +#ifndef CONFIG_ARM64 + if (!tos_flashed) + return 0; +#endif + ret = trusty_write_lock_state(lock); + if (ret < 0) { + printf("cannot set lock status due Trusty return %d\n", ret); + return ret; + } + return 0; +} +#else + +/* + * Set status of the lock&unlock to FSL_FASTBOOT_FB_PART + * Currently use the very first Byte of FSL_FASTBOOT_FB_PART + * to store the fastboot lock&unlock status + */ +int fastboot_set_lock_stat(FbLockState lock) { + struct blk_desc *fs_dev_desc; + struct disk_partition fs_partition; + unsigned char *bdata; + int mmc_id; + int status, ret; + + bdata = (unsigned char *)memalign(ARCH_DMA_MINALIGN, SECTOR_SIZE); + if (bdata == NULL) + goto fail2; + memset(bdata, 0, SECTOR_SIZE); + + mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_FBMISC); + if (mmc_id < 0) { + printf("%s: error in get mmc part\n", __FUNCTION__); + ret = -1; + goto fail; + } + status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV, + get_mmc_part(mmc_id), + &fs_dev_desc, &fs_partition, 1); + if (status < 0) { + printf("%s:error in getdevice partition.\n", __FUNCTION__); + ret = -1; + goto fail; + } + + status = encrypt_lock_store(lock, bdata); + if (status < 0) { + ret = -1; + goto fail; + } + status = blk_dwrite(fs_dev_desc, fs_partition.start, 1, bdata); + if (!status) { + printf("%s:error in block write.\n", __FUNCTION__); + ret = -1; + goto fail; + } + ret = 0; +fail: + free(bdata); + return ret; +fail2: + g_lockstat = lock; + return 0; +} + +FbLockState fastboot_get_lock_stat(void) { + struct blk_desc *fs_dev_desc; + struct disk_partition fs_partition; + unsigned char *bdata; + int mmc_id; + FbLockState ret; + /* uboot used by uuu will boot from USB, always return UNLOCK state */ + if (is_boot_from_usb()) + return g_lockstat; + + bdata = (unsigned char *)memalign(ARCH_DMA_MINALIGN, SECTOR_SIZE); + if (bdata == NULL) + return g_lockstat; + + int status; + mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_FBMISC); + if (mmc_id < 0) { + printf("%s: error in get mmc part\n", __FUNCTION__); + ret = g_lockstat; + goto fail; + } + status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV, + get_mmc_part(mmc_id), + &fs_dev_desc, &fs_partition, 1); + + if (status < 0) { + printf("%s:error in getdevice partition.\n", __FUNCTION__); + ret = g_lockstat; + goto fail; + } + + status = blk_dread(fs_dev_desc, fs_partition.start, 1, bdata); + if (!status) { + printf("%s:error in block read.\n", __FUNCTION__); + ret = FASTBOOT_LOCK_ERROR; + goto fail; + } + + ret = decrypt_lock_store(bdata); +fail: + free(bdata); + return ret; +} +#endif + + +/* Return the last byte of of FSL_FASTBOOT_PR_DATA + * which is managed by PresistDataService + */ + +#ifdef CONFIG_ENABLE_LOCKSTATUS_SUPPORT +//Brillo has no presist data partition +FbLockEnableResult fastboot_lock_enable(void) { + return FASTBOOT_UL_ENABLE; +} +void set_fastboot_lock_disable(void) { +} +#else +void set_fastboot_lock_disable(void) { + struct blk_desc *fs_dev_desc; + struct disk_partition fs_partition; + unsigned char *bdata; + int mmc_id; + + bdata = (unsigned char *)memalign(ALIGN_BYTES, SECTOR_SIZE); + if (bdata == NULL) + return; + set_lock_disable_data(bdata); + int status; + mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_PRDATA); + if (mmc_id < 0) { + printf("%s: error in get mmc part\n", __FUNCTION__); + goto fail; + } + status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV, + get_mmc_part(mmc_id), + &fs_dev_desc, &fs_partition, 1); + if (status < 0) { + printf("%s:error in getdevice partition.\n", __FUNCTION__); + goto fail; + } + + lbaint_t target_block = fs_partition.start + fs_partition.size - 1; + status = blk_dwrite(fs_dev_desc, target_block, 1, bdata); + if (!status) { + printf("%s: error in block read\n", __FUNCTION__); + goto fail; + } + +fail: + free(bdata); + return; + +} +FbLockEnableResult fastboot_lock_enable() { + struct blk_desc *fs_dev_desc; + struct disk_partition fs_partition; + unsigned char *bdata; + int mmc_id; + FbLockEnableResult ret; + + bdata = (unsigned char *)memalign(ALIGN_BYTES, SECTOR_SIZE); + if (bdata == NULL) + return FASTBOOT_UL_ERROR; + int status; + mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_PRDATA); + if (mmc_id < 0) { + printf("%s: error in get mmc part\n", __FUNCTION__); + ret = FASTBOOT_UL_ERROR; + goto fail; + } + status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV, + get_mmc_part(mmc_id), + &fs_dev_desc, &fs_partition, 1); + if (status < 0) { + printf("%s:error in getdevice partition.\n", __FUNCTION__); + ret = FASTBOOT_UL_ERROR; + goto fail; + } + + //The data is stored in the last blcok of this partition. + lbaint_t target_block = fs_partition.start + fs_partition.size - 1; + status = blk_dread(fs_dev_desc, target_block, 1, bdata); + if (!status) { + printf("%s: error in block read\n", __FUNCTION__); + ret = FASTBOOT_UL_ERROR; + goto fail; + } + int i = 0; + FB_DEBUG("\n PRIST last sector is:\n"); + for (i = 0; i < SECTOR_SIZE; i++) { + FB_DEBUG("0x%x ", *(bdata + i)); + if (i % 32 == 0) + FB_DEBUG("\n"); + } + FB_DEBUG("\n"); + ret = lock_enable_parse(bdata); +fail: + free(bdata); + return ret; + +} +#endif + +int display_lock(FbLockState lock, int verify) { + struct stdio_dev *disp; + disp = stdio_get_by_name("vga"); + if (disp != NULL) { + if (lock == FASTBOOT_UNLOCK) { + disp->puts(disp, "\n============= NOTICE ============\n"); + disp->puts(disp, "| |\n"); + disp->puts(disp, "| Your device is NOT locked. |\n"); + disp->puts(disp, "| |\n"); + disp->puts(disp, "=================================\n"); + } else { + if (verify == -1) { + disp->puts(disp, "\n============= NOTICE ============\n"); + disp->puts(disp, "| |\n"); + disp->puts(disp, "| Your device is NOT protected. |\n"); + disp->puts(disp, "| |\n"); + disp->puts(disp, "=================================\n"); + } else if (verify == 1) { + disp->puts(disp, "\n============= NOTICE ============\n"); + disp->puts(disp, "| |\n"); + disp->puts(disp, "| Boot verify failed! |\n"); + disp->puts(disp, "| |\n"); + disp->puts(disp, "=================================\n"); + } + } + return 0; + } else + printf("not found VGA disp console.\n"); + + return -1; + +} + +int fastboot_wipe_data_partition(void) +{ + struct blk_desc *fs_dev_desc; + struct disk_partition fs_partition; + int status; + int mmc_id; + mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_DATA); + if (mmc_id < 0) { + printf("%s: error in get mmc part\n", __FUNCTION__); + return -1; + } + status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV, + get_mmc_part(mmc_id), &fs_dev_desc, &fs_partition, 1); + if (status < 0) { + printf("error in get device partition for wipe /data\n"); + return -1; + } + status = blk_derase(fs_dev_desc, fs_partition.start , fs_partition.size ); + if (status != fs_partition.size ) { + printf("erase not complete\n"); + return -1; + } + mdelay(2000); + + return 0; +} + +void fastboot_wipe_all(void) { + struct blk_desc *fs_dev_desc; + struct disk_partition fs_partition; + int status; + int mmc_id; + mmc_id = fastboot_flash_find_index(FASTBOOT_PARTITION_GPT); + if (mmc_id < 0) { + printf("%s: error in get mmc part\n", __FUNCTION__); + return; + } + status = blk_get_device_part_str(FSL_FASTBOOT_FB_DEV, + get_mmc_part(mmc_id), &fs_dev_desc, &fs_partition, 1); + if (status < 0) { + printf("error in get device partition for wipe user partition\n"); + return; + } + status = blk_derase(fs_dev_desc, fs_partition.start , fs_partition.size ); + if (status != fs_partition.size ) { + printf("erase not complete\n"); + return; + } + printf("fastboot wiped all.\n"); +} diff --git a/drivers/fastboot/fb_fsl/fastboot_lock_unlock.h b/drivers/fastboot/fb_fsl/fastboot_lock_unlock.h new file mode 100644 index 0000000000..06c69ca88e --- /dev/null +++ b/drivers/fastboot/fb_fsl/fastboot_lock_unlock.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FASTBOOT_LOCK_UNLOCK_H +#define FASTBOOT_LOCK_UNLOCK_H + +#define ALIGN_BYTES 64 /*armv7 cache line need 64 bytes aligned */ + +//#define FASTBOOT_LOCK_DEBUG +#ifdef CONFIG_FSL_CAAM_KB +#define FASTBOOT_ENCRYPT_LOCK +#endif + +#ifdef FASTBOOT_LOCK_DEBUG +#define FB_DEBUG(format, ...) printf(format, ##__VA_ARGS__) +#else +#define FB_DEBUG(format, ...) +#endif + +typedef enum { + FASTBOOT_UNLOCK, + FASTBOOT_LOCK, + FASTBOOT_LOCK_ERROR, + FASTBOOT_LOCK_NUM +}FbLockState; + +typedef enum { + FASTBOOT_UL_DISABLE, + FASTBOOT_UL_ENABLE, + FASTBOOT_UL_ERROR, + FASTBOOT_UL_NUM +}FbLockEnableResult; + +FbLockState fastboot_get_lock_stat(void); + +int fastboot_set_lock_stat(FbLockState lock); + +int fastboot_wipe_data_partition(void); +void fastboot_wipe_all(void); + +FbLockEnableResult fastboot_lock_enable(void); +void set_fastboot_lock_disable(void); + +int display_lock(FbLockState lock, int verify); + +bool valid_tos(void); +#endif diff --git a/drivers/fastboot/fb_fsl/fb_fsl_boot.c b/drivers/fastboot/fb_fsl/fb_fsl_boot.c new file mode 100644 index 0000000000..7877207adb --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_boot.c @@ -0,0 +1,1051 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../lib/avb/fsl/utils.h" + +#ifdef CONFIG_AVB_SUPPORT +#include +#include +#endif + +#ifdef CONFIG_ANDROID_THINGS_SUPPORT +#include +#include +#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 +#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 [ mmc0 | mmc1 [ ] ] */ +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", + "[ | mmc0 | mmc1 | mmc2 | mmcX] []\n " + "- boot application image stored in memory or mmc\n" + "\t'addr' should be the address of boot image " + "which is zImage+ramdisk.img\n" + "\t'mmcX' is the mmc device you store your boot.img, " + "which will read the boot.img from 1M offset('/boot' partition)\n" + "\t 'partition' (optional) is the partition id of your device, " + "if no partition give, will going to 'boot' partition\n" +); +#endif /* CONFIG_AVB_SUPPORT */ +#endif /* CONFIG_CMD_BOOTA */ diff --git a/drivers/fastboot/fb_fsl/fb_fsl_command.c b/drivers/fastboot/fb_fsl/fb_fsl_command.c new file mode 100644 index 0000000000..71e21ebe97 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_command.c @@ -0,0 +1,898 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_ANDROID_RECOVERY +#include +#endif + +#ifdef CONFIG_BCB_SUPPORT +#include "bcb.h" +#endif + +#ifdef CONFIG_AVB_SUPPORT +#include +#include +#endif + +#ifdef CONFIG_ANDROID_THINGS_SUPPORT +#include +#include +#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 +#endif + +#include "fb_fsl_common.h" + +#define EP_BUFFER_SIZE 4096 + +/** + * fastboot_bytes_received - number of bytes received in the current download + */ +static u32 fastboot_bytes_received; + +/** + * fastboot_bytes_expected - number of bytes expected in the current download + */ +static u32 fastboot_bytes_expected; + + +/* Write the bcb with fastboot bootloader commands */ +static void enable_fastboot_command(void) +{ +#ifdef CONFIG_BCB_SUPPORT + char fastboot_command[32] = {0}; + strncpy(fastboot_command, FASTBOOT_BCB_CMD, 31); + bcb_write_command(fastboot_command); +#endif +} + +/* Get the Boot mode from BCB cmd or Key pressed */ +static FbBootMode fastboot_get_bootmode(void) +{ + int boot_mode = BOOTMODE_NORMAL; +#ifdef CONFIG_ANDROID_RECOVERY + if(is_recovery_key_pressing()) { + boot_mode = BOOTMODE_RECOVERY_KEY_PRESSED; + return boot_mode; + } +#endif +#ifdef CONFIG_BCB_SUPPORT + int ret = 0; + char command[32]; + ret = bcb_read_command(command); + if (ret < 0) { + printf("read command failed\n"); + return boot_mode; + } + if (!strcmp(command, FASTBOOT_BCB_CMD)) { + boot_mode = BOOTMODE_FASTBOOT_BCB_CMD; + } +#ifdef CONFIG_ANDROID_RECOVERY + else if (!strcmp(command, RECOVERY_BCB_CMD)) { + boot_mode = BOOTMODE_RECOVERY_BCB_CMD; + } +#endif + + /* Clean the mode once its read out, + no matter what in the mode string */ + memset(command, 0, 32); + bcb_write_command(command); +#endif + return boot_mode; +} + +/* export to lib_arm/board.c */ +void fastboot_run_bootmode(void) +{ + FbBootMode boot_mode = fastboot_get_bootmode(); + switch(boot_mode){ + case BOOTMODE_FASTBOOT_BCB_CMD: + /* Make the boot into fastboot mode*/ + puts("Fastboot: Got bootloader commands!\n"); + run_command("fastboot 0", 0); + break; +#ifdef CONFIG_ANDROID_RECOVERY + case BOOTMODE_RECOVERY_BCB_CMD: + case BOOTMODE_RECOVERY_KEY_PRESSED: + /* Make the boot into recovery mode */ + puts("Fastboot: Got Recovery key pressing or recovery commands!\n"); + board_recovery_setup(); + break; +#endif + default: + /* skip special mode boot*/ + puts("Fastboot: Normal\n"); + break; + } +} + + + +/** + * okay() - Send bare OKAY response + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + * + * Send a bare OKAY fastboot response. This is used where the command is + * valid, but all the work is done after the response has been sent (e.g. + * boot, reboot etc.) + */ +static void okay(char *cmd_parameter, char *response) +{ + fastboot_okay(NULL, response); +} + +/** + * getvar() - Read a config/version variable + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void getvar(char *cmd_parameter, char *response) +{ + fastboot_getvar(cmd_parameter, response); +} + +/** + * reboot_bootloader() - Sets reboot bootloader flag. + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void reboot_bootloader(char *cmd_parameter, char *response) +{ + enable_fastboot_command(); + + if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER)) + fastboot_fail("Cannot set reboot flag", response); + else + fastboot_okay(NULL, response); +} + +static void upload(char *cmd_parameter, char *response) +{ + if (!fastboot_bytes_received || fastboot_bytes_received > (EP_BUFFER_SIZE * 32)) { + fastboot_fail("", response); + return; + } + + printf("Will upload %d bytes.\n", fastboot_bytes_received); + snprintf(response, FASTBOOT_RESPONSE_LEN, "DATA%08x", fastboot_bytes_received); + fastboot_tx_write_more(response); + + fastboot_tx_write((const char *)(fastboot_buf_addr), fastboot_bytes_received); + + snprintf(response,FASTBOOT_RESPONSE_LEN, "OKAY"); + fastboot_tx_write_more(response); + + fastboot_none_resp(response); +} + +/** + * fastboot_download() - Start a download transfer from the client + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void download(char *cmd_parameter, char *response) +{ + char *tmp; + + if (!cmd_parameter) { + fastboot_fail("Expected command parameter", response); + return; + } + fastboot_bytes_received = 0; + fastboot_bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16); + if (fastboot_bytes_expected == 0) { + fastboot_fail("Expected nonzero image size", response); + return; + } + /* + * Nothing to download yet. Response is of the form: + * [DATA|FAIL]$cmd_parameter + * + * where cmd_parameter is an 8 digit hexadecimal number + */ + if (fastboot_bytes_expected > fastboot_buf_size) { + fastboot_fail(cmd_parameter, response); + } else { + printf("Starting download of %d bytes\n", + fastboot_bytes_expected); + fastboot_response("DATA", response, "%s", cmd_parameter); + } +} + +/** + * fastboot_data_remaining() - return bytes remaining in current transfer + * + * Return: Number of bytes left in the current download + */ +u32 fastboot_data_remaining(void) +{ + if (fastboot_bytes_received >= fastboot_bytes_expected) + return 0; + + return fastboot_bytes_expected - fastboot_bytes_received; +} + +/** + * fastboot_data_download() - Copy image data to fastboot_buf_addr. + * + * @fastboot_data: Pointer to received fastboot data + * @fastboot_data_len: Length of received fastboot data + * @response: Pointer to fastboot response buffer + * + * Copies image data from fastboot_data to fastboot_buf_addr. Writes to + * response. fastboot_bytes_received is updated to indicate the number + * of bytes that have been transferred. + * + * On completion sets image_size and ${filesize} to the total size of the + * downloaded image. + */ +void fastboot_data_download(const void *fastboot_data, + unsigned int fastboot_data_len, + char *response) +{ +#define BYTES_PER_DOT 0x20000 + u32 pre_dot_num, now_dot_num; + + if (fastboot_data_len == 0 || + (fastboot_bytes_received + fastboot_data_len) > + fastboot_bytes_expected) { + fastboot_fail("Received invalid data length", + response); + return; + } + /* Download data to fastboot_buf_addr */ + memcpy(fastboot_buf_addr + fastboot_bytes_received, + fastboot_data, fastboot_data_len); + + pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT; + fastboot_bytes_received += fastboot_data_len; + now_dot_num = fastboot_bytes_received / BYTES_PER_DOT; + + if (pre_dot_num != now_dot_num) { + putc('.'); + if (!(now_dot_num % 74)) + putc('\n'); + } + *response = '\0'; +} + +/** + * fastboot_data_complete() - Mark current transfer complete + * + * @response: Pointer to fastboot response buffer + * + * Set image_size and ${filesize} to the total size of the downloaded image. + */ +void fastboot_data_complete(char *response) +{ + /* Download complete. Respond with "OKAY" */ + fastboot_okay(NULL, response); + printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received); + env_set_hex("filesize", fastboot_bytes_received); + env_set_hex("fastboot_bytes", fastboot_bytes_received); + fastboot_bytes_expected = 0; +} + +#if defined(CONFIG_FASTBOOT_LOCK) +static int partition_table_valid(void) +{ + int status, mmc_no; + struct blk_desc *dev_desc; +#if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_ARM64) + /* Prevent other partition accessing when no TOS flashed. */ + if (!tos_flashed) + return 0; +#endif + struct disk_partition info; + mmc_no = fastboot_devinfo.dev_id; + dev_desc = blk_get_dev("mmc", mmc_no); + if (dev_desc) + status = part_get_info(dev_desc, 1, &info); + else + status = -1; + return (status == 0); +} + +static void wipe_all_userdata(void) +{ + char response[FASTBOOT_RESPONSE_LEN]; + + /* Erase all user data */ + printf("Start userdata wipe process....\n"); + /* Erase /data partition */ + fastboot_wipe_data_partition(); + +#if defined (CONFIG_ANDROID_SUPPORT) || defined (CONFIG_ANDROID_AUTO_SUPPORT) + /* Erase the misc partition. */ + process_erase_mmc(FASTBOOT_PARTITION_MISC, response); +#endif + +#ifndef CONFIG_ANDROID_AB_SUPPORT + /* Erase the cache partition for legacy imx6/7 */ + process_erase_mmc(FASTBOOT_PARTITION_CACHE, response); +#endif + /* The unlock permissive flag is set by user and should be wiped here. */ + set_fastboot_lock_disable(); + + +#if defined(AVB_RPMB) && !defined(CONFIG_IMX_TRUSTY_OS) + printf("Start stored_rollback_index wipe process....\n"); + rbkidx_erase(); + printf("Wipe stored_rollback_index completed.\n"); +#endif + printf("Wipe userdata completed.\n"); +} + +static FbLockState do_fastboot_unlock(bool force) +{ + int status; + + if (fastboot_get_lock_stat() == FASTBOOT_UNLOCK) { + printf("The device is already unlocked\n"); + return FASTBOOT_UNLOCK; + } + if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) { + printf("It is able to unlock device. %d\n",fastboot_lock_enable()); + status = fastboot_set_lock_stat(FASTBOOT_UNLOCK); + if (status < 0) + return FASTBOOT_LOCK_ERROR; + + wipe_all_userdata(); + + } else { + printf("It is not able to unlock device."); + return FASTBOOT_LOCK_ERROR; + } + + return FASTBOOT_UNLOCK; +} + +static FbLockState do_fastboot_lock(void) +{ + int status; + + if (fastboot_get_lock_stat() == FASTBOOT_LOCK) { + printf("The device is already locked\n"); + return FASTBOOT_LOCK; + } + status = fastboot_set_lock_stat(FASTBOOT_LOCK); + if (status < 0) + return FASTBOOT_LOCK_ERROR; + + wipe_all_userdata(); + + return FASTBOOT_LOCK; +} + +static bool endswith(char* s, char* subs) { + if (!s || !subs) + return false; + uint32_t len = strlen(s); + uint32_t sublen = strlen(subs); + if (len < sublen) { + return false; + } + if (strncmp(s + len - sublen, subs, sublen)) { + return false; + } + return true; +} + +static void flashing(char *cmd, char *response) +{ + FbLockState status; + FbLockEnableResult result; + if (endswith(cmd, "lock_critical")) { + strcpy(response, "OKAY"); + } +#ifdef CONFIG_AVB_ATX + else if (endswith(cmd, FASTBOOT_AVB_AT_PERM_ATTR)) { + if (avb_atx_fuse_perm_attr(fastboot_buf_addr, fastboot_bytes_received)) + strcpy(response, "FAILInternal error!"); + else + strcpy(response, "OKAY"); + } else if (endswith(cmd, FASTBOOT_AT_GET_UNLOCK_CHALLENGE)) { + if (avb_atx_get_unlock_challenge(fsl_avb_ops.atx_ops, + fastboot_buf_addr, &fastboot_bytes_received)) + strcpy(response, "FAILInternal error!"); + else + strcpy(response, "OKAY"); + } else if (endswith(cmd, FASTBOOT_AT_UNLOCK_VBOOT)) { + if (at_unlock_vboot_is_disabled()) { + printf("unlock vboot already disabled, can't unlock the device!\n"); + strcpy(response, "FAILunlock vboot already disabled!."); + } else { +#ifdef CONFIG_AT_AUTHENTICATE_UNLOCK + if (avb_atx_verify_unlock_credential(fsl_avb_ops.atx_ops, + fastboot_buf_addr)) + strcpy(response, "FAILIncorrect unlock credential!"); + else { +#endif + status = do_fastboot_unlock(true); + if (status != FASTBOOT_LOCK_ERROR) + strcpy(response, "OKAY"); + else + strcpy(response, "FAILunlock device failed."); +#ifdef CONFIG_AT_AUTHENTICATE_UNLOCK + } +#endif + } + } else if (endswith(cmd, FASTBOOT_AT_LOCK_VBOOT)) { + if (perm_attr_are_fused()) { + status = do_fastboot_lock(); + if (status != FASTBOOT_LOCK_ERROR) + strcpy(response, "OKAY"); + else + strcpy(response, "FAILlock device failed."); + } else + strcpy(response, "FAILpermanent attributes not fused!"); + } else if (endswith(cmd, FASTBOOT_AT_DISABLE_UNLOCK_VBOOT)) { + /* This command can only be called after 'oem at-lock-vboot' */ + status = fastboot_get_lock_stat(); + if (status == FASTBOOT_LOCK) { + if (at_unlock_vboot_is_disabled()) { + printf("unlock vboot already disabled!\n"); + strcpy(response, "OKAY"); + } + else { + if (!at_disable_vboot_unlock()) + strcpy(response, "OKAY"); + else + strcpy(response, "FAILdisable unlock vboot fail!"); + } + } else + strcpy(response, "FAILplease lock the device first!"); + } +#endif /* CONFIG_AVB_ATX */ +#ifdef CONFIG_ANDROID_THINGS_SUPPORT + else if (endswith(cmd, FASTBOOT_BOOTLOADER_VBOOT_KEY)) { + strcpy(response, "OKAY"); + } +#endif /* CONFIG_ANDROID_THINGS_SUPPORT */ +#ifdef CONFIG_IMX_TRUSTY_OS + else if (endswith(cmd, FASTBOOT_GET_CA_REQ)) { + uint8_t *ca_output; + uint32_t ca_length, cp_length; + if (trusty_atap_get_ca_request(fastboot_buf_addr, fastboot_bytes_received, + &(ca_output), &ca_length)) { + printf("ERROR get_ca_request failed!\n"); + strcpy(response, "FAILInternal error!"); + } else { + cp_length = min((uint32_t)CONFIG_FASTBOOT_BUF_SIZE, ca_length); + memcpy(fastboot_buf_addr, ca_output, cp_length); + fastboot_bytes_received = ca_length; + strcpy(response, "OKAY"); + } + + } else if (endswith(cmd, FASTBOOT_SET_CA_RESP)) { + if (trusty_atap_set_ca_response(fastboot_buf_addr, fastboot_bytes_received)) { + printf("ERROR set_ca_response failed!\n"); + strcpy(response, "FAILInternal error!"); + } else + strcpy(response, "OKAY"); + } else if (endswith(cmd, FASTBOOT_SET_RSA_ATTESTATION_KEY)) { + if (trusty_set_attestation_key(fastboot_buf_addr, + fastboot_bytes_received, + KM_ALGORITHM_RSA)) { + printf("ERROR set rsa attestation key failed!\n"); + strcpy(response, "FAILInternal error!"); + } else { + printf("Set rsa attestation key successfully!\n"); + strcpy(response, "OKAY"); + } + } else if (endswith(cmd, FASTBOOT_SET_EC_ATTESTATION_KEY)) { + if (trusty_set_attestation_key(fastboot_buf_addr, + fastboot_bytes_received, + KM_ALGORITHM_EC)) { + printf("ERROR set ec attestation key failed!\n"); + strcpy(response, "FAILInternal error!"); + } else { + printf("Set ec attestation key successfully!\n"); + strcpy(response, "OKAY"); + } + } else if (endswith(cmd, FASTBOOT_APPEND_RSA_ATTESTATION_CERT)) { + if (trusty_append_attestation_cert_chain(fastboot_buf_addr, + fastboot_bytes_received, + KM_ALGORITHM_RSA)) { + printf("ERROR append rsa attestation cert chain failed!\n"); + strcpy(response, "FAILInternal error!"); + } else { + printf("Append rsa attestation key successfully!\n"); + strcpy(response, "OKAY"); + } + } else if (endswith(cmd, FASTBOOT_APPEND_EC_ATTESTATION_CERT)) { + if (trusty_append_attestation_cert_chain(fastboot_buf_addr, + fastboot_bytes_received, + KM_ALGORITHM_EC)) { + printf("ERROR append ec attestation cert chain failed!\n"); + strcpy(response, "FAILInternal error!"); + } else { + printf("Append ec attestation key successfully!\n"); + strcpy(response, "OKAY"); + } + } +#ifndef CONFIG_AVB_ATX + else if (endswith(cmd, FASTBOOT_SET_RPMB_KEY)) { + if (fastboot_set_rpmb_key(fastboot_buf_addr, fastboot_bytes_received)) { + printf("ERROR set rpmb key failed!\n"); + strcpy(response, "FAILset rpmb key failed!"); + } else + strcpy(response, "OKAY"); + } else if (endswith(cmd, FASTBOOT_SET_RPMB_RANDOM_KEY)) { + if (fastboot_set_rpmb_random_key()) { + printf("ERROR set rpmb random key failed!\n"); + strcpy(response, "FAILset rpmb random key failed!"); + } else + strcpy(response, "OKAY"); + } else if (endswith(cmd, FASTBOOT_SET_VBMETA_PUBLIC_KEY)) { + if (avb_set_public_key(fastboot_buf_addr, + fastboot_bytes_received)) + strcpy(response, "FAILcan't set public key!"); + else + strcpy(response, "OKAY"); + } +#endif /* !CONFIG_AVB_ATX */ +#endif /* CONFIG_IMX_TRUSTY_OS */ + else if (endswith(cmd, "unlock_critical")) { + strcpy(response, "OKAY"); + } else if (endswith(cmd, "unlock")) { + printf("flashing unlock.\n"); +#ifdef CONFIG_AVB_ATX + /* We should do nothing here For Android Things which + * enables the authenticated unlock feature. + */ + strcpy(response, "OKAY"); +#else + status = do_fastboot_unlock(false); + if (status != FASTBOOT_LOCK_ERROR) + strcpy(response, "OKAY"); + else + strcpy(response, "FAILunlock device failed."); +#endif + } else if (endswith(cmd, "lock")) { +#ifdef CONFIG_AVB_ATX + /* We should do nothing here For Android Things which + * enables the at-lock-vboot feature. + */ + strcpy(response, "OKAY"); +#else + printf("flashing lock.\n"); + status = do_fastboot_lock(); + if (status != FASTBOOT_LOCK_ERROR) + strcpy(response, "OKAY"); + else + strcpy(response, "FAILlock device failed."); +#endif + } else if (endswith(cmd, "get_unlock_ability")) { + result = fastboot_lock_enable(); + if (result == FASTBOOT_UL_ENABLE) { + fastboot_tx_write_more("INFO1"); + strcpy(response, "OKAY"); + } else if (result == FASTBOOT_UL_DISABLE) { + fastboot_tx_write_more("INFO0"); + strcpy(response, "OKAY"); + } else { + printf("flashing get_unlock_ability fail!\n"); + strcpy(response, "FAILget unlock ability failed."); + } + } else { + printf("Unknown flashing command:%s\n", cmd); + strcpy(response, "FAILcommand not defined"); + } + fastboot_tx_write_more(response); + + /* Must call fastboot_none_resp before returning from the dispatch function + * which uses fastboot_tx_write_more + */ + fastboot_none_resp(response); +} +#endif /* CONFIG_FASTBOOT_LOCK */ + +#ifdef CONFIG_AVB_SUPPORT +static void set_active_avb(char *cmd, char *response) +{ + AvbIOResult ret; + int slot = 0; + + if (!cmd) { + pr_err("missing slot suffix\n"); + fastboot_fail("missing slot suffix", response); + return; + } + + slot = slotidx_from_suffix(cmd); + + if (slot < 0) { + fastboot_fail("err slot suffix", response); + return; + } + + ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot); + if (ret != AVB_IO_RESULT_OK) + fastboot_fail("avb IO error", response); + else + fastboot_okay(NULL, response); + + return; +} +#endif /*CONFIG_AVB_SUPPORT*/ + +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) +static void flash(char *cmd, char *response) +{ + if (!cmd) { + pr_err("missing partition name"); + fastboot_fail("missing partition name", response); + return; + } + + /* Always enable image flash for Android Things. */ +#if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX) + int status; + status = fastboot_get_lock_stat(); + + if (status == FASTBOOT_LOCK) { + pr_err("device is LOCKed!\n"); + fastboot_fail("device is locked.", response); + return; + + } else if (status == FASTBOOT_LOCK_ERROR) { + pr_err("write lock status into device!\n"); + fastboot_set_lock_stat(FASTBOOT_LOCK); + fastboot_fail("device is locked.", response); + return; + } +#endif + + fastboot_process_flash(cmd, fastboot_buf_addr, + fastboot_bytes_received, response); + +#if defined(CONFIG_FASTBOOT_LOCK) + if (strncmp(cmd, "gpt", 3) == 0) { + int gpt_valid = 0; + gpt_valid = partition_table_valid(); + /* If gpt is valid, load partitons table into memory. + So if the next command is "fastboot reboot bootloader", + it can find the "misc" partition to r/w. */ + if(gpt_valid) { + fastboot_load_partitions(); + /* Unlock device if the gpt is valid */ + do_fastboot_unlock(true); + } + } + +#endif +} + +static void erase(char *cmd, char *response) +{ + if (!cmd) { + pr_err("missing partition name"); + fastboot_fail("missing partition name", response); + return; + } + +#if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX) + FbLockState status; + status = fastboot_get_lock_stat(); + if (status == FASTBOOT_LOCK) { + pr_err("device is LOCKed!\n"); + fastboot_fail("device is locked.", response); + return; + } else if (status == FASTBOOT_LOCK_ERROR) { + pr_err("write lock status into device!\n"); + fastboot_set_lock_stat(FASTBOOT_LOCK); + fastboot_fail("device is locked.", response); + return; + } +#endif + fastboot_process_erase(cmd, response); +} +#endif + +#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) +/** + * run_ucmd() - Execute the UCmd command + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void run_ucmd(char *cmd_parameter, char *response) +{ + if (!cmd_parameter) { + pr_err("missing slot suffix\n"); + fastboot_fail("missing command", response); + return; + } + if(run_command(cmd_parameter, 0)) { + fastboot_fail("", response); + } else { + fastboot_okay(NULL, response); + /* cmd may impact fastboot related environment*/ + fastboot_setup(); + } +} + +static char g_a_cmd_buff[64]; + +void fastboot_acmd_complete(void) +{ + run_command(g_a_cmd_buff, 0); +} + +/** + * run_acmd() - Execute the ACmd command + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void run_acmd(char *cmd_parameter, char *response) +{ + if (!cmd_parameter) { + pr_err("missing slot suffix\n"); + fastboot_fail("missing command", response); + return; + } + + if (strlen(cmd_parameter) >= sizeof(g_a_cmd_buff)) { + pr_err("input acmd is too long\n"); + fastboot_fail("too long command", response); + return; + } + + strcpy(g_a_cmd_buff, cmd_parameter); + fastboot_okay(NULL, response); +} +#endif + +static const struct { + const char *command; + void (*dispatch)(char *cmd_parameter, char *response); +} commands[FASTBOOT_COMMAND_COUNT] = { + [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] = { + .command = "reboot-bootloader", + .dispatch = reboot_bootloader, + }, + [FASTBOOT_COMMAND_UPLOAD] = { + .command = "upload", + .dispatch = upload, + }, + [FASTBOOT_COMMAND_GETSTAGED] = { + .command = "get_staged", + .dispatch = upload, + }, +#if defined(CONFIG_FASTBOOT_LOCK) + [FASTBOOT_COMMAND_FLASHING] = { + .command = "flashing", + .dispatch = flashing, + }, + [FASTBOOT_COMMAND_OEM] = { + .command = "oem", + .dispatch = flashing, + }, +#endif +#ifdef CONFIG_AVB_SUPPORT + [FASTBOOT_COMMAND_SETACTIVE] = { + .command = "set_active", + .dispatch = set_active_avb, + }, +#endif +#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) + [FASTBOOT_COMMAND_UCMD] = { + .command = "UCmd", + .dispatch = run_ucmd, + }, + [FASTBOOT_COMMAND_ACMD] = { + .command ="ACmd", + .dispatch = run_acmd, + }, +#endif + [FASTBOOT_COMMAND_REBOOT] = { + .command = "reboot", + .dispatch = okay, + }, + [FASTBOOT_COMMAND_GETVAR] = { + .command = "getvar", + .dispatch = getvar, + }, + [FASTBOOT_COMMAND_DOWNLOAD] = { + .command = "download", + .dispatch = download, + }, + [FASTBOOT_COMMAND_BOOT] = { + .command = "boot", + .dispatch = okay, + }, + [FASTBOOT_COMMAND_CONTINUE] = { + .command = "continue", + .dispatch = okay, + }, +#ifdef CONFIG_FASTBOOT_FLASH + [FASTBOOT_COMMAND_FLASH] = { + .command = "flash", + .dispatch = flash, + }, + [FASTBOOT_COMMAND_ERASE] = { + .command = "erase", + .dispatch = erase, + }, +#endif +#ifdef CONFIG_AVB_ATX + [FASTBOOT_COMMAND_STAGE] = { + .command = "stage", + .dispatch = download, + }, +#endif +}; + +/** + * fastboot_handle_command - Handle fastboot command + * + * @cmd_string: Pointer to command string + * @response: Pointer to fastboot response buffer + * + * Return: Executed command, or -1 if not recognized + */ +int fastboot_handle_command(char *cmd_string, char *response) +{ + int i; + char *cmd_parameter; + + cmd_parameter = cmd_string; + strsep(&cmd_parameter, ":"); + /* separate cmdstring for "fastboot oem/flashing" with a blank */ + if(cmd_parameter == NULL) + { + cmd_parameter = cmd_string; + strsep(&cmd_parameter, " "); + } + + for (i = 0; i < ARRAY_SIZE(commands); i++) { + if (commands[i].command != NULL && + !strcmp(commands[i].command, cmd_string)) { + if (commands[i].dispatch) { + commands[i].dispatch(cmd_parameter, + response); + return i; + } else { + break; + } + } + } + + pr_err("command %s not recognized.\n", cmd_string); + fastboot_fail("unrecognized command", response); + return -1; +} diff --git a/drivers/fastboot/fb_fsl/fb_fsl_common.c b/drivers/fastboot/fb_fsl/fb_fsl_common.c new file mode 100644 index 0000000000..c65524a668 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_common.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_ANDROID_RECOVERY +#include +#endif + +#ifdef CONFIG_BCB_SUPPORT +#include "bcb.h" +#endif + +#ifdef CONFIG_AVB_SUPPORT +#include +#include +#endif + +#ifdef CONFIG_ANDROID_THINGS_SUPPORT +#include +#include +#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 + +extern int armv7_init_nonsec(void); +extern void trusty_os_init(void); +#endif + +#include "fb_fsl_common.h" + +#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC) +AvbABOps fsl_avb_ab_ops = { + .read_ab_metadata = fsl_read_ab_metadata, + .write_ab_metadata = fsl_write_ab_metadata, + .ops = NULL +}; +#ifdef CONFIG_AVB_ATX +AvbAtxOps fsl_avb_atx_ops = { + .ops = NULL, + .read_permanent_attributes = fsl_read_permanent_attributes, + .read_permanent_attributes_hash = fsl_read_permanent_attributes_hash, +#ifdef CONFIG_IMX_TRUSTY_OS + .set_key_version = fsl_write_rollback_index_rpmb, +#else + .set_key_version = fsl_set_key_version, +#endif + .get_random = fsl_get_random +}; +#endif +AvbOps fsl_avb_ops = { + .ab_ops = &fsl_avb_ab_ops, +#ifdef CONFIG_AVB_ATX + .atx_ops = &fsl_avb_atx_ops, +#endif + .read_from_partition = fsl_read_from_partition_multi, + .write_to_partition = fsl_write_to_partition, +#ifdef CONFIG_AVB_ATX + .validate_vbmeta_public_key = avb_atx_validate_vbmeta_public_key, +#else + .validate_vbmeta_public_key = fsl_validate_vbmeta_public_key_rpmb, +#endif + .read_rollback_index = fsl_read_rollback_index_rpmb, + .write_rollback_index = fsl_write_rollback_index_rpmb, + .read_is_device_unlocked = fsl_read_is_device_unlocked, + .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition, + .get_size_of_partition = fsl_get_size_of_partition +}; +#endif + +int get_block_size(void) { + int dev_no = 0; + struct blk_desc *dev_desc; + + dev_no = fastboot_devinfo.dev_id; + dev_desc = blk_get_dev(fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", dev_no); + if (NULL == dev_desc) { + printf("** Block device %s %d not supported\n", + fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", + dev_no); + return 0; + } + return dev_desc->blksz; +} + +struct fastboot_device_info fastboot_devinfo = {0xff, 0xff}; + +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT +struct fastboot_device_info fastboot_firmwareinfo; +#endif + +/** + * fastboot_none() - Skip the common write operation, nothing output. + * + * @response: Pointer to fastboot response buffer + */ +void fastboot_none_resp(char *response) +{ + *response = 0; +} + +void board_fastboot_setup(void) +{ + static char boot_dev_part[32]; + u32 dev_no; + + switch (get_boot_device()) { + case SD1_BOOT: + case SD2_BOOT: + case SD3_BOOT: + case SD4_BOOT: + case MMC1_BOOT: + case MMC2_BOOT: + case MMC3_BOOT: + case MMC4_BOOT: + dev_no = mmc_get_env_dev(); + sprintf(boot_dev_part,"mmc%d",dev_no); + if (!env_get("fastboot_dev")) + env_set("fastboot_dev", boot_dev_part); + sprintf(boot_dev_part, "boota mmc%d", dev_no); + if (!env_get("bootcmd")) + env_set("bootcmd", boot_dev_part); + break; + case USB_BOOT: + printf("Detect USB boot. Will enter fastboot mode!\n"); + if (!env_get("bootcmd")) + env_set("bootcmd", "fastboot 0"); + break; + default: + if (!env_get("bootcmd")) + printf("unsupported boot devices\n"); + break; + } + + /* add soc type into bootargs */ + if (is_mx6dqp()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx6qp"); + } else if (is_mx6dq()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx6q"); + } else if (is_mx6sdl()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx6dl"); + } else if (is_mx6sx()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx6sx"); + } else if (is_mx6sl()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx6sl"); + } else if (is_mx6ul()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx6ul"); + } else if (is_mx7()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx7d"); + } else if (is_mx7ulp()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx7ulp"); + } else if (is_imx8qm()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx8qm"); + } else if (is_imx8qxp()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx8qxp"); + } else if (is_imx8mq()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx8mq"); + } else if (is_imx8mm()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx8mm"); + } else if (is_imx8mn()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx8mn"); + } else if (is_imx8mp()) { + if (!env_get("soc_type")) + env_set("soc_type", "imx8mp"); + } +} + +#ifdef CONFIG_ANDROID_RECOVERY +void board_recovery_setup(void) +{ +/* boot from current mmc with avb verify */ +#ifdef CONFIG_AVB_SUPPORT + if (!env_get("bootcmd_android_recovery")) + env_set("bootcmd_android_recovery", "boota recovery"); +#else + static char boot_dev_part[32]; + u32 dev_no; + + int bootdev = get_boot_device(); + switch (bootdev) { + case SD1_BOOT: + case SD2_BOOT: + case SD3_BOOT: + case SD4_BOOT: + case MMC1_BOOT: + case MMC2_BOOT: + case MMC3_BOOT: + case MMC4_BOOT: + dev_no = mmc_get_env_dev(); + sprintf(boot_dev_part,"boota mmc%d recovery",dev_no); + if (!env_get("bootcmd_android_recovery")) + env_set("bootcmd_android_recovery", boot_dev_part); + break; + default: + printf("Unsupported bootup device for recovery: dev: %d\n", + bootdev); + return; + } +#endif /* CONFIG_AVB_SUPPORT */ + printf("setup env for recovery..\n"); + env_set("bootcmd", env_get("bootcmd_android_recovery")); +} +#endif /*CONFIG_ANDROID_RECOVERY*/ + +#ifdef CONFIG_IMX_TRUSTY_OS +#ifdef CONFIG_ARM64 +void tee_setup(void) +{ + trusty_ipc_init(); +} + +#else +extern bool tos_flashed; + +void tee_setup(void) +{ + /* load tee from boot1 of eMMC. */ + int mmcc = mmc_get_env_dev(); + struct blk_desc *dev_desc = NULL; + + struct mmc *mmc; + mmc = find_mmc_device(mmcc); + if (!mmc) { + printf("boota: cannot find '%d' mmc device\n", mmcc); + goto fail; + } + + dev_desc = blk_get_dev("mmc", mmcc); + if (NULL == dev_desc) { + printf("** Block device MMC %d not supported\n", mmcc); + goto fail; + } + + /* below was i.MX mmc operation code */ + if (mmc_init(mmc)) { + printf("mmc%d init failed\n", mmcc); + goto fail; + } + + struct fastboot_ptentry *tee_pte; + char *tee_ptn = FASTBOOT_PARTITION_TEE; + tee_pte = fastboot_flash_find_ptn(tee_ptn); + mmc_switch_part(mmc, TEE_HWPARTITION_ID); + if (!tee_pte) { + printf("boota: cannot find tee partition!\n"); + fastboot_flash_dump_ptn(); + } + + if (blk_dread(dev_desc, tee_pte->start, + tee_pte->length, (void *)TRUSTY_OS_ENTRY) < 0) { + printf("Failed to load tee."); + } + mmc_switch_part(mmc, FASTBOOT_MMC_USER_PARTITION_ID); + + tos_flashed = false; + if(!valid_tos()) { + printf("TOS not flashed! Will enter TOS recovery mode. Everything will be wiped!\n"); + fastboot_wipe_all(); + run_command("fastboot 0", 0); + goto fail; + } +#ifdef NON_SECURE_FASTBOOT + armv7_init_nonsec(); + trusty_os_init(); + trusty_ipc_init(); +#endif + +fail: + return; + +} +#endif /* CONFIG_ARM64 */ +#endif /* CONFIG_IMX_TRUSTY_OS */ + +static int _fastboot_setup_dev(int *switched) +{ + char *fastboot_env; + struct fastboot_device_info devinfo;; + fastboot_env = env_get("fastboot_dev"); + + if (fastboot_env) { + if (!strcmp(fastboot_env, "sata")) { + devinfo.type = DEV_SATA; + devinfo.dev_id = 0; + } else if (!strncmp(fastboot_env, "mmc", 3)) { + devinfo.type = DEV_MMC; + if(env_get("target_ubootdev")) + devinfo.dev_id = simple_strtoul(env_get("target_ubootdev"), NULL, 10); + else + devinfo.dev_id = mmc_get_env_dev(); + } else { + return 1; + } + } else { + return 1; + } +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT + /* For imx7ulp, flash m4 images directly to spi nor-flash, M4 will + * run automatically after powered on. For imx8mq, flash m4 images to + * physical partition 'm4_os', m4 will be kicked off by A core. */ + fastboot_firmwareinfo.type = ANDROID_MCU_FRIMWARE_DEV_TYPE; +#endif + + if (switched) { + if (devinfo.type != fastboot_devinfo.type || devinfo.dev_id != fastboot_devinfo.dev_id) + *switched = 1; + else + *switched = 0; + } + + fastboot_devinfo.type = devinfo.type; + fastboot_devinfo.dev_id = devinfo.dev_id; + + return 0; +} + +void fastboot_setup(void) +{ + int sw, ret; + struct tag_serialnr serialnr; + char serial[17]; + + if (!env_get("serial#")) { + get_board_serial(&serialnr); + sprintf(serial, "%08x%08x", serialnr.high, serialnr.low); + env_set("serial#", serial); + } + + /*execute board relevant initilizations for preparing fastboot */ + board_fastboot_setup(); + + /*get the fastboot dev*/ + ret = _fastboot_setup_dev(&sw); + + /*load partitions information for the fastboot dev*/ + if (!ret && sw) + fastboot_load_partitions(); + + fastboot_init(NULL, 0); +#ifdef CONFIG_AVB_SUPPORT + fsl_avb_ab_ops.ops = &fsl_avb_ops; +#ifdef CONFIG_AVB_ATX + fsl_avb_atx_ops.ops = &fsl_avb_ops; +#endif +#endif +} diff --git a/drivers/fastboot/fb_fsl/fb_fsl_common.h b/drivers/fastboot/fb_fsl/fb_fsl_common.h new file mode 100644 index 0000000000..4577d9e9ae --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_common.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FB_FSL_COMMON_H +#define FB_FSL_COMMON_H + +#ifdef CONFIG_AVB_SUPPORT +#include +#include +#endif + +#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC) +extern AvbABOps fsl_avb_ab_ops; +#ifdef CONFIG_AVB_ATX +extern AvbAtxOps fsl_avb_atx_ops; +#endif +extern AvbOps fsl_avb_ops; +#endif + +int get_block_size(void); +void process_erase_mmc(const char *cmdbuf, char *response); + +#endif // FB_FSL_COMMON_H diff --git a/drivers/fastboot/fb_fsl/fb_fsl_dev.c b/drivers/fastboot/fb_fsl/fb_fsl_dev.c new file mode 100644 index 0000000000..1f75442e37 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_dev.c @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fb_fsl_common.h" + +static lbaint_t mmc_sparse_write(struct sparse_storage *info, + lbaint_t blk, lbaint_t blkcnt, const void *buffer) +{ +#define SPARSE_FILL_BUF_SIZE (2 * 1024 * 1024) + + + struct blk_desc *dev_desc = (struct blk_desc *)info->priv; + ulong ret = 0; + void *data; + int fill_buf_num_blks, cnt; + + if ((unsigned long)buffer & (CONFIG_SYS_CACHELINE_SIZE - 1)) { + + fill_buf_num_blks = SPARSE_FILL_BUF_SIZE / info->blksz; + + data = memalign(CONFIG_SYS_CACHELINE_SIZE, fill_buf_num_blks * info->blksz); + + while (blkcnt) { + + if (blkcnt > fill_buf_num_blks) + cnt = fill_buf_num_blks; + else + cnt = blkcnt; + + memcpy(data, buffer, cnt * info->blksz); + + ret += blk_dwrite(dev_desc, blk, cnt, data); + + blk += cnt; + blkcnt -= cnt; + buffer = (void *)((unsigned long)buffer + cnt * info->blksz); + + } + + free(data); + } else { + ret = blk_dwrite(dev_desc, blk, blkcnt, buffer); + } + + return ret; +} + +static lbaint_t mmc_sparse_reserve(struct sparse_storage *info, + lbaint_t blk, lbaint_t blkcnt) +{ + return blkcnt; +} + +int write_backup_gpt(void *download_buffer) +{ + int mmc_no = 0; + struct mmc *mmc; + struct blk_desc *dev_desc; + + mmc_no = fastboot_devinfo.dev_id; + mmc = find_mmc_device(mmc_no); + if (mmc == NULL) { + printf("invalid mmc device\n"); + return -1; + } + dev_desc = blk_get_dev("mmc", mmc_no); + if (dev_desc == NULL) { + printf("Can't get Block device MMC %d\n", + mmc_no); + return -ENODEV; + } + + /* write backup get partition */ + if (write_backup_gpt_partitions(dev_desc, download_buffer)) { + printf("writing GPT image fail\n"); + return -1; + } + + printf("flash backup gpt image successfully\n"); + return 0; +} + +static int get_fastboot_target_dev(char *mmc_dev, struct fastboot_ptentry *ptn) +{ + int dev = 0; + struct mmc *target_mmc; + + /* Support flash bootloader to mmc 'target_ubootdev' devices, if the + * 'target_ubootdev' env is not set just flash bootloader to current + * mmc device. + */ + if ((!strncmp(ptn->name, FASTBOOT_PARTITION_BOOTLOADER, + sizeof(FASTBOOT_PARTITION_BOOTLOADER))) && + (env_get("target_ubootdev"))) { + dev = simple_strtoul(env_get("target_ubootdev"), NULL, 10); + + /* if target_ubootdev is set, it must be that users want to change + * fastboot device, then fastboot environment need to be updated */ + fastboot_setup(); + + target_mmc = find_mmc_device(dev); + if ((target_mmc == NULL) || mmc_init(target_mmc)) { + printf("MMC card init failed!\n"); + return -1; + } else { + printf("Flash target is mmc%d\n", dev); + if (target_mmc->part_config != MMCPART_NOAVAILABLE) + sprintf(mmc_dev, "mmc dev %x %x", dev, /*slot no*/ + FASTBOOT_MMC_BOOT_PARTITION_ID/*part no*/); + else + sprintf(mmc_dev, "mmc dev %x", dev); + } + } else if (ptn->partition_id != FASTBOOT_MMC_NONE_PARTITION_ID) + sprintf(mmc_dev, "mmc dev %x %x", + fastboot_devinfo.dev_id, /*slot no*/ + ptn->partition_id /*part no*/); + else + sprintf(mmc_dev, "mmc dev %x", + fastboot_devinfo.dev_id /*slot no*/); + return 0; +} + +static void process_flash_blkdev(const char *cmdbuf, void *download_buffer, + u32 download_bytes, char *response) +{ + if (download_bytes) { + struct fastboot_ptentry *ptn; + + /* Next is the partition name */ + ptn = fastboot_flash_find_ptn(cmdbuf); + if (ptn == NULL) { + fastboot_fail("partition does not exist", response); + fastboot_flash_dump_ptn(); + } else if ((download_bytes > + ptn->length * MMC_SATA_BLOCK_SIZE) && + !(ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV)) { + printf("Image too large for the partition\n"); + fastboot_fail("image too large for partition", response); + } else { + unsigned int temp; + + char blk_dev[128]; + char blk_write[128]; + int blkret; + + printf("writing to partition '%s'\n", ptn->name); + /* Get target flash device. */ + if (get_fastboot_target_dev(blk_dev, ptn) != 0) + return; + + if (!fastboot_parts_is_raw(ptn) && + is_sparse_image(download_buffer)) { + int dev_no = 0; + struct mmc *mmc; + struct blk_desc *dev_desc; + struct disk_partition info; + struct sparse_storage sparse; + int err; + + dev_no = fastboot_devinfo.dev_id; + + printf("sparse flash target is %s:%d\n", + fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", + dev_no); + if (fastboot_devinfo.type == DEV_MMC) { + mmc = find_mmc_device(dev_no); + if (mmc && mmc_init(mmc)) + printf("MMC card init failed!\n"); + } + + dev_desc = blk_get_dev(fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", dev_no); + if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { + printf("** Block device %s %d not supported\n", + fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", + dev_no); + return; + } + + if( strncmp(ptn->name, FASTBOOT_PARTITION_ALL, + strlen(FASTBOOT_PARTITION_ALL)) == 0) { + info.blksz = dev_desc->blksz; + info.size = dev_desc->lba; + info.start = 0; + } else { + + if (part_get_info(dev_desc, + ptn->partition_index, &info)) { + printf("Bad partition index:%d for partition:%s\n", + ptn->partition_index, ptn->name); + return; + } + } + printf("writing to partition '%s' for sparse, buffer size %d\n", + ptn->name, download_bytes); + + sparse.blksz = info.blksz; + sparse.start = info.start; + sparse.size = info.size; + sparse.write = mmc_sparse_write; + sparse.reserve = mmc_sparse_reserve; + sparse.mssg = fastboot_fail; + printf("Flashing sparse image at offset " LBAFU "\n", + sparse.start); + + sparse.priv = dev_desc; + err = write_sparse_image(&sparse, ptn->name, download_buffer, + response); + + if (!err) + fastboot_okay(NULL, response); + } else { + /* Will flash images in below case: + * 1. Is not gpt partition. + * 2. Is gpt partition but no overlay detected. + * */ + if (strncmp(ptn->name, "gpt", 3) || !bootloader_gpt_overlay()) { + /* block count */ + if (strncmp(ptn->name, "gpt", 3) == 0) { + temp = (ANDROID_GPT_END + + MMC_SATA_BLOCK_SIZE - 1) / + MMC_SATA_BLOCK_SIZE; + } else { + temp = (download_bytes + + MMC_SATA_BLOCK_SIZE - 1) / + MMC_SATA_BLOCK_SIZE; + } + + sprintf(blk_write, "%s write 0x%x 0x%x 0x%x", + fastboot_devinfo.type == DEV_SATA ? "sata" : "mmc", + (unsigned int)(uintptr_t)download_buffer, /*source*/ + ptn->start, /*dest*/ + temp /*length*/); + + printf("Initializing '%s'\n", ptn->name); + + blkret = run_command(blk_dev, 0); + if (blkret) + fastboot_fail("Init of BLK device failed", response); + else + fastboot_okay(NULL, response); + + printf("Writing '%s'\n", ptn->name); + if (run_command(blk_write, 0)) { + printf("Writing '%s' FAILED!\n", ptn->name); + fastboot_fail("Write partition failed", response); + } else { + printf("Writing '%s' DONE!\n", ptn->name); + fastboot_okay(NULL, response); + } + } + /* Write backup gpt image */ + if (strncmp(ptn->name, "gpt", 3) == 0) { + if (write_backup_gpt(download_buffer)) + fastboot_fail("write backup GPT image fail", response); + else + fastboot_okay(NULL, response); + + /* will force scan the device, + * so dev_desc can be re-inited + * with the latest data */ + run_command(blk_dev, 0); + } + } + } + } else { + fastboot_fail("no image downloaded", response); + } +} + +static void process_erase_blkdev(const char *cmdbuf, char *response) +{ + int mmc_no = 0; + lbaint_t blks, blks_start, blks_size, grp_size; + struct mmc *mmc; + struct blk_desc *dev_desc; + struct fastboot_ptentry *ptn; + struct disk_partition info; + + ptn = fastboot_flash_find_ptn(cmdbuf); + if ((ptn == NULL) || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) { + fastboot_fail("partition does not exist or uneraseable", response); + fastboot_flash_dump_ptn(); + return; + } + + if (fastboot_devinfo.type == DEV_SATA) { + printf("Not support erase on SATA\n"); + return; + } + + mmc_no = fastboot_devinfo.dev_id; + printf("erase target is MMC:%d\n", mmc_no); + + mmc = find_mmc_device(mmc_no); + if ((mmc == NULL) || mmc_init(mmc)) { + printf("MMC card init failed!\n"); + return; + } + + dev_desc = blk_get_dev("mmc", mmc_no); + if (NULL == dev_desc) { + printf("Block device MMC %d not supported\n", + mmc_no); + fastboot_fail("not valid MMC card", response); + return; + } + + if (part_get_info(dev_desc, + ptn->partition_index, &info)) { + printf("Bad partition index:%d for partition:%s\n", + ptn->partition_index, ptn->name); + fastboot_fail("erasing of MMC card", response); + return; + } + + /* Align blocks to erase group size to avoid erasing other partitions */ + grp_size = mmc->erase_grp_size; + blks_start = (info.start + grp_size - 1) & ~(grp_size - 1); + if (info.size >= grp_size) + blks_size = (info.size - (blks_start - info.start)) & + (~(grp_size - 1)); + else + blks_size = 0; + + printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n", + blks_start, blks_start + blks_size); + + blks = blk_derase(dev_desc, blks_start, blks_size); + if (blks != blks_size) { + printf("failed erasing from device %d", dev_desc->devnum); + fastboot_fail("erasing of MMC card", response); + return; + } + + printf("........ erased " LBAFU " bytes from '%s'\n", + blks_size * info.blksz, cmdbuf); + fastboot_okay(NULL, response); + + return; +} + +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT +static void process_flash_sf(const char *cmdbuf, void *download_buffer, + u32 download_bytes, char *response) +{ + int blksz = 0; + blksz = get_block_size(); + + if (download_bytes) { + struct fastboot_ptentry *ptn; + ptn = fastboot_flash_find_ptn(cmdbuf); + if (ptn == 0) { + fastboot_fail("partition does not exist", response); + fastboot_flash_dump_ptn(); + } else if ((download_bytes > ptn->length * blksz)) { + fastboot_fail("image too large for partition", response); + /* TODO : Improve check for yaffs write */ + } else { + int ret; + char sf_command[128]; + /* Normal case */ + /* Probe device */ + sprintf(sf_command, "sf probe"); + ret = run_command(sf_command, 0); + if (ret){ + fastboot_fail("Probe sf failed", response); + return; + } + /* Erase */ + sprintf(sf_command, "sf erase 0x%x 0x%x", ptn->start * blksz, /*start*/ + ptn->length * blksz /*size*/); + ret = run_command(sf_command, 0); + if (ret) { + fastboot_fail("Erasing sf failed", response); + return; + } + /* Write image */ + sprintf(sf_command, "sf write 0x%x 0x%x 0x%x", + (unsigned int)(ulong)download_buffer, /* source */ + ptn->start * blksz, /* start */ + download_bytes /*size*/); + printf("sf write '%s'\n", ptn->name); + ret = run_command(sf_command, 0); + if (ret){ + fastboot_fail("Writing sf failed", response); + return; + } + printf("sf write finished '%s'\n", ptn->name); + fastboot_okay(NULL, response); + } + } else { + fastboot_fail("no image downloaded", response); + } +} + +#ifdef CONFIG_ARCH_IMX8M +/* Check if the mcu image is built for running from TCM */ +static bool is_tcm_image(unsigned char *image_addr) +{ + u32 stack; + + stack = *(u32 *)image_addr; + + if ((stack != (u32)ANDROID_MCU_FIRMWARE_HEADER_STACK)) { + printf("Please flash mcu firmware images for running from TCM\n"); + return false; + } else + return true; +} +#endif +#endif + +void fastboot_process_erase(const char *cmdbuf, char *response) +{ + switch (fastboot_devinfo.type) { + case DEV_SATA: + case DEV_MMC: + process_erase_blkdev(cmdbuf, response); + break; + default: + printf("Not support flash command for current device %d\n", + fastboot_devinfo.type); + fastboot_fail("failed to flash device", response); + break; + } +} + +void fastboot_process_flash(const char *cmdbuf, void *download_buffer, + u32 download_bytes, char *response) +{ +/* Check if we need to flash mcu firmware */ +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT + if (!strncmp(cmdbuf, FASTBOOT_MCU_FIRMWARE_PARTITION, + sizeof(FASTBOOT_MCU_FIRMWARE_PARTITION))) { + switch (fastboot_firmwareinfo.type) { + case DEV_SF: + process_flash_sf(cmdbuf, download_buffer, + download_bytes, response); + break; +#ifdef CONFIG_ARCH_IMX8M + case DEV_MMC: + if (is_tcm_image(download_buffer)) + process_flash_blkdev(cmdbuf, download_buffer, + download_bytes, response); + break; +#endif + default: + printf("Don't support flash firmware\n"); + } + return; + } +#endif + /* Normal case */ + switch (fastboot_devinfo.type) { + case DEV_SATA: + case DEV_MMC: + process_flash_blkdev(cmdbuf, download_buffer, + download_bytes, response); + break; + default: + printf("Not support flash command for current device %d\n", + fastboot_devinfo.type); + fastboot_fail("failed to flash device", response); + break; + } +} + +/* erase a partition on mmc */ +void process_erase_mmc(const char *cmdbuf, char *response) +{ + int mmc_no = 0; + lbaint_t blks, blks_start, blks_size, grp_size; + struct mmc *mmc; + struct blk_desc *dev_desc; + struct fastboot_ptentry *ptn; + struct disk_partition info; + + ptn = fastboot_flash_find_ptn(cmdbuf); + if ((ptn == NULL) || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) { + sprintf(response, "FAILpartition does not exist or uneraseable"); + fastboot_flash_dump_ptn(); + return; + } + + mmc_no = fastboot_devinfo.dev_id; + printf("erase target is MMC:%d\n", mmc_no); + + mmc = find_mmc_device(mmc_no); + if ((mmc == NULL) || mmc_init(mmc)) { + printf("MMC card init failed!\n"); + return; + } + + dev_desc = blk_get_dev("mmc", mmc_no); + if (NULL == dev_desc) { + printf("Block device MMC %d not supported\n", + mmc_no); + sprintf(response, "FAILnot valid MMC card"); + return; + } + + if (part_get_info(dev_desc, + ptn->partition_index, &info)) { + printf("Bad partition index:%d for partition:%s\n", + ptn->partition_index, ptn->name); + sprintf(response, "FAILerasing of MMC card"); + return; + } + + /* Align blocks to erase group size to avoid erasing other partitions */ + grp_size = mmc->erase_grp_size; + blks_start = (info.start + grp_size - 1) & ~(grp_size - 1); + if (info.size >= grp_size) + blks_size = (info.size - (blks_start - info.start)) & + (~(grp_size - 1)); + else + blks_size = 0; + + printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n", + blks_start, blks_start + blks_size); + + blks = blk_derase(dev_desc, blks_start, blks_size); + if (blks != blks_size) { + printf("failed erasing from device %d", dev_desc->devnum); + sprintf(response, "FAILerasing of MMC card"); + return; + } + + printf("........ erased " LBAFU " bytes from '%s'\n", + blks_size * info.blksz, cmdbuf); + sprintf(response, "OKAY"); + + return; +} diff --git a/drivers/fastboot/fb_fsl/fb_fsl_getvar.c b/drivers/fastboot/fb_fsl/fb_fsl_getvar.c new file mode 100644 index 0000000000..24e94b8cd0 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_getvar.c @@ -0,0 +1,572 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_AVB_SUPPORT +#include +#include +#endif + +#ifdef CONFIG_ANDROID_THINGS_SUPPORT +#include +#include +#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 + +#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; + } +} diff --git a/drivers/fastboot/fb_fsl/fb_fsl_partitions.c b/drivers/fastboot/fb_fsl/fb_fsl_partitions.c new file mode 100644 index 0000000000..3ea3a27ca9 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_partitions.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SATA +#include +#endif + +#if defined(CONFIG_FASTBOOT_LOCK) +#include "fastboot_lock_unlock.h" +#endif + +#ifdef CONFIG_IMX_TRUSTY_OS +#include "u-boot/sha256.h" +#include +#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; +} + diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 8ba55aab9f..e8444cbfcb 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -38,12 +38,20 @@ * that expect bulk OUT requests to be divisible by maxpacket size. */ +typedef struct usb_req usb_req; +struct usb_req { + struct usb_request *in_req; + usb_req *next; +}; + struct f_fastboot { struct usb_function usb_function; /* IN/OUT EP's and corresponding requests */ struct usb_ep *in_ep, *out_ep; struct usb_request *in_req, *out_req; + + usb_req *front, *rear; }; static char fb_ext_prop_name[] = "DeviceInterfaceGUID"; @@ -194,6 +202,24 @@ static struct usb_gadget_strings *fastboot_strings[] = { static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); +static void fastboot_fifo_complete(struct usb_ep *ep, struct usb_request *req) +{ + int status = req->status; + usb_req *request; + + if (!status) { + if (fastboot_func->front != NULL) { + request = fastboot_func->front; + fastboot_func->front = fastboot_func->front->next; + usb_ep_free_request(ep, request->in_req); + free(request); + } else { + printf("fail free request\n"); + } + return; + } +} + static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) { int status = req->status; @@ -397,11 +423,57 @@ static int fastboot_add(struct usb_configuration *c) } DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add); -static int fastboot_tx_write(const char *buffer, unsigned int buffer_size) +int fastboot_tx_write_more(const char *buffer) +{ + int ret = 0; + + /* alloc usb request FIFO node */ + usb_req *req = (usb_req *)malloc(sizeof(usb_req)); + if (!req) { + printf("failed alloc usb req!\n"); + return -ENOMEM; + } + + /* usb request node FIFO enquene */ + if ((fastboot_func->front == NULL) && (fastboot_func->rear == NULL)) { + fastboot_func->front = fastboot_func->rear = req; + req->next = NULL; + } else { + fastboot_func->rear->next = req; + fastboot_func->rear = req; + req->next = NULL; + } + + /* alloc in request for current node */ + req->in_req = fastboot_start_ep(fastboot_func->in_ep); + if (!req->in_req) { + printf("failed alloc req in\n"); + fastboot_disable(&(fastboot_func->usb_function)); + return -EINVAL; + } + req->in_req->complete = fastboot_fifo_complete; + + memcpy(req->in_req->buf, buffer, strlen(buffer)); + req->in_req->length = strlen(buffer); + + ret = usb_ep_queue(fastboot_func->in_ep, req->in_req, 0); + if (ret) { + printf("Error %d on queue\n", ret); + return -EINVAL; + } + + ret = 0; + return ret; +} + +int fastboot_tx_write(const char *buffer, unsigned int buffer_size) { struct usb_request *in_req = fastboot_func->in_req; int ret; + if (!buffer_size) + return 0; + memcpy(in_req->buf, buffer, buffer_size); in_req->length = buffer_size; @@ -512,6 +584,10 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) char response[FASTBOOT_RESPONSE_LEN] = {0}; int cmd = -1; + /* init in request FIFO pointer */ + fastboot_func->front = NULL; + fastboot_func->rear = NULL; + if (req->status != 0 || req->length == 0) return; diff --git a/include/android_image.h b/include/android_image.h index 54d25af068..ef6ecc2e78 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -22,6 +22,19 @@ /* The bootloader expects the structure of andr_img_hdr with header * version 0 to be as follows: */ +/* Boot metric variables (in millisecond) */ +struct boot_metric +{ + u32 bll_1; /* 1th bootloader load duration */ + u32 ble_1; /* 1th bootloader exec duration */ + u32 kl; /* kernel image load duration */ + u32 kd; /* kernel image decompress duration */ + u32 avb; /* avb verify boot.img duration */ + u32 odt; /* overlay device tree duration */ + u32 sw; /* system wait for UI interaction duration*/ +}; +typedef struct boot_metric boot_metric; + struct andr_img_hdr { /* Must be ANDR_BOOT_MAGIC. */ char magic[ANDR_BOOT_MAGIC_SIZE]; @@ -73,16 +86,19 @@ struct andr_img_hdr { * +-----------------+ * | boot header | 1 page * +-----------------+ - * | kernel | n pages + * | kernel | i pages * +-----------------+ * | ramdisk | m pages * +-----------------+ - * | second stage | o pages + * | second stage | n pages + * +-----------------+ + * | recovery dtbo | o pages * +-----------------+ * - * n = (kernel_size + page_size - 1) / page_size + * i = (kernel_size + page_size - 1) / page_size * m = (ramdisk_size + page_size - 1) / page_size - * o = (second_size + page_size - 1) / page_size + * n = (second_size + page_size - 1) / page_size + * o = (recovery_dtbo_size + page_size - 1) / page_size * * 0. all entities are page_size aligned in flash * 1. kernel and ramdisk are required (size != 0) @@ -136,4 +152,16 @@ struct andr_img_hdr { * else: jump to kernel_addr */ +struct header_image { + uint32_t code0; /* Executable code */ + uint32_t code1; /* Executable code */ + uint64_t text_offset; /* Image load offset, LE */ + uint64_t image_size; /* Effective Image size, LE */ + uint64_t res1; /* reserved */ + uint64_t res2; /* reserved */ + uint64_t res3; /* reserved */ + uint64_t res4; /* reserved */ + uint32_t magic; /* Magic number */ + uint32_t res5; +}; #endif diff --git a/include/command.h b/include/command.h index 747f8f8095..1498fc2541 100644 --- a/include/command.h +++ b/include/command.h @@ -203,6 +203,10 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc, int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size, const char *r, const char *s, bool global); +#ifdef CONFIG_CMD_READ +int do_raw_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +#endif + /* * Error codes that commands return to cmd_process(). We use the standard 0 * and 1 for success and failure, but add one more case - failure with a diff --git a/include/fastboot.h b/include/fastboot.h index 57daaf1298..5671cbab07 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -48,7 +48,20 @@ enum { FASTBOOT_COMMAND_ACMD, FASTBOOT_COMMAND_UCMD, #endif - +#ifdef CONFIG_FSL_FASTBOOT + FASTBOOT_COMMAND_UPLOAD, + FASTBOOT_COMMAND_GETSTAGED, +#ifdef CONFIG_FASTBOOT_LOCK + FASTBOOT_COMMAND_FLASHING, + FASTBOOT_COMMAND_OEM, +#endif +#ifdef CONFIG_AVB_SUPPORT + FASTBOOT_COMMAND_SETACTIVE, +#endif +#ifdef CONFIG_AVB_ATX + FASTBOOT_COMMAND_STAGE, +#endif +#endif FASTBOOT_COMMAND_COUNT }; @@ -176,4 +189,9 @@ void fastboot_data_complete(char *response); #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) void fastboot_acmd_complete(void); #endif + +int fastboot_tx_write_more(const char *buffer); + +int fastboot_tx_write(const char *buffer, unsigned int buffer_size); + #endif /* _FASTBOOT_H_ */ diff --git a/include/fb_fsl.h b/include/fb_fsl.h new file mode 100644 index 0000000000..dbd37017ec --- /dev/null +++ b/include/fb_fsl.h @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + */ + +#ifndef FB_FSL_H +#define FB_FSL_H +#include +#include + +#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 */ diff --git a/include/image.h b/include/image.h index b4b284d52b..05266b4cf2 100644 --- a/include/image.h +++ b/include/image.h @@ -1539,6 +1539,7 @@ void android_print_contents(const struct andr_img_hdr *hdr); #if !defined(CONFIG_SPL_BUILD) bool android_image_print_dtb_contents(ulong hdr_addr); #endif +bool image_arm64(void *images); #endif /* CONFIG_ANDROID_BOOT_IMAGE */ #endif /* !USE_HOSTCC */ diff --git a/include/init.h b/include/init.h index fd51d7f966..7a32b57b17 100644 --- a/include/init.h +++ b/include/init.h @@ -278,6 +278,10 @@ int init_func_vid(void); int checkboard(void); int show_board_info(void); +#ifdef CONFIG_ANDROID_BOOT_IMAGE +void get_reboot_reason(char *ret); +#endif + /** * Get the uppermost pointer that is valid to access * diff --git a/include/mmc.h b/include/mmc.h index 8600881705..5f92622752 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -956,6 +956,7 @@ int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr); extern uint mmc_get_env_part(struct mmc *mmc); # endif int mmc_get_env_dev(void); +int mmc_map_to_kernel_blk(int dev_no); /* Minimum partition switch timeout in units of 10-milliseconds */ #define MMC_MIN_PART_SWITCH_TIME 30 /* 300 ms */ diff --git a/include/part.h b/include/part.h index 6a8875884f..40c72f7df4 100644 --- a/include/part.h +++ b/include/part.h @@ -410,6 +410,15 @@ int is_valid_gpt_buf(struct blk_desc *dev_desc, void *buf); */ int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf); +/** + * write_backup_gpt_partitions - write MBR, backup gpt table. + * @param dev_desc - block device descriptor + * @param buf - buffer which contains the MBR and Primary GPT info + * + * @return - '0' on success, otherwise error + */ +int write_backup_gpt_partitions(struct blk_desc *dev_desc, void *buf); + /** * gpt_verify_headers() - Function to read and CRC32 check of the GPT's header * and partition table entries (PTE) diff --git a/include/recovery.h b/include/recovery.h new file mode 100644 index 0000000000..c6b097efeb --- /dev/null +++ b/include/recovery.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2017 NXP + */ + +#ifndef __RECOVERY_H_ +#define __RECOVERY_H_ + +struct reco_envs { + char *cmd; + char *args; +}; + +void board_recovery_setup(void); + +#endif diff --git a/lib/avb/fsl/fsl_avb.c b/lib/avb/fsl/fsl_avb.c index ff92654e8b..cd70ebac38 100644 --- a/lib/avb/fsl/fsl_avb.c +++ b/lib/avb/fsl/fsl_avb.c @@ -8,8 +8,8 @@ #include #include -#include -#include "../../../drivers/usb/gadget/fastboot_lock_unlock.h" +#include +#include "../../../drivers/fastboot/fb_fsl/fastboot_lock_unlock.h" #include #include "fsl_avbkey.h" diff --git a/lib/avb/fsl/fsl_bootctl.c b/lib/avb/fsl/fsl_bootctl.c index 8f853bc807..1143c3f088 100755 --- a/lib/avb/fsl/fsl_bootctl.c +++ b/lib/avb/fsl/fsl_bootctl.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include /* as libavb's bootctl doesn't have the get_var support diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 730ee0e3df..201c8a3266 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -28,6 +28,10 @@ CONFIG_AM335X_USB1_MODE CONFIG_AM437X_USB2PHY2_HOST CONFIG_ANDES_PCU CONFIG_ANDES_PCU_BASE +CONFIG_ANDROID_AB_SUPPORT +CONFIG_ANDROID_AUTO_SUPPORT +CONFIG_ANDROID_SUPPORT +CONFIG_ANDROID_THINGS_SUPPORT CONFIG_APER_0_BASE CONFIG_APER_1_BASE CONFIG_APER_SIZE @@ -85,6 +89,10 @@ CONFIG_ATMEL_MCI_8BIT CONFIG_ATMEL_SPI0 CONFIG_AT_TRANS CONFIG_AUTO_ZRELADDR +CONFIG_AVB_FUSE +CONFIG_AVB_FUSE_BANK_END +CONFIG_AVB_FUSE_BANK_SIZEW +CONFIG_AVB_FUSE_BANK_START CONFIG_BACKSIDE_L2_CACHE CONFIG_BAT_PAIR CONFIG_BAT_RW @@ -380,6 +388,7 @@ CONFIG_EHCI_MXS_PORT0 CONFIG_EHCI_MXS_PORT1 CONFIG_EMU CONFIG_ENABLE_36BIT_PHYS +CONFIG_ENABLE_LOCKSTATUS_SUPPORT CONFIG_ENABLE_MMU CONFIG_ENABLE_MUST_CHECK CONFIG_ENV_ADDR_FLEX @@ -1639,6 +1648,7 @@ CONFIG_SXNI855T CONFIG_SYSFLAGS_ADDR CONFIG_SYSFS CONFIG_SYSMGR_ISWGRP_HANDOFF +CONFIG_SYSTEM_RAMDISK_SUPPORT CONFIG_SYS_33MHZ CONFIG_SYS_64BIT CONFIG_SYS_64BIT_LBA -- 2.17.1