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.geu...@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, ®); + ret = fuse_read(sec_config->bank, sec_config->word, ®); 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, ®); + 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