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

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 | 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

On 6/21/24 3:06 PM, Paul Geurts wrote:
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
The purpose of the field return fuse is to unlock a system when it is returned to factory, right ?
Can the system be re-locked afterward too ?

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
The purpose of the field return fuse is to unlock a system when it is returned to factory, right ?
That is the intention of the field return mode indeed.
Can the system be re-locked afterward too ?
No, the field return is enabled by a fuse, which cannot be reverted. The mode is intended to be able to perform investigations on broken devices, but these devices are not intended to go back into the field.

On 6/24/24 10:20 AM, Paul Geurts wrote:
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
The purpose of the field return fuse is to unlock a system when it is returned to factory, right ?
That is the intention of the field return mode indeed.
Can the system be re-locked afterward too ?
No, the field return is enabled by a fuse, which cannot be reverted. The mode is intended to be able to perform investigations on broken devices, but these devices are not intended to go back into the field.
Understood, thanks for clarifying.

Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks

Hi Fabio,
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Yes, I will do that.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks

Hi Paul,
On 6/24/2024 8:09 PM, Fabio Estevam wrote:
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks
Can you take a look iMX8MP FIELD_RETURN fuse, I think it does not have 1 bit but 8 bits which requires to burn a sequence. Only when the bits sequence is matched, the field return can work. So checking the bit 0 is not enough.
Fuses for other platforms look ok.
Best regards,
Ye Li

Hi, Thanks for the feedback.
Hi Paul,
On 6/24/2024 8:09 PM, Fabio Estevam wrote:
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks
Can you take a look iMX8MP FIELD_RETURN fuse, I think it does not have 1 bit but 8 bits which requires to burn a sequence. Only when the bits sequence is matched, the field return can work. So checking the bit 0 is not enough.
Are you sure about that? The security reference manual (IMX8MPSRM) says in Table 5-5 that the FIELD_RETURN fuse is located on fuse 0x630[0], which is a single bit. Also, the "Chip Security Lifecycle" section (2.15.1) says the following:
FEILD RETURN (SEC_CONFIG[1] fuse = 1 and FIELD_RETURN fuse = 1)
Are you maybe confusing the FIELD_RETURN fuse with the FIELD_RETURN_LOCK sticky bit? clearing the lock bit _is_ quite the procedure, but it is unrelated to U-Boot, as this is done by ROM code through CSF.
I tested this on an i.MX8M Plus and it seems to work fine.
Fuses for other platforms look ok.
Best regards,
Ye Li

Hi Paul,
On 6/26/2024 3:17 PM, Paul Geurts wrote:
Hi, Thanks for the feedback.
Hi Paul,
On 6/24/2024 8:09 PM, Fabio Estevam wrote:
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks
Can you take a look iMX8MP FIELD_RETURN fuse, I think it does not have 1 bit but 8 bits which requires to burn a sequence. Only when the bits sequence is matched, the field return can work. So checking the bit 0 is not enough.
Are you sure about that? The security reference manual (IMX8MPSRM) says in Table 5-5 that the FIELD_RETURN fuse is located on fuse 0x630[0], which is a single bit. Also, the "Chip Security Lifecycle" section (2.15.1) says the following:
FEILD RETURN (SEC_CONFIG[1] fuse = 1 and FIELD_RETURN fuse = 1)
Are you maybe confusing the FIELD_RETURN fuse with the FIELD_RETURN_LOCK sticky bit? clearing the lock bit _is_ quite the procedure, but it is unrelated to U-Boot, as this is done by ROM code through CSF.
I tested this on an i.MX8M Plus and it seems to work fine.
I know the steps for field return. What I mean is the FIELD_RETURN fuse. It is true that security RM mentions it as you quote. But from 8MP fuse map and ROM codes, I get different things.
FIELD_RETURN 8-bit code. FIELD_RETURN = 0, is non-field return mode, functional/secure mode. FIELD_RETURN = Matching Sequence, device is in field_return mode FIELD_RETURN != Matching Sequence, device asserts security violation
However, I'm not sure how is it implemented in HAB. Since you have tested 8M plus, can you confirm the closed part is successfully converted to field return and can boot without signing?
Best regards,
Ye Li
Fuses for other platforms look ok.
Best regards,
Ye Li

Hi Ye,
Hi Paul,
On 6/26/2024 3:17 PM, Paul Geurts wrote:
Hi, Thanks for the feedback.
Hi Paul,
On 6/24/2024 8:09 PM, Fabio Estevam wrote:
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks
Can you take a look iMX8MP FIELD_RETURN fuse, I think it does not have 1 bit but 8 bits which requires to burn a sequence. Only when the bits sequence is matched, the field return can work. So checking the bit 0 is not enough.
Are you sure about that? The security reference manual (IMX8MPSRM) says in Table 5-5 that the FIELD_RETURN fuse is located on fuse 0x630[0], which is a single bit. Also, the "Chip Security Lifecycle" section (2.15.1) says the following:
FEILD RETURN (SEC_CONFIG[1] fuse = 1 and FIELD_RETURN fuse = 1)
Are you maybe confusing the FIELD_RETURN fuse with the FIELD_RETURN_LOCK sticky bit? clearing the lock bit _is_ quite the procedure, but it is unrelated to U-Boot, as this is done by ROM code through CSF.
I tested this on an i.MX8M Plus and it seems to work fine.
I know the steps for field return. What I mean is the FIELD_RETURN fuse. It is true that security RM mentions it as you quote. But from 8MP fuse map and ROM codes, I get different things.
FIELD_RETURN 8-bit code. FIELD_RETURN = 0, is non-field return mode, functional/secure mode. FIELD_RETURN = Matching Sequence, device is in field_return mode FIELD_RETURN != Matching Sequence, device asserts security violation
That is indeed different from what is mentioned in documentation. I have asked our NXP FAE about the discrepancy and I will adjust the code if needed.
However, I'm not sure how is it implemented in HAB. Since you have tested 8M plus, can you confirm the closed part is successfully converted to field return and can boot without signing?
Maybe I did something wrong while testing. I will retest it on a new board when I have received some more information from NXP.
Best regards,
Ye Li

Hi Paul,
On 7/1/2024 8:39 PM, Paul Geurts wrote:
Hi Ye,
Hi Paul,
On 6/26/2024 3:17 PM, Paul Geurts wrote:
Hi, Thanks for the feedback.
Hi Paul,
On 6/24/2024 8:09 PM, Fabio Estevam wrote:
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
-struct imx_sec_config_fuse_t { +struct imx_fuse_t {
Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks
Can you take a look iMX8MP FIELD_RETURN fuse, I think it does not have 1 bit but 8 bits which requires to burn a sequence. Only when the bits sequence is matched, the field return can work. So checking the bit 0 is not enough.
Are you sure about that? The security reference manual (IMX8MPSRM) says in Table 5-5 that the FIELD_RETURN fuse is located on fuse 0x630[0], which is a single bit. Also, the "Chip Security Lifecycle" section (2.15.1) says the following:
FEILD RETURN (SEC_CONFIG[1] fuse = 1 and FIELD_RETURN fuse = 1)
Are you maybe confusing the FIELD_RETURN fuse with the FIELD_RETURN_LOCK sticky bit? clearing the lock bit _is_ quite the procedure, but it is unrelated to U-Boot, as this is done by ROM code through CSF.
I tested this on an i.MX8M Plus and it seems to work fine.
I know the steps for field return. What I mean is the FIELD_RETURN fuse. It is true that security RM mentions it as you quote. But from 8MP fuse map and ROM codes, I get different things.
FIELD_RETURN 8-bit code. FIELD_RETURN = 0, is non-field return mode, functional/secure mode. FIELD_RETURN = Matching Sequence, device is in field_return mode FIELD_RETURN != Matching Sequence, device asserts security violation
That is indeed different from what is mentioned in documentation. I have asked our NXP FAE about the discrepancy and I will adjust the code if needed.
Thanks for confirm. I also cross checked with teams. 8MP must burn a pattern. Otherwise HAB won't covert to field return.
Additional, do you think it is very necessary to add this patch set? Because field return is a pure debug feature, it won't be deployed on productions. The developers working on field return parts can re-build u-boot with CONFIG_IMX_HAB disabled.
This patch may introduce risk to HAB in some sense, especially for productions. One mistake would make unsigned image bypass authentication result.
Best regards,
Ye Li
However, I'm not sure how is it implemented in HAB. Since you have tested 8M plus, can you confirm the closed part is successfully converted to field return and can boot without signing?
Maybe I did something wrong while testing. I will retest it on a new board when I have received some more information from NXP.
Best regards,
Ye Li

Hi Ye,
Hi Paul,
On 7/1/2024 8:39 PM, Paul Geurts wrote:
Hi Ye,
Hi Paul,
On 6/26/2024 3:17 PM, Paul Geurts wrote:
Hi, Thanks for the feedback.
Hi Paul,
On 6/24/2024 8:09 PM, Fabio Estevam wrote:
Hi Paul,
On Fri, Jun 21, 2024 at 10:06 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
> -struct imx_sec_config_fuse_t { > +struct imx_fuse_t { Please make the struct renaming a separate patch.
Peng Fan, Ye Li,
Could you please help review this patch?
Thanks
Can you take a look iMX8MP FIELD_RETURN fuse, I think it does not have 1 bit but 8 bits which requires to burn a sequence. Only when the bits sequence is matched, the field return can work. So checking the bit 0 is not enough.
Are you sure about that? The security reference manual (IMX8MPSRM) says in Table 5-5 that the FIELD_RETURN fuse is located on fuse 0x630[0], which is a single bit. Also, the "Chip Security Lifecycle" section (2.15.1) says the following:
FEILD RETURN (SEC_CONFIG[1] fuse = 1 and FIELD_RETURN fuse = 1)
Are you maybe confusing the FIELD_RETURN fuse with the FIELD_RETURN_LOCK sticky bit? clearing the lock bit _is_ quite the procedure, but it is unrelated to U-Boot, as this is done by ROM code through CSF.
I tested this on an i.MX8M Plus and it seems to work fine.
I know the steps for field return. What I mean is the FIELD_RETURN fuse. It is true that security RM mentions it as you quote. But from 8MP fuse map and ROM codes, I get different things.
FIELD_RETURN 8-bit code. FIELD_RETURN = 0, is non-field return mode, functional/secure mode. FIELD_RETURN = Matching Sequence, device is in field_return mode FIELD_RETURN != Matching Sequence, device asserts security violation
That is indeed different from what is mentioned in documentation. I have asked our NXP FAE about the discrepancy and I will adjust the code if needed.
Thanks for confirm. I also cross checked with teams. 8MP must burn a pattern. Otherwise HAB won't covert to field return.
Okay, thanks for checking, I will wait for the details and make the necessary adjustments
Additional, do you think it is very necessary to add this patch set? Because field return is a pure debug feature, it won't be deployed on productions. The developers working on field return parts can re-build u-boot with CONFIG_IMX_HAB disabled.
In an OEM situation, is a lot of cases, the company creating the bootloader (OEM) is typically neither the one singing the bootloader nor performing the FIELD_RETURN setting (end customer/VAR). The end customer is typically neither interested nor capable of rebuilding the bootloader with CONFIG_IMX_HAB disabled.
This means 2 bootloaders need to be maintained in parallel by the OEM, creating unnecessary overhead. This also introduces additional risk as the end customer may sign the wrong bootloader (with HAB disabled).
This patch may introduce risk to HAB in some sense, especially for productions. One mistake would make unsigned image bypass authentication result.
I think this risk is mitigated by the fuse unlocking procedure imposed by HAB. I don't think someone will accidentally go through the entire procedure of unlocking the FIELD_RETURN fuse and then also accidentally burning the fuse. The risk in code IMO is not greater then the risk already there by reading out the SEC_CONFIG fuse.
Best regards,
Ye Li
However, I'm not sure how is it implemented in HAB. Since you have tested 8M plus, can you confirm the closed part is successfully converted to field return and can boot without signing?
Maybe I did something wrong while testing. I will retest it on a new board when I have received some more information from NXP.
Best regards,
Ye Li

Hi Ye Li,
On Tue, Jul 2, 2024 at 6:09 AM Paul Geurts paul.geurts@prodrive-technologies.com wrote:
Thanks for confirm. I also cross checked with teams. 8MP must burn a pattern. Otherwise HAB won't covert to field return.
Okay, thanks for checking, I will wait for the details and make the necessary adjustments
Please let us know if you have more information on this so we can proceed with this patch.
Thanks

Hi Paul,
On Thu, Jul 18, 2024 at 2:02 PM Fabio Estevam festevam@gmail.com wrote:
Okay, thanks for checking, I will wait for the details and make the necessary adjustments
Please let us know if you have more information on this so we can proceed with this patch.
Please re-send this series whenever you receive a confirmation from NXP.
Thanks
participants (4)
-
Fabio Estevam
-
Marek Vasut
-
Paul Geurts
-
Ye Li