* [PATCH v2 2/5] ARM: import setjmp implementation from U-Boot
2020-01-20 8:56 [PATCH v2 1/5] optee: move optee_verify_header() to common Rouven Czerwinski
@ 2020-01-20 8:56 ` Rouven Czerwinski
2020-01-21 7:46 ` Sascha Hauer
2020-01-20 8:56 ` [PATCH v2 3/5] ARM: add optee early loading function Rouven Czerwinski
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Rouven Czerwinski @ 2020-01-20 8:56 UTC (permalink / raw)
To: barebox; +Cc: Rouven Czerwinski
Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
---
arch/arm/include/asm/setjmp.h | 29 ++++++++++++++++++++++++++++
arch/arm/lib32/setjmp.S | 36 +++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)
create mode 100644 arch/arm/include/asm/setjmp.h
create mode 100644 arch/arm/lib32/setjmp.S
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/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
--
2.25.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/5] ARM: import setjmp implementation from U-Boot
2020-01-20 8:56 ` [PATCH v2 2/5] ARM: import setjmp implementation from U-Boot Rouven Czerwinski
@ 2020-01-21 7:46 ` Sascha Hauer
0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2020-01-21 7:46 UTC (permalink / raw)
To: Rouven Czerwinski; +Cc: barebox
On Mon, Jan 20, 2020 at 09:56:45AM +0100, Rouven Czerwinski wrote:
> Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
> ---
> arch/arm/include/asm/setjmp.h | 29 ++++++++++++++++++++++++++++
> arch/arm/lib32/setjmp.S | 36 +++++++++++++++++++++++++++++++++++
> 2 files changed, 65 insertions(+)
> create mode 100644 arch/arm/include/asm/setjmp.h
> create mode 100644 arch/arm/lib32/setjmp.S
>
> 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/setjmp.S b/arch/arm/lib32/setjmp.S
While you are at it please add arch/arm/lib64/setjmp.S as well. You can
copy it directly from U-Boot.
This patch should also add setjmp.o to the Makefiles. In patch 3/5
you add:
pbl-$(CONFIG_PBL_OPTEE) += setjmp.o
How does a potential second user select setjmp? You can instead either
add a CONFIG_SETJMP symbol which you select from CONFIG_PBL_OPTEE or
just do a obj-pbl-y += setjmp.o. In this case it's fine to not add a new
symbol for it.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 3/5] ARM: add optee early loading function
2020-01-20 8:56 [PATCH v2 1/5] optee: move optee_verify_header() to common Rouven Czerwinski
2020-01-20 8:56 ` [PATCH v2 2/5] ARM: import setjmp implementation from U-Boot Rouven Czerwinski
@ 2020-01-20 8:56 ` Rouven Czerwinski
2020-01-20 8:56 ` [PATCH v2 4/5] ARM: mach-imx: test PL310 write access Rouven Czerwinski
2020-01-20 8:56 ` [PATCH v2 5/5] user: add documentation for OP-TEE loading Rouven Czerwinski
3 siblings, 0 replies; 7+ messages in thread
From: Rouven Czerwinski @ 2020-01-20 8:56 UTC (permalink / raw)
To: barebox; +Cc: Rouven Czerwinski
Add a OP-TEE early loading function which expects a pointer to a valid
tee binary and the device tree. OP-TEE will then be started and barebox
will continue to run in normal mode.
The function start_optee_early should be used in a boards lowlevel.c
file. Ensure that barebox has been relocated and a proper c environment
has been setup beforehand. Depending on the OP-TEE configuration, the
fdt will be modified. If the internal barebox device tree is passed,
OP-TEE will overwrite barebox PBL memory during this modification. Copy
the fdt to a save memory location beforehand to avoid a corruption of
barebox PBL memory.
This also moves the OP-TEE Kconfig symbols into a separate menu.
Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
---
arch/arm/lib32/Makefile | 3 ++
arch/arm/lib32/optee-early.c | 38 ++++++++++++++++++++
common/Kconfig | 54 ++++++++++++++++++-----------
common/Makefile | 1 +
include/asm-generic/memory_layout.h | 4 +--
include/tee/optee.h | 6 ++++
6 files changed, 83 insertions(+), 23 deletions(-)
create mode 100644 arch/arm/lib32/optee-early.c
diff --git a/arch/arm/lib32/Makefile b/arch/arm/lib32/Makefile
index cd43147e66..18f6973fcc 100644
--- a/arch/arm/lib32/Makefile
+++ b/arch/arm/lib32/Makefile
@@ -28,3 +28,6 @@ extra-y += barebox.lds
pbl-y += lib1funcs.o
pbl-y += ashldi3.o
pbl-y += div0.o
+
+pbl-$(CONFIG_PBL_OPTEE) += setjmp.o
+pbl-$(CONFIG_PBL_OPTEE) += optee-early.o
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/common/Kconfig b/common/Kconfig
index 60237d3056..25587d1927 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -643,27 +643,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
@@ -1000,6 +979,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 fbdd74a9fd..8312e88572 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -66,6 +66,7 @@ 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/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 9fb27fcec0..fa124236ba 100644
--- a/include/tee/optee.h
+++ b/include/tee/optee.h
@@ -32,4 +32,10 @@ struct optee_header {
int optee_verify_header (struct optee_header *hdr);
+#ifdef __PBL__
+
+int start_optee_early(void* fdt, void* tee);
+
+#endif /* __PBL__ */
+
#endif /* _OPTEE_H */
--
2.25.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 4/5] ARM: mach-imx: test PL310 write access
2020-01-20 8:56 [PATCH v2 1/5] optee: move optee_verify_header() to common Rouven Czerwinski
2020-01-20 8:56 ` [PATCH v2 2/5] ARM: import setjmp implementation from U-Boot Rouven Czerwinski
2020-01-20 8:56 ` [PATCH v2 3/5] ARM: add optee early loading function Rouven Czerwinski
@ 2020-01-20 8:56 ` Rouven Czerwinski
2020-01-21 7:37 ` Sascha Hauer
2020-01-20 8:56 ` [PATCH v2 5/5] user: add documentation for OP-TEE loading Rouven Czerwinski
3 siblings, 1 reply; 7+ messages in thread
From: Rouven Czerwinski @ 2020-01-20 8:56 UTC (permalink / raw)
To: barebox; +Cc: Rouven Czerwinski
If OP-TEE early loading is performed, OP-TEE will configure the PL210
and lock write access to the controller from the normal world. Test this
by trying to write the same value back and do not configure if we can
not write to the PL310.
Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
---
arch/arm/mach-imx/imx6.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 41e0066add..c6fd862379 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>
@@ -273,6 +274,22 @@ int imx6_devices_init(void)
return 0;
}
+static bool imx6_can_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);
@@ -281,6 +298,9 @@ static int imx6_mmu_init(void)
if (!cpu_is_mx6())
return 0;
+ if (imx6_can_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;
--
2.25.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 4/5] ARM: mach-imx: test PL310 write access
2020-01-20 8:56 ` [PATCH v2 4/5] ARM: mach-imx: test PL310 write access Rouven Czerwinski
@ 2020-01-21 7:37 ` Sascha Hauer
0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2020-01-21 7:37 UTC (permalink / raw)
To: Rouven Czerwinski; +Cc: barebox
On Mon, Jan 20, 2020 at 09:56:47AM +0100, Rouven Czerwinski wrote:
> If OP-TEE early loading is performed, OP-TEE will configure the PL210
> and lock write access to the controller from the normal world. Test this
> by trying to write the same value back and do not configure if we can
> not write to the PL310.
>
> Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
> ---
> arch/arm/mach-imx/imx6.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
> index 41e0066add..c6fd862379 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>
> @@ -273,6 +274,22 @@ int imx6_devices_init(void)
> return 0;
> }
>
> +static bool imx6_can_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);
> @@ -281,6 +298,9 @@ static int imx6_mmu_init(void)
> if (!cpu_is_mx6())
> return 0;
>
> + if (imx6_can_write_l2x0())
> + return 0;
Function name seems wrong, should be imx6_cannot_write_l2x0()
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 5/5] user: add documentation for OP-TEE loading
2020-01-20 8:56 [PATCH v2 1/5] optee: move optee_verify_header() to common Rouven Czerwinski
` (2 preceding siblings ...)
2020-01-20 8:56 ` [PATCH v2 4/5] ARM: mach-imx: test PL310 write access Rouven Czerwinski
@ 2020-01-20 8:56 ` Rouven Czerwinski
3 siblings, 0 replies; 7+ messages in thread
From: Rouven Czerwinski @ 2020-01-20 8:56 UTC (permalink / raw)
To: barebox; +Cc: Rouven Czerwinski
Some rudimentary documentation how to load OP-TEE.
Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
---
Documentation/user/optee.rst | 29 +++++++++++++++++++++++++++++
Documentation/user/user-manual.rst | 1 +
2 files changed, 30 insertions(+)
create mode 100644 Documentation/user/optee.rst
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
--
2.25.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 7+ messages in thread