[PATCH] imx: hab: Make imx_hab_is_enabled dependent on FIELD_RETURN

Paul Geurts paul.geurts at prodrive-technologies.com
Fri Jun 21 15:06:26 CEST 2024


The decision on whether HAB is enabled is solely based on the SEC_CONFIG
fuse. The HAB FIELD_RETURN feature is able to permanently disable HAB on
a CPU, after which it is able to boot unsigned firmware. U-Boot however
does not take into account the FIELD_RETURN mode, and refuses to boot
unsigned software when the feature is enabled.

Also take the FIELD_RETURN fuse into account when deciding whether HAB
is enabled. When The FIELD_RETURN fuse is blown, HAB is not enabled.

Tested on i.MX8M Mini, i.MX8M Plus, i.MX8M Nano and i.MX6ULL

Signed-off-by: Paul Geurts <paul.geurts at prodrive-technologies.com>
---
 arch/arm/include/asm/mach-imx/hab.h |  5 +++--
 arch/arm/mach-imx/hab.c             | 21 +++++++++++++++++----
 arch/arm/mach-imx/imx8m/soc.c       |  7 ++++++-
 arch/arm/mach-imx/mx6/soc.c         |  7 ++++++-
 arch/arm/mach-imx/mx7/soc.c         |  7 ++++++-
 arch/arm/mach-imx/mx7ulp/soc.c      |  7 ++++++-
 6 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/hab.h b/arch/arm/include/asm/mach-imx/hab.h
index 2abf28ea45bc..d70e8eac1358 100644
--- a/arch/arm/include/asm/mach-imx/hab.h
+++ b/arch/arm/include/asm/mach-imx/hab.h
@@ -132,13 +132,14 @@ enum hab_target {
 	HAB_TGT_ANY		= 0x55,
 };
 
-struct imx_sec_config_fuse_t {
+struct imx_fuse_t {
 	int bank;
 	int word;
 };
 
 #if defined(CONFIG_IMX_HAB)
-extern struct imx_sec_config_fuse_t const imx_sec_config_fuse;
+extern struct imx_fuse_t const imx_sec_config_fuse;
+extern struct imx_fuse_t const imx_field_return_fuse;
 #endif
 
 /*Function prototype description*/
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index 27e053ef701c..03d827e6c1eb 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define IS_HAB_ENABLED_BIT \
 	(is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 :	\
 	 ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2))
+#define IS_FIELD_RETURN_BIT 0x00000001
 
 #ifdef CONFIG_MX7ULP
 #define HAB_M4_PERSISTENT_START	((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \
@@ -871,18 +872,30 @@ static int validate_ivt(struct ivt *ivt_initial)
 
 bool imx_hab_is_enabled(void)
 {
-	struct imx_sec_config_fuse_t *fuse =
-		(struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
+	struct imx_fuse_t *sec_config =
+		(struct imx_fuse_t *)&imx_sec_config_fuse;
+	struct imx_fuse_t *field_return =
+		(struct imx_fuse_t *)&imx_field_return_fuse;
 	uint32_t reg;
+	bool is_enabled;
 	int ret;
 
-	ret = fuse_read(fuse->bank, fuse->word, &reg);
+	ret = fuse_read(sec_config->bank, sec_config->word, &reg);
 	if (ret) {
 		puts("\nSecure boot fuse read error\n");
 		return ret;
 	}
+	is_enabled = (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
+	if (is_enabled) {
+		ret = fuse_read(field_return->bank, field_return->word, &reg);
+		if (ret) {
+			puts("\nField return fuse read error\n");
+			return ret;
+		}
+		is_enabled = !(reg & IS_FIELD_RETURN_BIT);
+	}
 
-	return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
+	return is_enabled;
 }
 
 int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 0c49fb9cd488..af0844946378 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -36,10 +36,15 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #if defined(CONFIG_IMX_HAB)
-struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
+struct imx_fuse_t const imx_sec_config_fuse = {
 	.bank = 1,
 	.word = 3,
 };
+
+struct imx_fuse_t const imx_field_return_fuse = {
+	.bank = 8,
+	.word = 3,
+};
 #endif
 
 int timer_init(void)
diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c
index c2875e727c94..02179b02b8d2 100644
--- a/arch/arm/mach-imx/mx6/soc.c
+++ b/arch/arm/mach-imx/mx6/soc.c
@@ -52,10 +52,15 @@ U_BOOT_DRVINFO(imx6_thermal) = {
 #endif
 
 #if defined(CONFIG_IMX_HAB)
-struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
+struct imx_fuse_t const imx_sec_config_fuse = {
 	.bank = 0,
 	.word = 6,
 };
+
+struct imx_fuse_t const imx_field_return_fuse = {
+	.bank = 5,
+	.word = 6,
+};
 #endif
 
 u32 get_nr_cpus(void)
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c
index 689dbefe8ee0..3369696e4614 100644
--- a/arch/arm/mach-imx/mx7/soc.c
+++ b/arch/arm/mach-imx/mx7/soc.c
@@ -128,10 +128,15 @@ static void isolate_resource(void)
 #endif
 
 #if defined(CONFIG_IMX_HAB)
-struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
+struct imx_fuse_t const imx_sec_config_fuse = {
 	.bank = 1,
 	.word = 3,
 };
+
+struct imx_fuse_t const imx_field_return_fuse = {
+	.bank = 8,
+	.word = 3,
+};
 #endif
 
 static bool is_mx7d(void)
diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c
index 217b7c45867d..d11204cb2479 100644
--- a/arch/arm/mach-imx/mx7ulp/soc.c
+++ b/arch/arm/mach-imx/mx7ulp/soc.c
@@ -38,10 +38,15 @@
 static char *get_reset_cause(char *);
 
 #if defined(CONFIG_IMX_HAB)
-struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
+struct imx_fuse_t const imx_sec_config_fuse = {
 	.bank = 29,
 	.word = 6,
 };
+
+struct imx_fuse_t const imx_field_return_fuse = {
+	.bank = 9,
+	.word = 6,
+};
 #endif
 
 #define ROM_VERSION_ADDR 0x80
-- 
2.30.2



More information about the U-Boot mailing list