ARM: bootm: Add support for starting Linux through OPTEE-OS on ARMv7a

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>
This commit is contained in:
Marek Vasut
2025-10-30 22:23:49 +01:00
committed by Tom Rini
parent 08bf42e1fa
commit 20861863eb
6 changed files with 159 additions and 9 deletions

View 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[];

View 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

View File

@@ -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)

View 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);
}
#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

View 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

View File

@@ -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 */
};
};
};