[08/37] imx: HAB: Update hab codes to support ARM64 and i.MX8M

Message ID 20210325093036.3270101-9-peng.fan@oss.nxp.com
State New
Headers show
Series
  • imx: hab/caam new feature and update
Related show

Commit Message

Peng Fan (OSS) March 25, 2021, 9:30 a.m.
From: Peng Fan <peng.fan@nxp.com>


There are some changes to support ARM64 i.MX8M platform in this patches:
1. The hab_rvt base and function vectors are different as i.MX6/7

2. Need to bypass an workaround for i.MX6 to fix problem in MMU.

3. The x18 register needed save & restore before calling any HAB API. According
   to ARM procedure call spec, the x18 is caller saved when it is used as
   temporary register. So calling HAB API may scratch this register, and
   cause crash once accessing the gd pointer.

   On ARMv7, the r9 is callee saved when it is used as variable register. So
   no need to save & restore it.

4. Add SEC_CONFIG fuse for iMX8M

When current EL is not EL3, the direct calling to HAB will fail because
CAAM/SNVS can't initialize at non-secure mode. In this case, we use
SIP call to run the HAB in ATF.

Signed-off-by: Ye Li <ye.li@nxp.com>

Signed-off-by: Peng Fan <peng.fan@nxp.com>

---
 arch/arm/include/asm/mach-imx/hab.h |  14 ++
 arch/arm/mach-imx/hab.c             | 229 +++++++++++++++++++++++++---
 2 files changed, 218 insertions(+), 25 deletions(-)

-- 
2.25.1

Patch

diff --git a/arch/arm/include/asm/mach-imx/hab.h b/arch/arm/include/asm/mach-imx/hab.h
index d8bd77075a..c4393ef443 100644
--- a/arch/arm/include/asm/mach-imx/hab.h
+++ b/arch/arm/include/asm/mach-imx/hab.h
@@ -165,6 +165,18 @@  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 *)(HAB_RVT_BASE + 0x08))
+#define HAB_RVT_EXIT			(*(ulong *)(HAB_RVT_BASE + 0x10))
+#define HAB_RVT_CHECK_TARGET		(*(ulong *)(HAB_RVT_BASE + 0x18))
+#define HAB_RVT_AUTHENTICATE_IMAGE	(*(ulong *)(HAB_RVT_BASE + 0x20))
+#define HAB_RVT_REPORT_EVENT		(*(ulong *)(HAB_RVT_BASE + 0x40))
+#define HAB_RVT_REPORT_STATUS		(*(ulong *)(HAB_RVT_BASE + 0x48))
+#define HAB_RVT_FAILSAFE		(*(ulong *)(HAB_RVT_BASE + 0x50))
+#else
+
 #ifdef CONFIG_ROM_UNIFIED_SECTIONS
 #define HAB_RVT_BASE			0x00000100
 #else
@@ -186,6 +198,8 @@  typedef void hapi_clock_init_t(void);
 #define HAB_RVT_REPORT_STATUS		(*(uint32_t *)(HAB_RVT_BASE + 0x24))
 #define HAB_RVT_FAILSAFE		(*(uint32_t *)(HAB_RVT_BASE + 0x28))
 
+#endif /*CONFIG_ARM64*/
+
 #define HAB_CID_ROM 0 /**< ROM Caller ID */
 #define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/
 
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index 66ac440349..9ebdbe6ac3 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -10,10 +10,14 @@ 
 #include <mapmem.h>
 #include <image.h>
 #include <asm/io.h>
+#include <asm/global_data.h>
 #include <asm/system.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/hab.h>
+#include <linux/arm-smccc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 #define ALIGN_SIZE		0x1000
 #define MX6DQ_PU_IROM_MMU_EN_VAR	0x009024a8
@@ -21,7 +25,7 @@ 
 #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))
 
 static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
 {
@@ -48,6 +52,194 @@  static int verify_ivt_header(struct ivt_header *ivt_hdr)
 	return result;
 }
 
+#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
+#define FSL_SIP_HAB_FAILSAFE		0x05
+#define FSL_SIP_HAB_CHECK_TARGET	0x06
+static volatile gd_t *gd_save;
+#endif
+
+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
+}
+
+enum hab_status hab_rvt_report_event(enum hab_status status, u32 index,
+				     u8 *event, size_t *bytes)
+{
+	enum hab_status ret;
+	hab_rvt_report_event_t *hab_rvt_report_event_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_report_event_func =  (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index,
+			      (unsigned long)event, (unsigned long)bytes, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_report_event_func(status, index, event, bytes);
+	restore_gd();
+
+	return ret;
+
+}
+
+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;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, (unsigned long)config,
+			      (unsigned long)state, 0, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_report_status_func(config, state);
+	restore_gd();
+
+	return ret;
+}
+
+enum hab_status hab_rvt_entry(void)
+{
+	enum hab_status ret;
+	hab_rvt_entry_t *hab_rvt_entry_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_entry_func();
+	restore_gd();
+
+	return ret;
+}
+
+enum hab_status hab_rvt_exit(void)
+{
+	enum hab_status ret;
+	hab_rvt_exit_t *hab_rvt_exit_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_exit_func =  (hab_rvt_exit_t *)HAB_RVT_EXIT;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_exit_func();
+	restore_gd();
+
+	return ret;
+}
+
+void hab_rvt_failsafe(void)
+{
+	hab_rvt_failsafe_t *hab_rvt_failsafe_func;
+
+	hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0, 0, 0, 0, NULL);
+		return;
+	}
+#endif
+
+	save_gd();
+	hab_rvt_failsafe_func();
+	restore_gd();
+}
+
+enum hab_status hab_rvt_check_target(enum hab_target type, const void *start,
+					       size_t bytes)
+{
+	enum hab_status ret;
+	hab_rvt_check_target_t *hab_rvt_check_target_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_check_target_func =  (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type,
+			      (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_check_target_func(type, start, bytes);
+	restore_gd();
+
+	return ret;
+}
+
+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;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset,
+			      (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
+		return (void *)res.a0;
+	}
+#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 */
@@ -253,12 +445,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");
@@ -493,7 +679,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) {
@@ -561,25 +747,15 @@  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;
 	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;
-
 	if (!imx_hab_is_enabled()) {
 		puts("hab fuse not enabled\n");
 		return 0;
@@ -591,7 +767,7 @@  int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
 	hab_caam_clock_enable(1);
 
 	/* Calculate IVT address header */
-	ivt_addr = ddr_start + ivt_offset;
+	ivt_addr = (ulong) (ddr_start + ivt_offset);
 	ivt = (struct ivt *)ivt_addr;
 	ivt_hdr = &ivt->hdr;
 
@@ -601,7 +777,7 @@  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",
+		printf("ivt->self 0x%08x pointer is 0x%08lx\n",
 		       ivt->self, ivt_addr);
 		goto hab_authentication_exit;
 	}
@@ -624,9 +800,9 @@  int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
 		goto hab_exit_failure_print_status;
 	}
 
-	status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)ddr_start, bytes);
+	status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes);
 	if (status != HAB_SUCCESS) {
-		printf("HAB check target 0x%08x-0x%08x fail\n",
+		printf("HAB check target 0x%08x-0x%08lx fail\n",
 		       ddr_start, ddr_start + bytes);
 		goto hab_exit_failure_print_status;
 	}
@@ -649,6 +825,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.
@@ -676,8 +854,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);