diff options
author | Ye.Li <B37916@freescale.com> | 2015-02-01 23:10:30 +0800 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2016-03-09 14:42:08 +0100 |
commit | 9116bee869ef3b974154fb6d3636613fea5d367c (patch) | |
tree | 0a4ec19753e460205d5db19e6b08adefa614d144 | |
parent | 9bed92b75d7f2330c16ee75d41b70ad4a089b351 (diff) |
MLK-10176-8 imx: mx7: add HAB security support
Add HAB files for secure boot and image athentication.
Signed-off-by: Ye.Li <B37916@freescale.com>
(cherry picked from commit 2447bbcdd4ffcbdbd4ebed1b25e67ea753332d9d)
Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
-rw-r--r-- | arch/arm/cpu/armv7/mx7/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx7/hab.c | 277 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx7/hab.h | 75 |
3 files changed, 353 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/mx7/Makefile b/arch/arm/cpu/armv7/mx7/Makefile index ba8964f8e8d..2b09f5b0816 100644 --- a/arch/arm/cpu/armv7/mx7/Makefile +++ b/arch/arm/cpu/armv7/mx7/Makefile @@ -6,3 +6,4 @@ # obj-y := soc.o clock.o clock_slice.o timer.o +obj-$(CONFIG_SECURE_BOOT) += hab.o diff --git a/arch/arm/cpu/armv7/mx7/hab.c b/arch/arm/cpu/armv7/mx7/hab.c new file mode 100644 index 00000000000..5b36f6776a4 --- /dev/null +++ b/arch/arm/cpu/armv7/mx7/hab.c @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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_p \ +( \ + ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) \ +) + +#define hab_rvt_report_status_p \ +( \ + ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) \ +) + +#define hab_rvt_authenticate_image_p \ +( \ + ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) \ +) + +#define hab_rvt_entry_p \ +( \ + ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) \ +) + +#define hab_rvt_exit_p \ +( \ + ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) \ +) + +#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) +{ + 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; + uint32_t reg = readl(&fuse->cfg0); + + return (reg & 0x2000000) == 0x2000000; +} + +void display_event(uint8_t *event_data, size_t bytes) +{ + uint32_t i; + + if (!(event_data && bytes > 0)) + return; + + for (i = 0; i < bytes; i++) { + if (i == 0) + printf("\t0x%02x", event_data[i]); + else if ((i % 8) == 0) + printf("\n\t0x%02x", event_data[i]); + else + printf(" 0x%02x", event_data[i]); + } +} + +int get_hab_status(void) +{ + uint32_t index = 0; /* Loop index */ + uint8_t event_data[128]; /* Event data buffer */ + 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", + config, state); + + /* Display HAB Error events */ + while (hab_rvt_report_event(HAB_FAILURE, index, event_data, + &bytes) == HAB_SUCCESS) { + puts("\n"); + printf("--------- HAB Event %d -----------------\n", + index + 1); + puts("event data:\n"); + display_event(event_data, bytes); + puts("\n"); + bytes = sizeof(event_data); + index++; + } + } + /* Display message if no HAB events are found */ + else { + printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", + config, state); + puts("No HAB Events Found!\n\n"); + } + 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 + 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)) { + cmd_usage(cmdtp); + return 1; + } + + get_hab_status(); + + 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/include/asm/arch-mx7/hab.h b/arch/arm/include/asm/arch-mx7/hab.h new file mode 100644 index 00000000000..97a2fec4558 --- /dev/null +++ b/arch/arm/include/asm/arch-mx7/hab.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + * +*/ + +#ifndef __SECURE_MX7_H__ +#define __SECURE_MX7_H__ + +#include <linux/types.h> + +/* -------- start of HAB API updates ------------*/ +/* The following are taken from HAB4 SIS */ + +/* Status definitions */ +enum hab_status { + HAB_STS_ANY = 0x00, + HAB_FAILURE = 0x33, + HAB_WARNING = 0x69, + HAB_SUCCESS = 0xf0 +}; + +/* Security Configuration definitions */ +enum hab_config { + HAB_CFG_RETURN = 0x33, /**< Field Return IC */ + HAB_CFG_OPEN = 0xf0, /**< Non-secure IC */ + HAB_CFG_CLOSED = 0xcc /**< Secure IC */ +}; + +/* State definitions */ +enum hab_state { + HAB_STATE_INITIAL = 0x33, /**< Initialising state (transitory) */ + HAB_STATE_CHECK = 0x55, /**< Check state (non-secure) */ + HAB_STATE_NONSECURE = 0x66, /**< Non-secure state */ + HAB_STATE_TRUSTED = 0x99, /**< Trusted state */ + HAB_STATE_SECURE = 0xaa, /**< Secure state */ + HAB_STATE_FAIL_SOFT = 0xcc, /**< Soft fail state */ + HAB_STATE_FAIL_HARD = 0xff, /**< Hard fail state (terminal) */ + HAB_STATE_NONE = 0xf0, /**< No security state machine */ + HAB_STATE_MAX +}; + +/*Function prototype description*/ +typedef enum hab_status hab_rvt_report_event_t(enum hab_status, uint32_t, + uint8_t* , size_t*); +typedef enum hab_status hab_rvt_report_status_t(enum hab_config *, + enum hab_state *); +typedef enum hab_status hab_loader_callback_f_t(void**, size_t*, const void*); +typedef enum hab_status hab_rvt_entry_t(void); +typedef enum hab_status hab_rvt_exit_t(void); +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_UNIFIED_BASE 0x00000100 +#define HAB_RVT_ENTRY (*(uint32_t *) (HAB_RVT_UNIFIED_BASE + 0x04)) +#define HAB_RVT_EXIT (*(uint32_t *) (HAB_RVT_UNIFIED_BASE + 0x08)) +#define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *) (HAB_RVT_UNIFIED_BASE + 0x10)) +#define HAB_RVT_REPORT_EVENT (*(uint32_t *) (HAB_RVT_UNIFIED_BASE + 0x20)) +#define HAB_RVT_REPORT_STATUS (*(uint32_t *) (HAB_RVT_UNIFIED_BASE + 0x24)) + +#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 */ +#define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/ +/* ----------- end of HAB API updates ------------*/ + +#endif |