]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
mx53: add HAB support
authorLothar Waßmann <LW@KARO-electronics.de>
Mon, 15 Jun 2015 08:11:10 +0000 (10:11 +0200)
committerLothar Waßmann <LW@KARO-electronics.de>
Tue, 16 Jun 2015 08:58:45 +0000 (10:58 +0200)
arch/arm/cpu/armv7/mx5/Makefile
arch/arm/cpu/armv7/mx5/hab.c [new file with mode: 0644]
arch/arm/include/asm/arch-mx5/hab.h [new file with mode: 0644]
board/karo/tx53/config.mk
board/karo/tx53/tx53.c

index d021842f6811d41004f695b9f746aad66a96f628..93b5378b6b63c71b78d54a5c7e1d2774c517e419 100644 (file)
@@ -9,3 +9,5 @@
 
 obj-y := soc.o clock.o
 obj-y += lowlevel_init.o
 
 obj-y := soc.o clock.o
 obj-y += lowlevel_init.o
+
+obj-$(CONFIG_SECURE_BOOT) += hab.o
diff --git a/arch/arm/cpu/armv7/mx5/hab.c b/arch/arm/cpu/armv7/mx5/hab.c
new file mode 100644 (file)
index 0000000..8d5949f
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hab.h>
+
+HAB_FUNC(entry, hab_status_t)
+HAB_FUNC(exit, hab_status_t)
+HAB_FUNC5(authenticate_image, void *, uint8_t, size_t, void **, size_t *, hab_loader_callback_f_t)
+HAB_FUNC2(report_status, hab_status_t, hab_config_t *, hab_state_t *)
+HAB_FUNC4(report_event, hab_status_t, hab_status_t, uint32_t, uint8_t *, size_t *)
+HAB_FUNC3(check_target, hab_status_t, uint8_t, const void *, size_t)
+HAB_FUNC3(assert, hab_status_t, uint8_t, const void *, size_t)
+
+struct mx53_ivt {
+       u32 header;
+       u32 app_start_addr;
+       u32 rsrvd1;
+       void *dcd_ptr;
+       struct mx53_boot_data *boot_data;
+       void *self;
+       void *csf;
+       u32 rsrvd2;
+};
+
+struct mx53_boot_data {
+       void *start;
+       u32 length;
+       u32 plugin;
+};
+
+#define IVT_SIZE               0x20
+#define ALIGN_SIZE             0x400
+#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
+ */
+
+static inline int read_fuse(unsigned bank, unsigned row)
+{
+       struct iim_regs *iim_regs = (void *)IMX_IIM_BASE;
+       u32 *fuses;
+
+       if (bank > ARRAY_SIZE(iim_regs->bank))
+               return -EINVAL;
+       fuses = iim_regs->bank[bank].fuse_regs;
+
+       debug("Reading fuse bank %u row %u @ %p\n", bank, row, &fuses[row]);
+       return readl(&fuses[row]);
+}
+
+static bool is_hab_enabled(void)
+{
+#ifdef DEBUG
+       static int first = 1;
+
+       if (first) {
+               debug("rvt_base=%p\n", hab_rvt_base());
+               debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
+               debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
+               debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
+               debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
+               debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
+               debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
+               debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
+               first = 0;
+       }
+#endif
+       return read_fuse(0, 4) & (1 << 1);
+}
+
+static void mx53_hab_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]);
+       }
+}
+
+static inline void mx53_hab_pr_fuse_val(unsigned bank, unsigned row)
+{
+       printf(" %02x", read_fuse(bank, row));
+}
+
+static inline void mx53_hab_dump_srk_hash(void)
+{
+       int i;
+
+       printf("SRK hash:\n\t");
+       mx53_hab_pr_fuse_val(1, 1);
+       for (i = 1; i <= 31; i++) {
+               if (i % 8 == 0)
+                       printf("\n\t");
+               mx53_hab_pr_fuse_val(3, i);
+       }
+       printf("\n");
+}
+
+int get_hab_status(void)
+{
+       static uint32_t last_hab_event __attribute__((section(".data")));
+       uint32_t index = last_hab_event; /* Loop index */
+       uint8_t event_data[128]; /* Event data buffer */
+       size_t bytes = sizeof(event_data); /* Event size in bytes */
+       enum hab_config config;
+       enum hab_state state;
+       int ret;
+       int hab_debug = getenv_yesno("hab_debug") == 1;
+
+       if (hab_debug) {
+               if (is_hab_enabled()) {
+                       printf("Secure boot enabled\n\t");
+               } else {
+                       printf("Secure boot disabled\n");
+               }
+               mx53_hab_dump_srk_hash();
+       }
+
+       /* Check HAB status */
+       config = state = 0; /* ROM code assumes short enums! */
+       ret = hab_rvt_report_status(&config, &state);
+       if (hab_debug || ret != HAB_SUCCESS)
+               printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
+                       config, state);
+       if (ret != HAB_SUCCESS) {
+               /* Display HAB Error events */
+               while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
+                                       &bytes) == HAB_SUCCESS) {
+                       puts("\n");
+                       printf("--------- HAB Event %d -----------------\n",
+                              index + 1);
+                       puts("event data:\n");
+                       mx53_hab_display_event(event_data, bytes);
+                       puts("\n");
+                       bytes = sizeof(event_data);
+                       index++;
+               }
+               ret = index - last_hab_event;
+               last_hab_event = index;
+       } else {
+               /* Display message if no HAB events are found */
+               if (hab_debug)
+                       puts("No HAB Events Found!\n");
+               ret = 0;
+       }
+       return ret;
+}
+
+static inline hab_status_t hab_init(void)
+{
+       hab_status_t ret;
+
+       ret = hab_rvt_entry();
+       debug("hab_rvt_entry() returned %02x\n", ret);
+       if (ret != HAB_SUCCESS) {
+               printf("hab entry function failed: %02x\n", ret);
+       }
+
+       return ret;
+}
+
+static inline hab_status_t hab_exit(void)
+{
+       hab_status_t ret;
+
+       ret = hab_rvt_exit();
+       if (ret != HAB_SUCCESS)
+               printf("hab exit function failed: %02x\n", ret);
+
+       return ret;
+}
+
+static hab_status_t hab_check_target(hab_target_t type, uint32_t addr, size_t len)
+{
+       hab_status_t ret;
+
+       ret = hab_init();
+       if (ret != HAB_SUCCESS)
+               return ret;
+
+       ret = hab_rvt_check_target(type, (void *)addr, len);
+       if (ret != HAB_SUCCESS) {
+               printf("check_target(0x%08x, 0x%08x) failed: %d\n",
+                       addr, len, ret);
+               return ret;
+       }
+       ret = hab_exit();
+
+       if (ret == HAB_SUCCESS && get_hab_status() > 0) {
+               return HAB_FAILURE;
+       }
+       return ret;
+}
+
+static hab_status_t hab_assert(uint32_t type, uint32_t addr, size_t len)
+{
+       hab_status_t ret;
+
+       ret = hab_init();
+       if (ret != HAB_SUCCESS)
+               return ret;
+
+       ret = hab_rvt_assert(type, (void *)addr, len);
+       if (ret != HAB_SUCCESS) {
+               printf("assert(0x%08x, 0x%08x) failed: %d\n",
+                       addr, len, ret);
+               return ret;
+       }
+       ret = hab_exit();
+
+       if (ret == HAB_SUCCESS && get_hab_status() > 0) {
+               return HAB_FAILURE;
+       }
+       return ret;
+}
+
+static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       if (argc != 1)
+               return CMD_RET_USAGE;
+
+       get_hab_status();
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       hab_target_t type = HAB_TGT_MEMORY;
+       uint32_t addr;
+       size_t len;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+       len = simple_strtoul(argv[2], NULL, 16);
+       if (argc > 3) {
+               switch (argv[3][0]) {
+               case 'p':
+               case 'P':
+                       type = HAB_TGT_PERIPHERAL;
+                       break;
+               case 'm':
+               case 'M':
+                       type = HAB_TGT_MEMORY;
+                       break;
+               default:
+                       printf("Invalid type '%s'\n", argv[3]);
+                       return CMD_RET_USAGE;
+               }
+       }
+       if (hab_check_target(type, addr, len) != HAB_SUCCESS)
+               return CMD_RET_FAILURE;
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       uint32_t type = 0;
+       uint32_t addr;
+       size_t len;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+       len = simple_strtoul(argv[2], NULL, 16);
+       if (argc > 3) {
+               type = simple_strtoul(argv[3], NULL, 16);
+       }
+
+       if (hab_assert(type, addr, len) != HAB_SUCCESS)
+               return CMD_RET_FAILURE;
+
+       return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+               hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
+               "display HAB status",
+               ""
+         );
+
+U_BOOT_CMD(
+               hab_check_target, 4, 0, do_hab_check_target,
+               "verify an address range via HAB",
+               "addr len [type]\n"
+               "\t\taddr -\taddress to verify\n"
+               "\t\tlen -\tlength of addr range to verify\n"
+         );
+
+U_BOOT_CMD(
+               hab_assert, 4, 0, do_hab_assert,
+               "Test an assertion against the HAB audit log",
+               "addr len [type]\n"
+               "\t\taddr -\taddress to verify\n"
+               "\t\tlen -\tlength of addr range to verify\n"
+         );
diff --git a/arch/arm/include/asm/arch-mx5/hab.h b/arch/arm/include/asm/arch-mx5/hab.h
new file mode 100644 (file)
index 0000000..c71f664
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+*/
+
+#ifndef __ARCH_MX5_HAB_H
+#define __ARCH_MX5_HAB_H
+
+#ifdef CONFIG_SECURE_BOOT
+
+#include <linux/types.h>
+
+int get_hab_status(void);
+
+/* -------- start of HAB API updates ------------*/
+/* The following are taken from HAB4 SIS */
+
+/* Status definitions */
+typedef enum hab_status {
+       HAB_STS_ANY = 0x00,
+       HAB_FAILURE = 0x33,
+       HAB_WARNING = 0x69,
+       HAB_SUCCESS = 0xf0
+} hab_status_t;
+
+/* Security Configuration definitions */
+typedef enum hab_config {
+       HAB_CFG_RETURN = 0x33, /**< Field Return IC */
+       HAB_CFG_OPEN = 0xf0, /**< Non-secure IC */
+       HAB_CFG_CLOSED = 0xcc /**< Secure IC */
+} hab_config_t;
+
+/* State definitions */
+typedef 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
+} hab_state_t;
+
+typedef enum hab_target {
+       HAB_TGT_MEMORY = 0x0f, /* Check memory white list */
+       HAB_TGT_PERIPHERAL = 0xf0, /* Check peripheral white list*/
+} hab_target_t;
+
+enum HAB_FUNC_OFFSETS {
+       HAB_RVT_HEADER,
+       HAB_RVT_ENTRY,
+       HAB_RVT_EXIT,
+       HAB_RVT_CHECK_TARGET,
+       HAB_RVT_AUTHENTICATE_IMAGE,
+       HAB_RVT_RUN_DCD,
+       HAB_RVT_RUN_CSF,
+       HAB_RVT_ASSERT,
+       HAB_RVT_REPORT_EVENT,
+       HAB_RVT_REPORT_STATUS,
+       HAB_RVT_FAILSAFE,
+};
+
+/* Function prototype description */
+typedef hab_status_t hab_rvt_entry_t(void);
+
+typedef hab_status_t hab_rvt_exit_t(void);
+
+typedef hab_status_t hab_rvt_check_target_t(hab_target_t, const void *,
+               size_t);
+
+typedef hab_status_t hab_loader_callback_f_t(void**, size_t*, const void*);
+typedef void *hab_rvt_authenticate_image_t(uint8_t, ptrdiff_t,
+               void **, size_t *, hab_loader_callback_f_t);
+
+typedef hab_status_t hab_rvt_assert_t(uint32_t, const void *,
+               size_t);
+
+typedef hab_status_t hab_rvt_report_event_t(hab_status_t, uint32_t,
+               uint8_t* , size_t*);
+
+typedef hab_status_t hab_rvt_report_status_t(enum hab_config *,
+               enum hab_state *);
+
+typedef void hapi_clock_init_t(void);
+
+#define HAB_RVT_BASE                   0x00000094
+
+static inline void **hab_rvt_base(void)
+{
+       uint32_t *base = (void *)0x94;
+
+       if ((*base & 0xff0000ff) != cpu_to_be32(0xdd000040)) {
+               printf("Invalid RVT @ %p\n", base);
+               hang();
+       }
+       return (void **)base;
+}
+
+#define HAB_CID_ROM 0 /**< ROM Caller ID */
+#define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/
+/* ----------- end of HAB API updates ------------*/
+
+#define hab_rvt_entry_p                                                \
+       ((hab_rvt_entry_t *)hab_rvt_base()[HAB_RVT_ENTRY])
+
+#define hab_rvt_exit_p                                         \
+       ((hab_rvt_exit_t *)hab_rvt_base()[HAB_RVT_EXIT])
+
+#define hab_rvt_check_target_p                                 \
+       ((hab_rvt_check_target_t*)hab_rvt_base()[HAB_RVT_CHECK_TARGET])
+
+#define hab_rvt_authenticate_image_p                           \
+       ((hab_rvt_authenticate_image_t *)hab_rvt_base()[HAB_RVT_AUTHENTICATE_IMAGE])
+
+#define hab_rvt_assert_p                                       \
+       ((hab_rvt_assert_t*)hab_rvt_base()[HAB_RVT_ASSERT])
+
+#define hab_rvt_report_event_p                                 \
+       ((hab_rvt_report_event_t*)hab_rvt_base()[HAB_RVT_REPORT_EVENT])
+
+#define hab_rvt_report_status_p                                        \
+       ((hab_rvt_report_status_t*)hab_rvt_base()[HAB_RVT_REPORT_STATUS])
+
+#define HAB_FUNC(n, rt)                                                        \
+static inline rt hab_rvt_##n(void)                                     \
+{                                                                      \
+       if (hab_rvt_base() == NULL)                                     \
+               return (rt)-1;                                          \
+       return hab_rvt_##n##_p();                                       \
+}                                                                      \
+
+#define HAB_FUNC2(n, rt, t1, t2)                                       \
+static inline rt hab_rvt_##n(t1 p1, t2 p2)                             \
+{                                                                      \
+       if (hab_rvt_base() == NULL)                                     \
+               return (rt)-1;                                          \
+       return hab_rvt_##n##_p(p1, p2);                                 \
+}
+
+#define HAB_FUNC3(n, rt, t1, t2, t3)                                   \
+static inline rt hab_rvt_##n(t1 p1, t2 p2, t3 p3)                      \
+{                                                                      \
+       if (hab_rvt_base() == NULL)                                     \
+               return (rt)-1;                                          \
+       return hab_rvt_##n##_p(p1, p2, p3);                             \
+}
+
+#define HAB_FUNC4(n, rt, t1, t2, t3, t4)                               \
+static inline rt hab_rvt_##n(t1 p1, t2 p2, t3 p3, t4 p4)               \
+{                                                                      \
+       if (hab_rvt_base() == NULL)                                     \
+               return (rt)-1;                                          \
+       return hab_rvt_##n##_p(p1, p2, p3, p4);                         \
+}
+
+#define HAB_FUNC5(n, rt, t1, t2, t3, t4, t5)                           \
+static inline rt hab_rvt_##n(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5)                \
+{                                                                      \
+       if (hab_rvt_base() == NULL)                                     \
+               return (rt)-1;                                          \
+       return hab_rvt_##n##_p(p1, p2, p3, p4, p5);                     \
+}
+
+#else /* CONFIG_SECURE_BOOT */
+
+static inline int get_hab_status(void)
+{
+       return 0;
+}
+
+#endif /* CONFIG_SECURE_BOOT */
+#endif /* __ARCH_MX5_HAB_H */
index 0ecbf3291542a958bf81322a1ac8f29c7ccb586a..09d6709dfea90bb405122eed42ad42d4effc4a73 100644 (file)
@@ -1,6 +1,7 @@
 # stack is allocated below CONFIG_SYS_TEXT_BASE
 # stack is allocated below CONFIG_SYS_TEXT_BASE
-CONFIG_SYS_TEXT_BASE := 0x70100000
+CONFIG_SYS_TEXT_BASE := 0x700ff000
 
 __HAVE_ARCH_GENERIC_BOARD := y
 PLATFORM_CPPFLAGS += -Werror
 LOGO_BMP = logos/karo.bmp
 
 __HAVE_ARCH_GENERIC_BOARD := y
 PLATFORM_CPPFLAGS += -Werror
 LOGO_BMP = logos/karo.bmp
+OBJCOPYFLAGS += -j .pad
index 6c0a3023156fceebc033ae2e488d43638d2fcd88..299a647b1690588f0a55965eaab76ad9122cf6c1 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/gpio.h>
 #include <asm/arch/iomux-mx53.h>
 #include <asm/arch/clock.h>
 #include <asm/gpio.h>
 #include <asm/arch/iomux-mx53.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/hab.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/sys_proto.h>
@@ -59,6 +60,7 @@ DECLARE_GLOBAL_DATA_PTR;
                                PAD_CTL_SRE_FAST | PAD_CTL_PUS_47K_UP)
 
 char __uboot_img_end[0] __attribute__((section(".__uboot_img_end")));
                                PAD_CTL_SRE_FAST | PAD_CTL_PUS_47K_UP)
 
 char __uboot_img_end[0] __attribute__((section(".__uboot_img_end")));
+char __csf_data[0] __attribute__((section(".__csf_data")));
 
 static iomux_v3_cfg_t tx53_pads[] = {
        /* NAND flash pads are set up in lowlevel_init.S */
 
 static iomux_v3_cfg_t tx53_pads[] = {
        /* NAND flash pads are set up in lowlevel_init.S */
@@ -1378,6 +1380,9 @@ exit:
 
        gpio_set_value(TX53_RESET_OUT_GPIO, 1);
        clear_ctrlc();
 
        gpio_set_value(TX53_RESET_OUT_GPIO, 1);
        clear_ctrlc();
+
+       get_hab_status();
+
        return ret;
 }
 
        return ret;
 }