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>
Fri, 11 Oct 2019 08:36:07 +0000 (01:36 -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)

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

index a970127..4c0d8cb 100644 (file)
@@ -21,6 +21,16 @@ config IMX8MN
        bool
        select IMX8M
 
+config SECURE_STICKY_BITS_LOCKUP
+       bool "Enable workaround to fix sticky bits lock up issue"
+       depends on IMX8MQ && SECURE_BOOT
+       default y
+
+config IMX_UNIQUE_ID
+       hex "Enable workaround to fix sticky bits lock up issue"
+       depends on IMX8MQ && SECURE_BOOT && !SECURE_STICKY_BITS_LOCKUP
+       default 0x0
+
 choice
        prompt  "NXP i.MX8M board select"
        optional
index 668498a..4c2cbee 100644 (file)
@@ -21,6 +21,7 @@
 #include <imx_sip.h>
 #include <generated/version_autogenerated.h>
 #include <asm/setup.h>
+#include <asm/bootm.h>
 #ifdef CONFIG_IMX_SEC_INIT
 #include <fsl_caam.h>
 #endif
@@ -279,6 +280,56 @@ static void imx_set_wdog_powerdown(bool enable)
        writew(enable, &wdog3->wmcr);
 }
 
+#ifdef CONFIG_SECURE_BOOT
+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;
@@ -294,6 +345,9 @@ int arch_cpu_init(void)
                clock_init();
                imx_set_wdog_powerdown(false);
 
+#ifdef CONFIG_SECURE_BOOT
+               secure_lockup();
+#endif
                if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() || is_imx8mmsl() ||
                        is_imx8mnd() || is_imx8mndl() || is_imx8mns() || is_imx8mnsl()) {
                        /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */