MLK-22749 imx8mq: Add workaround to fix sticky bits lock up
authorYe Li <ye.li@nxp.com>
Tue, 27 Aug 2019 06:39:57 +0000 (23:39 -0700)
committerYe Li <ye.li@nxp.com>
Thu, 29 Apr 2021 07:56:33 +0000 (00:56 -0700)
On B1 chips with HAB v4.4, the sticky bits are not locked up in
HAB closed mode. We introduce a workaround in SPL to lock up
these bits and clear Manufacturing Protection Private Key for
secure boot.

For field return case, user has to build a SPL with
CONFIG_SECURE_STICKY_BITS_LOCKUP=n and set CONFIG_IMX_UNIQUE_ID to
part's unique id. When the UID check is passed, sticky bits are not
lockup and users can burn field return fuse. Otherwise the boot will
stop.

Signed-off-by: Ye Li <ye.li@nxp.com>
(cherry picked from commit c98b47f1ff60e1f99807e24fd76053ad880f803e)
(cherry picked from commit ce78751b8428228f32b77386cc6e9be8bcbba470)

arch/arm/mach-imx/imx8m/Kconfig
arch/arm/mach-imx/imx8m/soc.c

index d279e2b..f5ef09b 100644 (file)
@@ -27,6 +27,16 @@ config IMX8MP
 config SYS_SOC
        default "imx8m"
 
+config SECURE_STICKY_BITS_LOCKUP
+       bool "Enable workaround to fix sticky bits lock up issue"
+       depends on IMX8MQ && IMX_HAB
+       default y
+
+config IMX_UNIQUE_ID
+       hex "Enable workaround to fix sticky bits lock up issue"
+       depends on IMX8MQ && IMX_HAB && !SECURE_STICKY_BITS_LOCKUP
+       default 0x0
+
 choice
        prompt  "NXP i.MX8M board select"
        optional
index 4fff36c..a19f3f9 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/arm-smccc.h>
 #include <linux/bitops.h>
 #include <asm/setup.h>
+#include <asm/bootm.h>
 #ifdef CONFIG_IMX_SEC_INIT
 #include <fsl_caam.h>
 #endif
@@ -459,6 +460,56 @@ int arch_cpu_init_dm(void)
        return 0;
 }
 
+#if defined(CONFIG_IMX_HAB) && defined(CONFIG_IMX8MQ)
+static bool is_hdmi_fused(void) {
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[1];
+       struct fuse_bank1_regs *fuse =
+               (struct fuse_bank1_regs *)bank->fuse_regs;
+
+       u32 value = readl(&fuse->tester4);
+
+       if (is_imx8mq()) {
+               if (value & 0x02000000)
+                       return true;
+       }
+
+       return false;
+}
+
+bool is_uid_matched(u64 uid) {
+       struct tag_serialnr nr;
+       get_board_serial(&nr);
+
+       if (lower_32_bits(uid) == nr.low &&
+               upper_32_bits(uid) == nr.high)
+               return true;
+
+       return false;
+}
+
+static void secure_lockup(void)
+{
+       if (is_imx8mq() && is_soc_rev(CHIP_REV_2_1) &&
+               imx_hab_is_enabled() && !is_hdmi_fused()) {
+#ifdef CONFIG_SECURE_STICKY_BITS_LOCKUP
+               struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+
+               clock_enable(CCGR_OCOTP, 1);
+               setbits_le32(&ocotp->sw_sticky, 0x6); /* Lock up field return and SRK revoke */
+               writel(0x80000000, &ocotp->scs_set); /* Lock up SCS */
+
+               /* Clear mfg prot private key in CAAM */
+               setbits_le32((ulong)(CONFIG_SYS_FSL_SEC_ADDR + 0xc), 0x08000000);
+#else
+               /* Check the Unique ID, if it is matched with UID config, then allow to leave sticky bits unlocked */
+               if (!is_uid_matched(CONFIG_IMX_UNIQUE_ID))
+                       hang();
+#endif
+       }
+}
+#endif
+
 int arch_cpu_init(void)
 {
        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
@@ -478,6 +529,9 @@ int arch_cpu_init(void)
                clock_init();
                imx_set_wdog_powerdown(false);
 
+#if defined(CONFIG_IMX_HAB) && defined(CONFIG_IMX8MQ)
+               secure_lockup();
+#endif
                if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
                    is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
                    is_imx8mnsl() || is_imx8mpd()) {