From: Ana Bobillo <[email protected]>

The SDP gadget implements the serial download protocol of the i.MX boot
ROM, but always reports SDP_SECURITY_OPEN in its HAB security report
(report 3), also on a part whose secure boot is fused closed, where the
ROM reports SDP_SECURITY_CLOSED.

Add sdp_is_closed(), a weak hook that says whether secure boot is
enforced, false by default so that other platforms are unchanged, and
implement it for i.MX:

- HAB parts (i.MX6/7/7ULP/8M): imx_hab_is_enabled(), the secure boot
  fuse minus a field return; a fuse read error counts as closed;
- ELE AHAB parts (i.MX8ULP/9): the OEM closed and OEM locked
  lifecycles, and on i.MX94/95/952 also OEM secure world closed, read
  from the same FSB register as ahab_status.

The SECO AHAB parts (i.MX8QM/QXP) keep the weak default; none of their
in-tree defconfigs enables SDP.

Use it for the security report. The next patch makes the gadget refuse
what the ROM refuses on a closed part.

Signed-off-by: Ana Bobillo <[email protected]>
---
 arch/arm/mach-imx/ele_ahab.c | 13 +++++++++++++
 arch/arm/mach-imx/hab.c      |  7 +++++++
 drivers/usb/gadget/f_sdp.c   |  7 ++++++-
 include/sdp.h                | 19 +++++++++++++++++++
 4 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c
index e1284833ac5..abbaf70682d 100644
--- a/arch/arm/mach-imx/ele_ahab.c
+++ b/arch/arm/mach-imx/ele_ahab.c
@@ -14,6 +14,7 @@
 #include <asm/arch/sys_proto.h>
 #include <console.h>
 #include <cpu_func.h>
+#include <sdp.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -414,6 +415,8 @@ static int do_authenticate(struct cmd_tbl *cmdtp, int flag, 
int argc,
 #if IS_ENABLED(CONFIG_IMX95) || IS_ENABLED(CONFIG_IMX94) || 
IS_ENABLED(CONFIG_IMX952)
 #define FSB_LC_OFFSET 0x414
 #define LC_OEM_OPEN 0x10
+/* OEM secure world closed, OEM closed, OEM locked */
+#define LC_OEM_CLOSED (0x20 | 0x40 | 0x80)
 static void display_life_cycle(u32 lc)
 {
        printf("Lifecycle: 0x%08X, ", lc);
@@ -459,6 +462,8 @@ static void display_life_cycle(u32 lc)
 #else
 #define FSB_LC_OFFSET 0x41c
 #define LC_OEM_OPEN 0x8
+/* OEM closed, OEM locked */
+#define LC_OEM_CLOSED (0x20 | 0x100)
 static void display_life_cycle(u32 lc)
 {
        printf("Lifecycle: 0x%08X, ", lc);
@@ -497,6 +502,14 @@ static void display_life_cycle(u32 lc)
 }
 #endif
 
+/* Secure boot is enforced: the SDP gadget then behaves as the ROM's does */
+bool sdp_is_closed(void)
+{
+       u32 lc = readl(FSB_BASE_ADDR + FSB_LC_OFFSET) & 0x3ff;
+
+       return lc & LC_OEM_CLOSED;
+}
+
 static int confirm_close(void)
 {
        puts("Warning: Please ensure your sample is in NXP closed state, "
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index 35c497619d6..78c85081055 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -16,6 +16,7 @@
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/hab.h>
 #include <linux/arm-smccc.h>
+#include <sdp.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -932,6 +933,12 @@ bool imx_hab_is_enabled(void)
        return is_enabled;
 }
 
+/* Secure boot is enforced: the SDP gadget then behaves as the ROM's does */
+bool sdp_is_closed(void)
+{
+       return imx_hab_is_enabled();
+}
+
 int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
                               uint32_t ivt_offset)
 {
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index aff69c3a138..8bd8f239766 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -288,6 +288,11 @@ static inline void *sdp_ptr(u32 val)
        return (void *)(uintptr_t)val;
 }
 
+__weak bool sdp_is_closed(void)
+{
+       return false;
+}
+
 static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req)
 {
        struct f_sdp *sdp = req->context;
@@ -801,7 +806,7 @@ static int sdp_handle_in_ep(struct spl_image_info 
*spl_image,
                debug("Report 3: HAB security\n");
                data[0] = 3;
 
-               status = SDP_SECURITY_OPEN;
+               status = sdp_is_closed() ? SDP_SECURITY_CLOSED : 
SDP_SECURITY_OPEN;
                memcpy(&data[1], &status, 4);
                sdp_func->in_req->length = 5;
                usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
diff --git a/include/sdp.h b/include/sdp.h
index 0a97f28073a..829f20ab4ef 100644
--- a/include/sdp.h
+++ b/include/sdp.h
@@ -9,8 +9,27 @@
 #ifndef __SDP_H_
 #define __SDP_H_
 
+#include <linux/types.h>
+
+struct udevice;
+
 int sdp_init(struct udevice *udc);
 
+/**
+ * sdp_is_closed() - Tell whether secure boot is enforced on this part
+ *
+ * The SDP gadget emulates the i.MX boot ROM's serial download mode. On a
+ * part with secure boot fused (HAB closed, AHAB OEM closed), the ROM refuses
+ * the operations that would bypass the signature chain, and SDP has to do the
+ * same, or it is a way around secure boot on an otherwise locked device.
+ *
+ * The weak default says open; i.MX code overrides it per secure boot
+ * mechanism.
+ *
+ * Return: true if the part is closed, false otherwise
+ */
+bool sdp_is_closed(void);
+
 #ifdef CONFIG_XPL_BUILD
 #include <spl.h>
 

Reply via email to