
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@prodrive-technologies.com --- arch/arm/include/asm/mach-imx/hab.h | 1 + arch/arm/mach-imx/hab.c | 28 ++++++++++++++++++++++++---- arch/arm/mach-imx/imx8m/soc.c | 5 +++++ arch/arm/mach-imx/mx6/soc.c | 5 +++++ arch/arm/mach-imx/mx7/soc.c | 5 +++++ arch/arm/mach-imx/mx7ulp/soc.c | 5 +++++ 6 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/mach-imx/hab.h b/arch/arm/include/asm/mach-imx/hab.h index 9410f30eef2e..c0caf57fe61d 100644 --- a/arch/arm/include/asm/mach-imx/hab.h +++ b/arch/arm/include/asm/mach-imx/hab.h @@ -139,6 +139,7 @@ struct imx_fuse {
#if defined(CONFIG_IMX_HAB) extern struct imx_fuse const imx_sec_config_fuse; +extern struct imx_fuse 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 7e4eaa4b14fb..600092389a32 100644 --- a/arch/arm/mach-imx/hab.c +++ b/arch/arm/mach-imx/hab.c @@ -26,6 +26,14 @@ 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 FIELD_RETURN_FUSE_MASK \ + (is_imx8mp() ? 0xFFFFFFFF : 0x00000001) +/* + * The fuse pattern for i.MX8M Plus is 0x28001401, but bit 2 is already set from factory. + * This means when field return is set, the fuse word value reads 0x28001405 + */ +#define FIELD_RETURN_PATTERN \ + (is_imx8mp() ? 0x28001405 : 0x00000001)
#ifdef CONFIG_MX7ULP #define HAB_M4_PERSISTENT_START ((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \ @@ -870,18 +878,30 @@ static int validate_ivt(struct ivt *ivt_initial)
bool imx_hab_is_enabled(void) { - struct imx_fuse *fuse = + struct imx_fuse *sec_config = (struct imx_fuse *)&imx_sec_config_fuse; + struct imx_fuse *field_return = + (struct imx_fuse *)&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"); + puts("Secure boot fuse read error\n"); return ret; } + is_enabled = reg & IS_HAB_ENABLED_BIT; + if (is_enabled) { + ret = fuse_read(field_return->bank, field_return->word, ®); + if (ret) { + puts("Field return fuse read error\n"); + return ret; + } + is_enabled = (reg & FIELD_RETURN_FUSE_MASK) != FIELD_RETURN_PATTERN; + }
- 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 e6c00e85412b..09a528a64f8e 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -41,6 +41,11 @@ struct imx_fuse const imx_sec_config_fuse = { .bank = 1, .word = 3, }; + +struct imx_fuse 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 e9dd33845635..d4a61731a67d 100644 --- a/arch/arm/mach-imx/mx6/soc.c +++ b/arch/arm/mach-imx/mx6/soc.c @@ -55,6 +55,11 @@ struct imx_fuse const imx_sec_config_fuse = { .bank = 0, .word = 6, }; + +struct imx_fuse 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 11e8ac066086..e504c1fd52a0 100644 --- a/arch/arm/mach-imx/mx7/soc.c +++ b/arch/arm/mach-imx/mx7/soc.c @@ -131,6 +131,11 @@ struct imx_fuse const imx_sec_config_fuse = { .bank = 1, .word = 3, }; + +struct imx_fuse 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 b50ad1cfa195..61d331e01819 100644 --- a/arch/arm/mach-imx/mx7ulp/soc.c +++ b/arch/arm/mach-imx/mx7ulp/soc.c @@ -42,6 +42,11 @@ struct imx_fuse const imx_sec_config_fuse = { .bank = 29, .word = 6, }; + +struct imx_fuse const imx_field_return_fuse = { + .bank = 9, + .word = 6, +}; #endif
#define ROM_VERSION_ADDR 0x80