diff options
-rw-r--r-- | Documentation/user/optee.rst | 29 | ||||
-rw-r--r-- | Documentation/user/user-manual.rst | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/barebox-arm.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/setjmp.h | 29 | ||||
-rw-r--r-- | arch/arm/lib32/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/lib32/bootm.c | 12 | ||||
-rw-r--r-- | arch/arm/lib32/optee-early.c | 38 | ||||
-rw-r--r-- | arch/arm/lib32/setjmp.S | 36 | ||||
-rw-r--r-- | arch/arm/lib64/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/lib64/setjmp.S | 40 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx6.c | 20 | ||||
-rw-r--r-- | common/Kconfig | 54 | ||||
-rw-r--r-- | common/Makefile | 2 | ||||
-rw-r--r-- | common/optee.c | 23 | ||||
-rw-r--r-- | include/asm-generic/memory_layout.h | 4 | ||||
-rw-r--r-- | include/tee/optee.h | 11 |
16 files changed, 273 insertions, 33 deletions
diff --git a/Documentation/user/optee.rst b/Documentation/user/optee.rst new file mode 100644 index 0000000000..950917b446 --- /dev/null +++ b/Documentation/user/optee.rst @@ -0,0 +1,29 @@ + +.. _optee: + +OP-TEE +====== + +Barebox is able to start the Open Portable Trusted Execution Environment +(OP-TEE) either before starting the linux kernel or during lowlevel board +initialization in the Pre Bootloader ``PBL``. + +Before Linux start +------------------ +Enable the `CONFIG_BOOTM_OPTEE` configuration variable and configure the +`CONFIG_OPTEE_SIZE` variable. This will reserve a memory area at the end +of memory for OP-TEE to run, usually Barebox would relocate itself there. To +load OP-TEE before the kernel is started, configure the global ``bootm.tee`` +variable to point to a valid OPTEE v1 binary. + +During the PBL +-------------- +To start OP-TEE during the lowlevel initialization of your board in the ``PBL``, +enable the ``CONFIG_PBL_OPTEE`` configuration variable. your board should then +call the function ``start_optee_early(void* tee, void* fdt)`` with a valid tee +and FDT. Ensure that your OP-TEE is compiled with ``CFG_NS_ENTRY_ADDR`` unset, +otherwise OP-TEE will not correctly return to barebox after startup. +Since OP-TEE in the default configuration also modifies the device tree, don't +pass the barebox internal device tree, instead copy it into a different memory +location and pass it to OP-TEE afterwards. +The modified device tree can then be passed to the main barebox start function. diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst index 41fdb8805c..827683eaa0 100644 --- a/Documentation/user/user-manual.rst +++ b/Documentation/user/user-manual.rst @@ -33,6 +33,7 @@ Contents: system-reset state random + optee debugging watchdog diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h index 8b2ecd9ab2..599852d644 100644 --- a/arch/arm/include/asm/barebox-arm.h +++ b/arch/arm/include/asm/barebox-arm.h @@ -119,7 +119,7 @@ void *barebox_arm_boot_dtb(void); static inline unsigned long arm_mem_stack_top(unsigned long membase, unsigned long endmem) { - if (IS_ENABLED(CONFIG_BOOTM_OPTEE)) + if (IS_ENABLED(CONFIG_BOOTM_OPTEE) || IS_ENABLED(CONFIG_PBL_OPTEE)) endmem -= OPTEE_SIZE; return endmem - SZ_64K; diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h new file mode 100644 index 0000000000..62bac613d6 --- /dev/null +++ b/arch/arm/include/asm/setjmp.h @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH + * (C) Copyright 2016 Alexander Graf <agraf@suse.de> + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1 + +#include <asm/types.h> + +/* + * This really should be opaque, but the EFI implementation wrongly + * assumes that a 'struct jmp_buf_data' is defined. + */ +struct jmp_buf_data { +#if defined(__aarch64__) + u64 regs[13]; +#else + u32 regs[10]; /* r4-r9, sl, fp, sp, lr */ +#endif +}; + +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf jmp); +void longjmp(jmp_buf jmp, int ret); + +#endif /* _SETJMP_H_ */ diff --git a/arch/arm/lib32/Makefile b/arch/arm/lib32/Makefile index cd43147e66..597bc07905 100644 --- a/arch/arm/lib32/Makefile +++ b/arch/arm/lib32/Makefile @@ -28,3 +28,7 @@ extra-y += barebox.lds pbl-y += lib1funcs.o pbl-y += ashldi3.o pbl-y += div0.o + +obj-pbl-y += setjmp.o + +pbl-$(CONFIG_PBL_OPTEE) += optee-early.o diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c index 180624445d..d64e705c40 100644 --- a/arch/arm/lib32/bootm.c +++ b/arch/arm/lib32/bootm.c @@ -137,16 +137,10 @@ static int get_kernel_addresses(size_t image_size, static int optee_verify_header_request_region(struct image_data *data, struct optee_header *hdr) { int ret = 0; - if (hdr->magic != OPTEE_MAGIC) { - pr_err("Invalid header magic 0x%08x, expected 0x%08x\n", - hdr->magic, OPTEE_MAGIC); - return -EINVAL; - } - if (hdr->arch != OPTEE_ARCH_ARM32 || hdr->init_load_addr_hi) { - pr_err("Only 32bit supported\n"); - return -EINVAL; - } + ret = optee_verify_header(hdr); + if (ret < 0) + return ret; data->tee_res = request_sdram_region("TEE", hdr->init_load_addr_lo, hdr->init_size); if (!data->tee_res) { diff --git a/arch/arm/lib32/optee-early.c b/arch/arm/lib32/optee-early.c new file mode 100644 index 0000000000..197325b8a0 --- /dev/null +++ b/arch/arm/lib32/optee-early.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * optee-early.c - start OP-TEE during PBL + * + * Copyright (c) 2019 Rouven Czerwinski <r.czerwinski@pengutronix.de>, Pengutronix + * + */ +#include <asm/cache.h> +#include <asm/setjmp.h> +#include <tee/optee.h> +#include <debug_ll.h> + +static jmp_buf tee_buf; + +int start_optee_early(void *fdt, void *tee) +{ + void (*tee_start)(void *r0, void *r1, void *r2); + struct optee_header *hdr; + int ret; + + hdr = tee; + ret = optee_verify_header(hdr); + if (ret < 0) + return ret; + + memcpy((void *)hdr->init_load_addr_lo, tee + sizeof(*hdr), hdr->init_size); + tee_start = (void *) hdr->init_load_addr_lo; + + /* We use setjmp/longjmp here because OP-TEE clobbers most registers */ + ret = setjmp(tee_buf); + if (ret == 0) { + sync_caches_for_execution(); + tee_start(0, 0, fdt); + longjmp(tee_buf, 1); + } + + return 0; +} diff --git a/arch/arm/lib32/setjmp.S b/arch/arm/lib32/setjmp.S new file mode 100644 index 0000000000..f0606a7f66 --- /dev/null +++ b/arch/arm/lib32/setjmp.S @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + */ + +#include <config.h> +#include <asm/assembler.h> +#include <linux/linkage.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + /* + * A subroutine must preserve the contents of the registers + * r4-r8, r10, r11 (v1-v5, v7 and v8) and SP (and r9 in PCS + * variants that designate r9 as v6). + */ + mov ip, sp + stm a1, {v1-v8, ip, lr} + mov a1, #0 + bx lr +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ldm a1, {v1-v8, ip, lr} + mov sp, ip + mov a1, a2 + /* If we were passed a return value of zero, return one instead */ + cmp a1, #0 + bne 1f + mov a1, #1 +1: + bx lr +ENDPROC(longjmp) +.popsection diff --git a/arch/arm/lib64/Makefile b/arch/arm/lib64/Makefile index 5068431342..69cb3d8ea1 100644 --- a/arch/arm/lib64/Makefile +++ b/arch/arm/lib64/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS) += memcpy.o obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS) += memset.o string.o extra-y += barebox.lds obj-pbl-y += runtime-offset.o +obj-pbl-y += setjmp.o pbl-y += div0.o pbl.o diff --git a/arch/arm/lib64/setjmp.S b/arch/arm/lib64/setjmp.S new file mode 100644 index 0000000000..a7f6d05417 --- /dev/null +++ b/arch/arm/lib64/setjmp.S @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + */ + +#include <config.h> +#include <linux/linkage.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + /* Preserve all callee-saved registers and the SP */ + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0, #96] + mov x0, #0 + ret +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#96] + mov sp, x2 + /* Move the return value in place, but return 1 if passed 0. */ + adds x0, xzr, x1 + csinc x0, x0, xzr, ne + ret +ENDPROC(longjmp) +.popsection diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index 8f949534b8..6a9ea23c71 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -11,6 +11,7 @@ * */ +#include <abort.h> #include <init.h> #include <common.h> #include <io.h> @@ -288,6 +289,22 @@ int imx6_devices_init(void) return 0; } +static bool imx6_cannot_write_l2x0(void) +{ + void __iomem *l2x0_base = IOMEM(0x00a02000); + u32 val; + /* + * Mask data aborts and try to access the PL210. If OP-TEE is running we + * will receive a data-abort and assume barebox is running in the normal + * world. + */ + val = readl(l2x0_base + L2X0_PREFETCH_CTRL); + + data_abort_mask(); + writel(val, l2x0_base + L2X0_PREFETCH_CTRL); + return data_abort_unmask(); +} + static int imx6_mmu_init(void) { void __iomem *l2x0_base = IOMEM(0x00a02000); @@ -296,6 +313,9 @@ static int imx6_mmu_init(void) if (!cpu_is_mx6()) return 0; + if (imx6_cannot_write_l2x0()) + return 0; + val = readl(l2x0_base + L2X0_CACHE_ID); cache_part = val & L2X0_CACHE_ID_PART_MASK; cache_rtl = val & L2X0_CACHE_ID_RTL_MASK; diff --git a/common/Kconfig b/common/Kconfig index 82bbdb3145..02ef3631e0 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -640,27 +640,6 @@ config BOOTM_FORCE_SIGNED_IMAGES are refused to boot. Effectively this means only FIT images can be booted since they are the only supported image type that support signing. -config BOOTM_OPTEE - bool - prompt "support booting OP-TEE" - depends on BOOTM && ARM - help - OP-TEE is a trusted execution environment (TEE). With this option - enabled barebox supports starting optee_os as part of the bootm command. - Instead of the kernel bootm starts the optee_os binary which then starts - the kernel in nonsecure mode. Pass the optee_os binary with the -t option - or in the global.bootm.tee variable. - -config BOOTM_OPTEE_SIZE - hex - default 0x02000000 - prompt "OP-TEE Memory Size" - depends on BOOTM_OPTEE - help - Size to reserve in main memory for OP-TEE. - Can be smaller than the actual size used by OP-TEE, this is used to prevent - barebox from allocating memory in this area. - config BLSPEC depends on FLEXIBLE_BOOTARGS depends on !SHELL_NONE @@ -1001,6 +980,39 @@ config MACHINE_ID Note: if no hashable information is available no machine id will be passed to the kernel. +menu "OP-TEE loading" + +config OPTEE_SIZE + hex + default 0x02000000 + prompt "OP-TEE Memory Size" + depends on BOOTM_OPTEE || PBL_OPTEE + help + Size to reserve in main memory for OP-TEE. + Can be smaller than the actual size used by OP-TEE, this is used to prevent + barebox from allocating memory in this area. + +config BOOTM_OPTEE + bool + prompt "support booting OP-TEE" + depends on BOOTM && ARM + help + OP-TEE is a trusted execution environment (TEE). With this option + enabled barebox supports starting optee_os as part of the bootm command. + Instead of the kernel bootm starts the optee_os binary which then starts + the kernel in nonsecure mode. Pass the optee_os binary with the -t option + or in the global.bootm.tee variable. + +config PBL_OPTEE + bool "Enable OP-TEE early start" + depends on ARM + depends on !THUMB2_BAREBOX + help + Allows starting OP-TEE during lowlevel initialization of the PBL. + Requires explicit support in the boards lowlevel file. + +endmenu + endmenu menu "Debugging" diff --git a/common/Makefile b/common/Makefile index 11c91dd016..84463b4d48 100644 --- a/common/Makefile +++ b/common/Makefile @@ -67,6 +67,8 @@ obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o obj-$(CONFIG_BOOT) += boot.o obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o obj-$(CONFIG_USBGADGET_START) += usbgadget.o +pbl-$(CONFIG_PBL_OPTEE) += optee.o +obj-$(CONFIG_BOOTM_OPTEE) += optee.o ifdef CONFIG_PASSWORD diff --git a/common/optee.c b/common/optee.c new file mode 100644 index 0000000000..d542dde118 --- /dev/null +++ b/common/optee.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define pr_fmt(fmt) "optee: " fmt + +#include <tee/optee.h> +#include <printk.h> +#include <asm-generic/errno.h> + +int optee_verify_header(struct optee_header *hdr) +{ + if (hdr->magic != OPTEE_MAGIC) { + pr_err("Invalid header magic 0x%08x, expected 0x%08x\n", + hdr->magic, OPTEE_MAGIC); + return -EINVAL; + } + + if (hdr->arch != OPTEE_ARCH_ARM32 || hdr->init_load_addr_hi) { + pr_err("Only 32bit supported\n"); + return -EINVAL; + } + + return 0; +} diff --git a/include/asm-generic/memory_layout.h b/include/asm-generic/memory_layout.h index 3f69664aa0..0d7ce3fe02 100644 --- a/include/asm-generic/memory_layout.h +++ b/include/asm-generic/memory_layout.h @@ -11,8 +11,8 @@ #define MALLOC_BASE CONFIG_MALLOC_BASE #endif -#ifdef CONFIG_BOOTM_OPTEE_SIZE -#define OPTEE_SIZE CONFIG_BOOTM_OPTEE_SIZE +#ifdef CONFIG_OPTEE_SIZE +#define OPTEE_SIZE CONFIG_OPTEE_SIZE #else #define OPTEE_SIZE 0 #endif diff --git a/include/tee/optee.h b/include/tee/optee.h index 8cfe06d889..fa124236ba 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h @@ -10,6 +10,9 @@ #ifndef _OPTEE_H #define _OPTEE_H +#include <types.h> +#include <asm-generic/errno.h> + #define OPTEE_MAGIC 0x4554504f #define OPTEE_VERSION 1 #define OPTEE_ARCH_ARM32 0 @@ -27,4 +30,12 @@ struct optee_header { uint32_t paged_size; }; +int optee_verify_header (struct optee_header *hdr); + +#ifdef __PBL__ + +int start_optee_early(void* fdt, void* tee); + +#endif /* __PBL__ */ + #endif /* _OPTEE_H */ |