]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
ARM: bootm: Add support for starting Linux through OPTEE-OS on ARMv7a
authorMarek Vasut <marek.vasut@mailbox.org>
Thu, 30 Oct 2025 21:23:49 +0000 (22:23 +0100)
committerTom Rini <trini@konsulko.com>
Thu, 6 Nov 2025 17:26:18 +0000 (11:26 -0600)
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>
arch/arm/include/asm/armv7.h
arch/arm/lib/Makefile
arch/arm/lib/bootm-optee.S [new file with mode: 0644]
arch/arm/lib/bootm.c
doc/usage/fit/index.rst
doc/usage/fit/kernel_fdt_optee.rst [new file with mode: 0644]

index c002998ac0be7f896d9f610cce4e7b54cfd912d7..bfffbbd5d9ab84827cce97edf22a1984b3d7afe1 100644 (file)
@@ -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[];
index ade42d0ca4370b7df3aec59615f12e28a96874cd..92149d7058c6deeb9a2614199618e6a795b69f56 100644 (file)
@@ -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 (file)
index 0000000..9d1a77b
--- /dev/null
@@ -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)
index b874aa252c6d603b7dd06e3b2075e8de75800c70..019eca95780965416fb3a9ca3abf2036e8dc5839 100644 (file)
@@ -259,6 +259,11 @@ bool armv7_boot_nonsec(void)
 
        return nonsec;
 }
+#else
+bool armv7_boot_nonsec(void)
+{
+       return false;
+}
 #endif
 
 #ifdef CONFIG_ARM64
@@ -284,9 +289,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);
@@ -324,7 +329,13 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
                                            ES_TO_AARCH64);
 #endif
        }
+}
 #else
+static __maybe_unused bool boot_jump_via_optee;
+static __maybe_unused 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);
@@ -336,6 +347,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) {
@@ -355,19 +373,39 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
        else
                r2 = gd->bd->bi_boot_params;
 
-       if (!fake) {
+       if (fake)
+               return;
+
 #ifdef CONFIG_ARMV7_NONSEC
-               if (armv7_boot_nonsec()) {
-                       armv7_init_nonsec();
-                       secure_ram_addr(_do_nonsec_entry)(kernel_entry,
-                                                         0, machid, r2);
-               } else
+       if (armv7_boot_nonsec())
+               armv7_init_nonsec();
 #endif
-                       kernel_entry(0, machid, r2);
-       }
+
+#ifdef CONFIG_BOOTM_OPTEE
+       if (boot_jump_via_optee)
+               boot_jump_linux_via_optee(kernel_entry, machid, r2, boot_jump_via_optee_addr);
+#endif
+
+#ifdef CONFIG_ARMV7_NONSEC
+       if (armv7_boot_nonsec()) {
+               secure_ram_addr(_do_nonsec_entry)(kernel_entry, 0, machid, r2);
+       } else
 #endif
+       {
+               kernel_entry(0, machid, r2);
+       }
 }
 
+#ifndef CONFIG_TI_SECURE_DEVICE
+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
+#endif
+
 /* Main Entry point for arm bootm implementation
  *
  * Modeled after the powerpc implementation
index a822bf20cb25cde0e1828a66f561bc99526e2e42..6c78d8584ed083bb1a668583390e4c05b390956c 100644 (file)
@@ -14,6 +14,7 @@ images that it reads and boots. Documentation about FIT is available in
     howto
     kernel_fdt
     kernel_fdts_compressed
+    kernel_fdt_optee
     kernel
     multi
     multi_spl
diff --git a/doc/usage/fit/kernel_fdt_optee.rst b/doc/usage/fit/kernel_fdt_optee.rst
new file mode 100644 (file)
index 0000000..0758771
--- /dev/null
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Single kernel, FDT blob and OPTEE-OS
+====================================
+
+Example FIT image description file demonstrating the usage of the
+bootm command to launch OPTEE-OS before starting Linux kernel on
+STM32MP13xx.
+
+::
+
+    /dts-v1/;
+
+    / {
+        description = "Simple image with single Linux kernel and FDT blob";
+        #address-cells = <1>;
+
+        images {
+            kernel {
+                description = "Vanilla Linux kernel";
+                data = /incbin/("./arch/arm/boot/zImage");
+                type = "kernel";
+                arch = "arm";
+                os = "linux";
+                compression = "none";
+                load = <0xc0008000>;
+                entry = <0xc0008000>;
+                hash-1 {
+                    algo = "crc32";
+                };
+                hash-2 {
+                    algo = "sha256";
+                };
+            };
+            fdt-1 {
+                description = "Flattened Device Tree blob";
+                data = /incbin/("./arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dtb");
+                type = "flat_dt";
+                arch = "arm";
+                compression = "none";
+                hash-1 {
+                    algo = "crc32";
+                };
+                hash-2 {
+                    algo = "sha256";
+                };
+            };
+            /* Bundled OPTEE-OS */
+            tee-1 {
+                description = "OP-TEE";
+                data = /incbin/("/path/to/optee_os/out/arm-plat-stm32mp1/core/tee-raw.bin");
+                type = "tee";
+                arch = "arm";
+                compression = "none";
+                os = "tee";
+                load = <0xde000000>;
+                entry = <0xde000000>;
+                hash-1 {
+                    algo = "crc32";
+                };
+                hash-2 {
+                    algo = "sha256";
+                };
+            };
+        };
+
+        configurations {
+            default = "conf-1";
+            conf-1 {
+                description = "Boot Linux kernel with FDT blob";
+                kernel = "kernel";
+                fdt = "fdt-1";
+                loadables = "tee-1"; /* OPTEE-OS */
+            };
+        };
+    };