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 +#include + +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 b874aa252c6..019eca95780 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -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); } -#endif } +#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 diff --git a/doc/usage/fit/index.rst b/doc/usage/fit/index.rst index a822bf20cb2..6c78d8584ed 100644 --- a/doc/usage/fit/index.rst +++ b/doc/usage/fit/index.rst @@ -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 index 00000000000..07587710fe5 --- /dev/null +++ b/doc/usage/fit/kernel_fdt_optee.rst @@ -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 */ + }; + }; + };