diff mbox series

[1/2] ARM: bootm: Add support for starting Linux through OpTee-OS on ARMv7a

Message ID 20250512165307.148434-1-marek.vasut@mailbox.org
State Changes Requested
Delegated to: Tom Rini
Headers show
Series [1/2] ARM: bootm: Add support for starting Linux through OpTee-OS on ARMv7a | expand

Commit Message

Marek Vasut May 12, 2025, 4:52 p.m. UTC
Add support for jumping to Linux kernel through OpTee-OS on ARMv7a.
This is only supported if U-Boot runs in PL1 secure. This change adds
two components, one is fitImage OpTee-OS loadable handler, which makes
a note of OpTee-OS being loaded and stores the load address for later
jump to it. The second part is the actual jump to Linux through OpTee-OS.
The jump through OpTee-OS requires set up of multiple CPU registers, r1
and r2 are passed through, r0 and r3 have to be set to 0, lr is set to
Linux kernel entry point. This setup is done by new assembler function
boot_jump_linux_via_optee().

The boot_jump_linux_via_optee() also includes STM32MP13xx late TZC
configuration write, this cannot be moved easily, hence the ifdef.

Signed-off-by: Marek Vasut <marek.vasut@mailbox.org>
---
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Janne Grunau <j@jannau.net>
Cc: Mattijs Korpershoek <mkorpershoek@kernel.org>
Cc: Patrick Rudolph <patrick.rudolph@9elements.com>
Cc: Sam Edwards <cfsworks@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: u-boot@lists.denx.de
---
 arch/arm/include/asm/armv7.h |  2 ++
 arch/arm/lib/Makefile        |  3 +++
 arch/arm/lib/bootm-optee.S   | 30 +++++++++++++++++++++++
 arch/arm/lib/bootm.c         | 47 +++++++++++++++++++++++++++---------
 4 files changed, 71 insertions(+), 11 deletions(-)
 create mode 100644 arch/arm/lib/bootm-optee.S

Comments

Tom Rini June 5, 2025, 9:48 p.m. UTC | #1
On Mon, May 12, 2025 at 06:52:12PM +0200, Marek Vasut wrote:

> Add support for jumping to Linux kernel through OpTee-OS on ARMv7a.
> This is only supported if U-Boot runs in PL1 secure. This change adds
> two components, one is fitImage OpTee-OS loadable handler, which makes
> a note of OpTee-OS being loaded and stores the load address for later
> jump to it. The second part is the actual jump to Linux through OpTee-OS.
> The jump through OpTee-OS requires set up of multiple CPU registers, r1
> and r2 are passed through, r0 and r3 have to be set to 0, lr is set to
> Linux kernel entry point. This setup is done by new assembler function
> boot_jump_linux_via_optee().
> 
> The boot_jump_linux_via_optee() also includes STM32MP13xx late TZC
> configuration write, this cannot be moved easily, hence the ifdef.
> 
> Signed-off-by: Marek Vasut <marek.vasut@mailbox.org>

The lack of a cover letter isn't the final problem, because I could
summarize this easily enough. However, this causes a large number of
targets to now have warnings, such as imx8mp-icore-mx8mp-edimm2.2 and
gxp.
diff mbox series

Patch

diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
index c002998ac0b..bfffbbd5d9a 100644
--- a/arch/arm/include/asm/armv7.h
+++ b/arch/arm/include/asm/armv7.h
@@ -142,6 +142,8 @@  bool armv7_boot_nonsec(void);
 unsigned int _nonsec_init(void);
 void _do_nonsec_entry(void *target_pc, unsigned long r0,
 		      unsigned long r1, unsigned long r2);
+void boot_jump_linux_via_optee(void *target_pc, unsigned long r1,
+			       unsigned long r2, unsigned long tee_entry);
 void _smp_pen(void);
 
 extern char __secure_start[];
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index ade42d0ca43..92149d7058c 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -41,6 +41,9 @@  obj-$(CONFIG_CMD_BOOTZ) += zimage.o
 endif
 obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
 endif
+ifndef CONFIG_ARM64
+obj-$(CONFIG_BOOTM_OPTEE) += bootm-optee.o
+endif
 ifdef CONFIG_ARM64
 obj-$(CONFIG_$(PHASE_)USE_ARCH_MEMSET) += memset-arm64.o
 obj-$(CONFIG_$(PHASE_)USE_ARCH_MEMCPY) += memcpy-arm64.o
diff --git a/arch/arm/lib/bootm-optee.S b/arch/arm/lib/bootm-optee.S
new file mode 100644
index 00000000000..9d1a77b563d
--- /dev/null
+++ b/arch/arm/lib/bootm-optee.S
@@ -0,0 +1,30 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  Copyright (C) 2025 Marek Vasut
+ */
+#include <config.h>
+#include <linux/linkage.h>
+
+ENTRY(boot_jump_linux_via_optee)
+	mov	r4, r3
+	mov	lr, r0
+	mov	r3, #0
+	mov	r0, #0
+
+	/*
+	 * Special TZC handling on this platform, the last
+	 * 'str' has to be immediately before 'bx' and can
+	 * not be interleaved with any return from function
+	 * call, if it is then the system hangs.
+	 */
+#if defined(CONFIG_STM32MP13X) && !defined(CONFIG_TFABOOT)
+	ldr	r6, =STM32_TZC_BASE + 0x114 + (0x20 * 2)
+	mov	r7, #0x0
+	str	r7, [r6]
+	ldr	r6, =STM32_TZC_BASE + 0x110 + (0x20 * 1)
+	mov	r7, #0x1
+	str	r7, [r6]
+#endif
+
+	bx	r4
+ENDPROC(boot_jump_linux_via_optee)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 7eb764e1f4e..f5343217505 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -283,9 +283,9 @@  static void switch_to_el1(void)
 #endif
 
 /* Subcommand: GO */
+#ifdef CONFIG_ARM64
 static void boot_jump_linux(struct bootm_headers *images, int flag)
 {
-#ifdef CONFIG_ARM64
 	void (*kernel_entry)(void *fdt_addr, void *res0, void *res1,
 			void *res2);
 	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
@@ -323,7 +323,13 @@  static void boot_jump_linux(struct bootm_headers *images, int flag)
 					    ES_TO_AARCH64);
 #endif
 	}
+}
 #else
+static bool boot_jump_via_optee;
+static unsigned long boot_jump_via_optee_addr;
+
+static void boot_jump_linux(struct bootm_headers *images, int flag)
+{
 	unsigned long machid = gd->bd->bi_arch_number;
 	char *s;
 	void (*kernel_entry)(int zero, int arch, uint params);
@@ -335,6 +341,13 @@  static void boot_jump_linux(struct bootm_headers *images, int flag)
 	ulong addr = (ulong)kernel_entry | 1;
 	kernel_entry = (void *)addr;
 #endif
+
+	if (IS_ENABLED(CONFIG_ARMV7_NONSEC) && armv7_boot_nonsec() &&
+	    boot_jump_via_optee) {
+		printf("Cannot start OpTee-OS from NS\n");
+		return;
+	}
+
 	s = env_get("machid");
 	if (s) {
 		if (strict_strtoul(s, 16, &machid) < 0) {
@@ -354,19 +367,31 @@  static void boot_jump_linux(struct bootm_headers *images, int flag)
 	else
 		r2 = gd->bd->bi_boot_params;
 
-	if (!fake) {
-#ifdef CONFIG_ARMV7_NONSEC
-		if (armv7_boot_nonsec()) {
-			armv7_init_nonsec();
-			secure_ram_addr(_do_nonsec_entry)(kernel_entry,
-							  0, machid, r2);
-		} else
-#endif
-			kernel_entry(0, machid, r2);
+	if (fake)
+		return;
+
+	if (armv7_boot_nonsec())
+		armv7_init_nonsec();
+
+	if (boot_jump_via_optee)
+		boot_jump_linux_via_optee(kernel_entry, machid, r2, boot_jump_via_optee_addr);
+
+	if (IS_ENABLED(CONFIG_ARMV7_NONSEC) && armv7_boot_nonsec()) {
+		armv7_init_nonsec();
+		secure_ram_addr(_do_nonsec_entry)(kernel_entry, 0, machid, r2);
+	} else {
+		kernel_entry(0, machid, r2);
 	}
-#endif
 }
 
+static void arch_tee_image_process(ulong image, size_t size)
+{
+	boot_jump_via_optee = true;
+	boot_jump_via_optee_addr = image;
+}
+U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_TEE, arch_tee_image_process);
+#endif
+
 /* Main Entry point for arm bootm implementation
  *
  * Modeled after the powerpc implementation