[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(&regs);
 
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