diff options
author | Nitin Garg <nitin.garg@freescale.com> | 2014-05-27 08:37:44 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-05-27 08:37:44 -0500 |
commit | 0802947cfb94789cdb6b8a402a7c4523549c2a12 (patch) | |
tree | f7db7449e67346b334cc87573134dafe9d40b00b | |
parent | b3b8da14c9469551991b09e24520eeed8240bafe (diff) | |
download | u-boot-imx-0802947cfb94789cdb6b8a402a7c4523549c2a12.zip u-boot-imx-0802947cfb94789cdb6b8a402a7c4523549c2a12.tar.gz u-boot-imx-0802947cfb94789cdb6b8a402a7c4523549c2a12.tar.bz2 |
ENGR00315499-3: Support i.MX6 HAB authentication of kernel image
Support HAB authentication of kernel or secondary images via bootm
or hab_auth_img u-boot command.
Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
-rw-r--r-- | arch/arm/cpu/armv7/mx6/clock.c | 38 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx6/hab.c | 241 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx6/soc.c | 15 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/clock.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/hab.h | 17 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/imx-regs.h | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/sys_proto.h | 2 | ||||
-rw-r--r-- | common/cmd_bootm.c | 10 |
8 files changed, 319 insertions, 13 deletions
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index bd65a08..fd6248d 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -498,6 +498,44 @@ int enable_pcie_clock(void) BM_ANADIG_PLL_ENET_ENABLE_PCIE); } +#ifdef CONFIG_SECURE_BOOT +void hab_caam_clock_enable(void) +{ + struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + u32 reg = 0; + + /*CG4 ~ CG6, enable CAAM clocks*/ + reg = readl(ccm_regs->CCGR0); + reg |= (MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK | + MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK | + MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK); + writel(reg, ccm_regs->CCGR0); + + /* Enable EMI slow clk */ + reg = readl(ccm_regs->CCGR6); + reg |= MXC_CCM_CCGR6_EMI_SLOW_MASK; + writel(reg, ccm_regs->CCGR6); +} + +void hab_caam_clock_disable(void) +{ + struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + u32 reg = 0; + + /*CG4 ~ CG6, disable CAAM clocks*/ + reg = readl(ccm_regs->CCGR0); + reg &= ~(MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK | + MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK | + MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK); + writel(reg, ccm_regs->CCGR0); + + /* Disable EMI slow clk */ + reg = readl(ccm_regs->CCGR6); + reg &= ~MXC_CCM_CCGR6_EMI_SLOW_MASK; + writel(reg, ccm_regs->CCGR6); +} +#endif + unsigned int mxc_get_clock(enum mxc_clock clk) { switch (clk) { diff --git a/arch/arm/cpu/armv7/mx6/hab.c b/arch/arm/cpu/armv7/mx6/hab.c index 5187775..e1d10b9 100644 --- a/arch/arm/cpu/armv7/mx6/hab.c +++ b/arch/arm/cpu/armv7/mx6/hab.c @@ -7,15 +7,98 @@ #include <common.h> #include <asm/io.h> #include <asm/arch/hab.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> /* -------- start of HAB API updates ------------*/ -#define hab_rvt_report_event ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) -#define hab_rvt_report_status ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS) -#define hab_rvt_authenticate_image \ - ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) -#define hab_rvt_entry ((hab_rvt_entry_t *)HAB_RVT_ENTRY) -#define hab_rvt_exit ((hab_rvt_exit_t *)HAB_RVT_EXIT) -#define hab_rvt_clock_init HAB_RVT_CLOCK_INIT +#define hab_rvt_report_event_p \ +( \ + ((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) \ + && (is_soc_rev(CHIP_REV_1_5) >= 0)) ? \ + ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ + (is_cpu_type(MXC_CPU_MX6DL) && (is_soc_rev(CHIP_REV_1_2) >= 0)) ? \ + ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ + ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) \ +) + +#define hab_rvt_report_status_p \ +( \ + ((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) \ + && (is_soc_rev(CHIP_REV_1_5) >= 0)) ? \ + ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) : \ + ((is_cpu_type(MXC_CPU_MX6DL) || is_cpu_type(MXC_CPU_MX6SOLO)) \ + && (is_soc_rev(CHIP_REV_1_2) >= 0)) ? \ + ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) : \ + ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS) \ +) + +#define hab_rvt_authenticate_image_p \ +( \ + ((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) \ + && (is_soc_rev(CHIP_REV_1_5) >= 0)) ? \ + ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ + ((is_cpu_type(MXC_CPU_MX6DL) || is_cpu_type(MXC_CPU_MX6SOLO)) \ + && (is_soc_rev(CHIP_REV_1_2) >= 0)) ? \ + ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) :\ + ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) \ +) + +#define hab_rvt_entry_p \ +( \ + ((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) \ + && (is_soc_rev(CHIP_REV_1_5) >= 0)) ? \ + ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ + ((is_cpu_type(MXC_CPU_MX6DL) || is_cpu_type(MXC_CPU_MX6SOLO)) \ + && (is_soc_rev(CHIP_REV_1_2) >= 0)) ? \ + ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ + ((hab_rvt_entry_t *)HAB_RVT_ENTRY) \ +) + +#define hab_rvt_exit_p \ +( \ + ((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) \ + && (is_soc_rev(CHIP_REV_1_5) >= 0)) ? \ + ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ + ((is_cpu_type(MXC_CPU_MX6DL) || is_cpu_type(MXC_CPU_MX6SOLO)) \ + && (is_soc_rev(CHIP_REV_1_2) >= 0)) ? \ + ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ + ((hab_rvt_exit_t *)HAB_RVT_EXIT) \ +) + +#define IVT_SIZE 0x20 +#define ALIGN_SIZE 0x1000 +#define CSF_PAD_SIZE 0x2000 + +/* + * +------------+ 0x0 (DDR_UIMAGE_START) - + * | Header | | + * +------------+ 0x40 | + * | | | + * | | | + * | | | + * | | | + * | Image Data | | + * . | | + * . | > Stuff to be authenticated ----+ + * . | | | + * | | | | + * | | | | + * +------------+ | | + * | | | | + * | Fill Data | | | + * | | | | + * +------------+ Align to ALIGN_SIZE | | + * | IVT | | | + * +------------+ + IVT_SIZE - | + * | | | + * | CSF DATA | <---------------------------------------------------------+ + * | | + * +------------+ + * | | + * | Fill Data | + * | | + * +------------+ + CSF_PAD_SIZE + */ bool is_hab_enabled(void) { @@ -52,12 +135,17 @@ int get_hab_status(void) size_t bytes = sizeof(event_data); /* Event size in bytes */ enum hab_config config = 0; enum hab_state state = 0; + hab_rvt_report_event_t *hab_rvt_report_event; + hab_rvt_report_status_t *hab_rvt_report_status; if (is_hab_enabled()) puts("\nSecure boot enabled\n"); else puts("\nSecure boot disabled\n"); + hab_rvt_report_event = hab_rvt_report_event_p; + hab_rvt_report_status = hab_rvt_report_status_p; + /* Check HAB status */ if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", @@ -85,6 +173,120 @@ int get_hab_status(void) return 0; } +#ifdef DEBUG_AUTHENTICATE_IMAGE +void dump_mem(uint32_t addr, int size) +{ + int i; + + for (i = 0; i < size; i += 4) { + if (i != 0) { + if (i % 16 == 0) + printf("\n"); + else + printf(" "); + } + + printf("0x%08x", *(uint32_t *)addr); + addr += 4; + } + + printf("\n"); + + return; +} +#endif + +uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size) +{ + uint32_t load_addr = 0; + size_t bytes; + ptrdiff_t ivt_offset = 0; + int result = 0; + ulong start; + hab_rvt_authenticate_image_t *hab_rvt_authenticate_image; + hab_rvt_entry_t *hab_rvt_entry; + hab_rvt_exit_t *hab_rvt_exit; + + hab_rvt_authenticate_image = hab_rvt_authenticate_image_p; + hab_rvt_entry = hab_rvt_entry_p; + hab_rvt_exit = hab_rvt_exit_p; + + if (is_hab_enabled()) { + printf("\nAuthenticate uImage from DDR location 0x%x...\n", + ddr_start); + + hab_caam_clock_enable(); + + if (hab_rvt_entry() == HAB_SUCCESS) { + /* If not already aligned, Align to ALIGN_SIZE */ + ivt_offset = (image_size + ALIGN_SIZE - 1) & + ~(ALIGN_SIZE - 1); + + start = ddr_start; + bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE; + +#ifdef DEBUG_AUTHENTICATE_IMAGE + printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", + ivt_offset, ddr_start + ivt_offset); + printf("Dumping IVT\n"); + dump_mem(ddr_start + ivt_offset, 0x20); + + printf("Dumping CSF Header\n"); + dump_mem(ddr_start + ivt_offset + 0x20, 0x40); + + get_hab_status(); + + printf("\nCalling authenticate_image in ROM\n"); + printf("\tivt_offset = 0x%x\n\tstart = 0x%08x" + "\n\tbytes = 0x%x\n", ivt_offset, start, bytes); +#endif + /* + * If the MMU is enabled, we have to notify the ROM + * code, or it won't flush the caches when needed. + * This is done, by setting the "pu_irom_mmu_enabled" + * word to 1. You can find its address by looking in + * the ROM map. This is critical for + * authenticate_image(). If MMU is enabled, without + * setting this but, authentication will fail and may + * crash. + */ + if (is_cpu_type(MXC_CPU_MX6Q) || + is_cpu_type(MXC_CPU_MX6D)) { + /* + * This won't work on Rev 1.0.0 of i.MX6Q/D, + * since their ROM doesn't do cache flushes. + * I don't think any exist, so we ignore them. + */ + writel(1, 0x009024a8); + } else if (is_cpu_type(MXC_CPU_MX6DL) || + is_cpu_type(MXC_CPU_MX6SOLO)) { + writel(1, 0x00901dd0); + } else if (is_cpu_type(MXC_CPU_MX6SL)) { + writel(1, 0x00900a18); + } + + load_addr = (uint32_t)hab_rvt_authenticate_image( + HAB_CID_UBOOT, + ivt_offset, (void **)&start, + (size_t *)&bytes, NULL); + if (hab_rvt_exit() != HAB_SUCCESS) { + printf("hab exit function fail\n"); + load_addr = 0; + } + } else + printf("hab entry function fail\n"); + + hab_caam_clock_disable(); + + get_hab_status(); + } + + if ((!is_hab_enabled()) || (load_addr != 0)) + result = 1; + + return result; +} + int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if ((argc != 1)) { @@ -97,8 +299,33 @@ int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } +static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + ulong addr, ivt_offset; + int rcode = 0; + + if (argc < 3) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[1], NULL, 16); + ivt_offset = simple_strtoul(argv[2], NULL, 16); + + rcode = authenticate_image(addr, ivt_offset); + + return rcode; +} + U_BOOT_CMD( hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, "display HAB status", "" ); + +U_BOOT_CMD( + hab_auth_img, 3, 1, do_authenticate_image, + "authenticate image via HAB", + "addr ivt_offset\n" + "addr - image hex address\n" + "ivt_offset - hex offset of IVT in the image" + ); diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index b29973f..c5f3b22 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -377,10 +377,25 @@ int board_postclk_init(void) #ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) + enum dcache_option option = DCACHE_WRITETHROUGH; +#else + enum dcache_option option = DCACHE_WRITEBACK; +#endif + /* Avoid random hang when download by usb */ invalidate_dcache_all(); + /* Enable D-cache. I-cache is already enabled in start.S */ dcache_enable(); + + /* Enable caching on OCRAM and ROM */ + mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR, + ROMCP_ARB_END_ADDR, + option); + mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, + IRAM_SIZE, + option); } #endif diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 1b4ded7..8a706a4 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -59,4 +59,8 @@ int enable_pcie_clock(void); int enable_i2c_clk(unsigned char enable, unsigned i2c_num); void enable_ipu_clock(void); int enable_fec_anatop_clock(enum enet_freq freq); +#ifdef CONFIG_SECURE_BOOT +void hab_caam_clock_enable(void); +void hab_caam_clock_disable(void); +#endif #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/arch-mx6/hab.h b/arch/arm/include/asm/arch-mx6/hab.h index d724f20..7636c05 100644 --- a/arch/arm/include/asm/arch-mx6/hab.h +++ b/arch/arm/include/asm/arch-mx6/hab.h @@ -53,11 +53,18 @@ typedef void *hab_rvt_authenticate_image_t(uint8_t, ptrdiff_t, void **, size_t *, hab_loader_callback_f_t); typedef void hapi_clock_init_t(void); -#define HAB_RVT_REPORT_EVENT (*(uint32_t *)0x000000B4) -#define HAB_RVT_REPORT_STATUS (*(uint32_t *)0x000000B8) -#define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *)0x000000A4) -#define HAB_RVT_ENTRY (*(uint32_t *)0x00000098) -#define HAB_RVT_EXIT (*(uint32_t *)0x0000009C) +#define HAB_RVT_REPORT_EVENT (*(uint32_t *) 0x000000B4) +#define HAB_RVT_REPORT_STATUS (*(uint32_t *) 0x000000B8) +#define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *) 0x000000A4) +#define HAB_RVT_ENTRY (*(uint32_t *) 0x00000098) +#define HAB_RVT_EXIT (*(uint32_t *) 0x0000009C) + +#define HAB_RVT_REPORT_EVENT_NEW (*(uint32_t *) 0x000000B8) +#define HAB_RVT_REPORT_STATUS_NEW (*(uint32_t *) 0x000000BC) +#define HAB_RVT_AUTHENTICATE_IMAGE_NEW (*(uint32_t *) 0x000000A8) +#define HAB_RVT_ENTRY_NEW (*(uint32_t *) 0x0000009C) +#define HAB_RVT_EXIT_NEW (*(uint32_t *) 0x000000A0) + #define HAB_RVT_CLOCK_INIT ((hapi_clock_init_t *)0x0000024D) #define HAB_CID_ROM 0 /**< ROM Caller ID */ diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index f1f8f5f..8a3243d 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -217,6 +217,11 @@ #define IP2APB_USBPHY2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x7C000) #define CHIP_REV_1_0 0x10 +#define CHIP_REV_1_1 0x11 +#define CHIP_REV_1_2 0x12 +#define CHIP_REV_1_3 0x13 +#define CHIP_REV_1_4 0x14 +#define CHIP_REV_1_5 0x15 #define IRAM_SIZE 0x00040000 #define FEC_QUIRK_ENET_MAC diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h index 38851a1..dfca85d 100644 --- a/arch/arm/include/asm/arch-mx6/sys_proto.h +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h @@ -11,7 +11,7 @@ #include <asm/imx-common/regs-common.h> #include "../arch-imx/cpu.h" -#define is_soc_rev(rev) ((get_cpu_rev() & 0xFF) - rev) +#define is_soc_rev(rev) ((int)((get_cpu_rev() & 0xFF) - rev)) u32 get_cpu_rev(void); /* returns MXC_CPU_ value */ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 9751edc..6cd9242 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -813,6 +813,16 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return do_bootm_subcommand(cmdtp, flag, argc, argv); } +#ifdef CONFIG_SECURE_BOOT + extern uint32_t authenticate_image( + uint32_t ddr_start, uint32_t image_size); + if (authenticate_image(load_addr, + image_get_image_size((image_header_t *)load_addr)) == 0) { + printf("Authenticate uImage Fail, Please check\n"); + return 1; + } +#endif + return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS | |