[U-Boot] HAB synchronous error loop i.MX8M
Patrick Wildt
patrick at blueri.se
Thu Oct 3 13:01:16 UTC 2019
On Thu, Oct 03, 2019 at 12:06:24PM +0200, Bartlomiej wrote:
> Hello,
> *
> *
> I'm using an i.MX8M based Boundary Devices Nitrogen8M board with U-Boot /
> U-Boot SPL as the bootloader. I want to use HAB (arch/arm/mach-imx/hab.c) in
> order to authenticate the bootloader and kernel images before running them.
> The problem is my board goes into a synchronous error loop when
> authenticating the bootloader image from U-Boot SPL level. I don't get any
> return code, nothing. It happens on the `hab_rvt_authenticate_image` call.
> The board is open, so it should just fail if the image is badly
> constructed/signed and let me continue.
>
> Any ideas as to why is it happening and what could possibly be done to fix
> this?
>
>
> Best regards,
> Bartlomiej Nowak
Boundary Devices U-Boot is about a year old, and I haven't checked how
they implemented it. I have a diff for i.MX8M HAB support which works
for me.
Best regards,
Patrick
diff --git a/arch/arm/include/asm/arch-imx8m/clock.h b/arch/arm/include/asm/arch-imx8m/clock.h
index e7c1670f6b..5cebe10c6f 100644
--- a/arch/arm/include/asm/arch-imx8m/clock.h
+++ b/arch/arm/include/asm/arch-imx8m/clock.h
@@ -675,4 +675,5 @@ int set_clk_qspi(void);
void enable_ocotp_clk(unsigned char enable);
int enable_i2c_clk(unsigned char enable, unsigned int i2c_num);
int set_clk_enet(enum enet_freq type);
+void hab_caam_clock_enable(unsigned char enable);
#endif
diff --git a/arch/arm/include/asm/mach-imx/hab.h b/arch/arm/include/asm/mach-imx/hab.h
index 95df88423c..f3bbad36de 100644
--- a/arch/arm/include/asm/mach-imx/hab.h
+++ b/arch/arm/include/asm/mach-imx/hab.h
@@ -10,6 +10,8 @@
#include <linux/types.h>
#include <linux/compiler.h>
+DECLARE_GLOBAL_DATA_PTR;
+
/*
* IVT header definitions
* Security Reference Manual for i.MX 7Dual and 7Solo Applications Processors,
@@ -165,6 +167,15 @@ typedef void hapi_clock_init_t(void);
#define HAB_ENG_RTL 0x77 /* RTL simulation engine */
#define HAB_ENG_SW 0xff /* Software engine */
+#ifdef CONFIG_ARM64
+#define HAB_RVT_BASE 0x00000880
+
+#define HAB_RVT_ENTRY ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x08))
+#define HAB_RVT_EXIT ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x10))
+#define HAB_RVT_AUTHENTICATE_IMAGE ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x20))
+#define HAB_RVT_REPORT_EVENT ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x40))
+#define HAB_RVT_REPORT_STATUS ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x48))
+#else
#ifdef CONFIG_ROM_UNIFIED_SECTIONS
#define HAB_RVT_BASE 0x00000100
#else
@@ -178,13 +189,14 @@ typedef void hapi_clock_init_t(void);
HAB_RVT_BASE_NEW : HAB_RVT_BASE_OLD)
#endif
-#define HAB_RVT_ENTRY (*(uint32_t *)(HAB_RVT_BASE + 0x04))
-#define HAB_RVT_EXIT (*(uint32_t *)(HAB_RVT_BASE + 0x08))
-#define HAB_RVT_CHECK_TARGET (*(uint32_t *)(HAB_RVT_BASE + 0x0C))
-#define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *)(HAB_RVT_BASE + 0x10))
-#define HAB_RVT_REPORT_EVENT (*(uint32_t *)(HAB_RVT_BASE + 0x20))
-#define HAB_RVT_REPORT_STATUS (*(uint32_t *)(HAB_RVT_BASE + 0x24))
-#define HAB_RVT_FAILSAFE (*(uint32_t *)(HAB_RVT_BASE + 0x28))
+#define HAB_RVT_ENTRY ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x04))
+#define HAB_RVT_EXIT ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x08))
+#define HAB_RVT_CHECK_TARGET ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x0C))
+#define HAB_RVT_AUTHENTICATE_IMAGE ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x10))
+#define HAB_RVT_REPORT_EVENT ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x20))
+#define HAB_RVT_REPORT_STATUS ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x24))
+#define HAB_RVT_FAILSAFE ((ulong)*(uint32_t *)(HAB_RVT_BASE + 0x28))
+#endif
#define HAB_CID_ROM 0 /**< ROM Caller ID */
#define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/
diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index 4925dd7894..65791cb1b2 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -133,7 +133,8 @@ int mxs_wait_mask_set(struct mxs_register_32 *reg, u32 mask, u32 timeout);
int mxs_wait_mask_clr(struct mxs_register_32 *reg, u32 mask, u32 timeout);
unsigned long call_imx_sip(unsigned long id, unsigned long reg0,
- unsigned long reg1, unsigned long reg2);
+ unsigned long reg1, unsigned long reg2,
+ unsigned long reg3);
unsigned long call_imx_sip_ret2(unsigned long id, unsigned long reg0,
unsigned long *reg1, unsigned long reg2,
unsigned long reg3);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index aeb5493488..1efc1ed8fa 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -36,9 +36,9 @@ config USE_IMXIMG_PLUGIN
config SECURE_BOOT
bool "Support i.MX HAB features"
- depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX5
+ depends on ARCH_IMX8M || ARCH_MX7 || ARCH_MX6 || ARCH_MX5
select FSL_CAAM if HAS_CAAM
- imply CMD_DEKBLOB
+ imply CMD_DEKBLOB if !ARCH_IMX8M
help
This option enables the support for secure boot (HAB).
See doc/README.mxc_hab for more details.
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 08ee52edbf..61d6bf176e 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -16,6 +16,7 @@ endif
obj-$(CONFIG_ENV_IS_IN_MMC) += mmc_env.o
obj-$(CONFIG_FEC_MXC) += mac.o
obj-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o
+obj-$(CONFIG_SECURE_BOOT) += hab.o
obj-y += cpu.o
endif
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index ce50dbe907..6b3f7928dd 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -20,7 +20,18 @@
#define MX6SL_PU_IROM_MMU_EN_VAR 0x00901c60
#define IS_HAB_ENABLED_BIT \
(is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \
- (is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2))
+ ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2))
+
+#ifdef CONFIG_ARM64
+#define FSL_SIP_HAB 0xC2000007
+#define FSL_SIP_HAB_AUTHENTICATE 0x00
+#define FSL_SIP_HAB_ENTRY 0x01
+#define FSL_SIP_HAB_EXIT 0x02
+#define FSL_SIP_HAB_REPORT_EVENT 0x03
+#define FSL_SIP_HAB_REPORT_STATUS 0x04
+
+static volatile gd_t *gd_save;
+#endif
static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
{
@@ -47,6 +58,97 @@ static int verify_ivt_header(struct ivt_header *ivt_hdr)
return result;
}
+static inline void save_gd(void)
+{
+#ifdef CONFIG_ARM64
+ gd_save = gd;
+#endif
+}
+
+static inline void restore_gd(void)
+{
+#ifdef CONFIG_ARM64
+ /*
+ * Make will already error that reserving x18 is not supported at the
+ * time of writing, clang: error: unknown argument: '-ffixed-x18'
+ */
+ __asm__ volatile("mov x18, %0\n" : : "r" (gd_save));
+#endif
+}
+
+static enum hab_status hab_rvt_entry(void)
+{
+ enum hab_status ret;
+ hab_rvt_entry_t *hab_rvt_entry_func;
+
+ hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
+
+#if defined(CONFIG_ARM64)
+ if (current_el() != 3) {
+ /* call sip */
+ ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB,
+ FSL_SIP_HAB_ENTRY, 0, 0, 0);
+ return ret;
+ }
+#endif
+
+ save_gd();
+ ret = hab_rvt_entry_func();
+ restore_gd();
+
+ return ret;
+}
+
+static enum hab_status hab_rvt_exit(void)
+{
+ enum hab_status ret;
+ hab_rvt_exit_t *hab_rvt_exit_func;
+
+ hab_rvt_exit_func = (hab_rvt_exit_t *)HAB_RVT_EXIT;
+
+#if defined(CONFIG_ARM64)
+ if (current_el() != 3) {
+ /* call sip */
+ ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB,
+ FSL_SIP_HAB_EXIT, 0, 0, 0);
+ return ret;
+ }
+#endif
+
+ save_gd();
+ ret = hab_rvt_exit_func();
+ restore_gd();
+
+ return ret;
+}
+
+static void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset,
+ void **start, size_t *bytes, hab_loader_callback_f_t loader)
+{
+ void *ret;
+ hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func;
+
+ hab_rvt_authenticate_image_func =
+ (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
+
+#if defined(CONFIG_ARM64)
+ if (current_el() != 3) {
+ /* call sip */
+ ret = (void *)call_imx_sip(FSL_SIP_HAB,
+ FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset,
+ (unsigned long)start, (unsigned long)bytes);
+ return ret;
+ }
+#endif
+
+ save_gd();
+ ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start,
+ bytes, loader);
+ restore_gd();
+
+ return ret;
+}
+
#if !defined(CONFIG_SPL_BUILD)
#define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */
@@ -245,6 +347,57 @@ static void display_event(uint8_t *event_data, size_t bytes)
process_event_record(event_data, bytes);
}
+static enum hab_status hab_rvt_report_event(enum hab_status status,
+ uint32_t index, uint8_t *event, size_t *bytes)
+{
+ enum hab_status ret;
+ hab_rvt_report_event_t *hab_rvt_report_event;
+
+ hab_rvt_report_event = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
+
+#if defined(CONFIG_ARM64)
+ if (current_el() != 3) {
+ /* call sip */
+ ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB,
+ FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index,
+ (unsigned long)event, (unsigned long)bytes);
+ return ret;
+ }
+#endif
+
+ save_gd();
+ ret = hab_rvt_report_event(status, index, event, bytes);
+ restore_gd();
+
+ return ret;
+}
+
+static enum hab_status hab_rvt_report_status(enum hab_config *config,
+ enum hab_state *state)
+{
+ enum hab_status ret;
+ hab_rvt_report_status_t *hab_rvt_report_status_func;
+
+ hab_rvt_report_status_func =
+ (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
+
+#if defined(CONFIG_ARM64)
+ if (current_el() != 3) {
+ /* call sip */
+ ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB,
+ FSL_SIP_HAB_REPORT_STATUS, (unsigned long)config,
+ (unsigned long)state, 0);
+ return ret;
+ }
+#endif
+
+ save_gd();
+ ret = hab_rvt_report_status_func(config, state);
+ restore_gd();
+
+ return ret;
+}
+
static int get_hab_status(void)
{
uint32_t index = 0; /* Loop index */
@@ -252,12 +405,6 @@ static 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;
-
- hab_rvt_report_event = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
- hab_rvt_report_status =
- (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
if (imx_hab_is_enabled())
puts("\nSecure boot enabled\n");
@@ -349,6 +496,7 @@ static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
return rcode;
}
+#ifdef HAB_RVT_FAILSAFE
static int do_hab_failsafe(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
@@ -389,6 +537,7 @@ static int do_authenticate_image_or_failover(cmd_tbl_t *cmdtp, int flag,
error:
return ret;
}
+#endif
U_BOOT_CMD(
hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
@@ -405,6 +554,7 @@ U_BOOT_CMD(
"ivt_offset - hex offset of IVT in the image"
);
+#ifdef HAB_RVT_FAILSAFE
U_BOOT_CMD(
hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
"run BootROM failsafe routine",
@@ -420,6 +570,7 @@ U_BOOT_CMD(
"length - image hex length\n"
"ivt_offset - hex offset of IVT in the image"
);
+#endif
#endif /* !defined(CONFIG_SPL_BUILD) */
@@ -471,7 +622,7 @@ static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes)
return false;
}
- csf_hdr = (u8 *)ivt->csf;
+ csf_hdr = (u8 *)(ulong)ivt->csf;
/* Verify if CSF Header exist */
if (*csf_hdr != HAB_CMD_HDR) {
@@ -539,24 +690,19 @@ bool imx_hab_is_enabled(void)
int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
uint32_t ivt_offset)
{
- uint32_t load_addr = 0;
+ ulong load_addr = 0;
size_t bytes;
- uint32_t ivt_addr = 0;
+ ulong ivt_addr = 0;
int result = 1;
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_check_target_t *hab_rvt_check_target;
struct ivt *ivt;
struct ivt_header *ivt_hdr;
+#ifdef HAB_RVT_CHECK_TARGET
+ hab_rvt_check_target_t *hab_rvt_check_target;
enum hab_status status;
- hab_rvt_authenticate_image =
- (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
- hab_rvt_entry = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
- hab_rvt_exit = (hab_rvt_exit_t *)HAB_RVT_EXIT;
hab_rvt_check_target = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
+#endif
if (!imx_hab_is_enabled()) {
puts("hab fuse not enabled\n");
@@ -579,8 +725,8 @@ int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
/* Verify IVT body */
if (ivt->self != ivt_addr) {
- printf("ivt->self 0x%08x pointer is 0x%08x\n",
- ivt->self, ivt_addr);
+ printf("ivt->self 0x%08x pointer is 0x%08lx\n",
+ ivt->self, (ulong)ivt_addr);
goto hab_authentication_exit;
}
@@ -602,12 +748,14 @@ int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
goto hab_exit_failure_print_status;
}
+#ifdef HAB_RVT_CHECK_TARGET
status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)ddr_start, bytes);
if (status != HAB_SUCCESS) {
printf("HAB check target 0x%08x-0x%08x fail\n",
ddr_start, ddr_start + bytes);
goto hab_exit_failure_print_status;
}
+#endif
#ifdef DEBUG
printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr);
printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
@@ -627,6 +775,8 @@ int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
printf("\tstart = 0x%08lx\n", start);
printf("\tbytes = 0x%x\n", bytes);
#endif
+
+#ifndef CONFIG_ARM64
/*
* If the MMU is enabled, we have to notify the ROM
* code, or it won't flush the caches when needed.
@@ -654,8 +804,9 @@ int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
}
}
+#endif
- load_addr = (uint32_t)hab_rvt_authenticate_image(
+ load_addr = (ulong)hab_rvt_authenticate_image(
HAB_CID_UBOOT,
ivt_offset, (void **)&start,
(size_t *)&bytes, NULL);
diff --git a/arch/arm/mach-imx/imx8m/clock.c b/arch/arm/mach-imx/imx8m/clock.c
index 289b9417aa..232219f2f6 100644
--- a/arch/arm/mach-imx/imx8m/clock.c
+++ b/arch/arm/mach-imx/imx8m/clock.c
@@ -304,6 +304,13 @@ static u32 get_root_clk(enum clk_root_index clock_id)
return root_src_clk / (post_podf + 1) / (pre_podf + 1);
}
+#ifdef CONFIG_SECURE_BOOT
+void hab_caam_clock_enable(unsigned char enable)
+{
+ /* The CAAM clock is always on for iMX8M */
+}
+#endif
+
#ifdef CONFIG_MXC_OCOTP
void enable_ocotp_clk(unsigned char enable)
{
diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c
index 18d7e6819c..3d9422d5a2 100644
--- a/arch/arm/mach-imx/imx_bootaux.c
+++ b/arch/arm/mach-imx/imx_bootaux.c
@@ -26,7 +26,7 @@ int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
/* Enable M4 */
#ifdef CONFIG_IMX8M
- call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0);
+ call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0, 0);
#else
clrsetbits_le32(SRC_BASE_ADDR + SRC_M4_REG_OFFSET,
SRC_M4C_NON_SCLR_RST_MASK, SRC_M4_ENABLE_MASK);
@@ -38,7 +38,7 @@ int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
int arch_auxiliary_core_check_up(u32 core_id)
{
#ifdef CONFIG_IMX8M
- return call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0);
+ return call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0, 0);
#else
unsigned int val;
diff --git a/arch/arm/mach-imx/sip.c b/arch/arm/mach-imx/sip.c
index 968e7cf309..fca520c671 100644
--- a/arch/arm/mach-imx/sip.c
+++ b/arch/arm/mach-imx/sip.c
@@ -7,7 +7,8 @@
#include <asm/arch/sys_proto.h>
unsigned long call_imx_sip(unsigned long id, unsigned long reg0,
- unsigned long reg1, unsigned long reg2)
+ unsigned long reg1, unsigned long reg2,
+ unsigned long reg3)
{
struct pt_regs regs;
@@ -15,6 +16,7 @@ unsigned long call_imx_sip(unsigned long id, unsigned long reg0,
regs.regs[1] = reg0;
regs.regs[2] = reg1;
regs.regs[3] = reg2;
+ regs.regs[4] = reg3;
smc_call(®s);
diff --git a/configs/imx8mq_evk_defconfig b/configs/imx8mq_evk_defconfig
index e45731edda..d5f6cdf1ca 100644
--- a/configs/imx8mq_evk_defconfig
+++ b/configs/imx8mq_evk_defconfig
@@ -1,4 +1,5 @@
CONFIG_ARM=y
+CONFIG_SECURE_BOOT=y
CONFIG_SPL_SYS_ICACHE_OFF=y
CONFIG_SPL_SYS_DCACHE_OFF=y
CONFIG_ARCH_IMX8M=y
More information about the U-Boot
mailing list