summaryrefslogtreecommitdiffstats
path: root/arch/arm/lib32
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-05-22 10:05:17 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-06-07 08:42:05 +0200
commite30340886fcbac1d2c03fbea4ee41ffa9464fb11 (patch)
treed6aec9dde274cafbdce1c8beca4699c05fd17f98 /arch/arm/lib32
parentab06d72a6ef8939831b8c0b1c412d9a11fc06889 (diff)
downloadbarebox-e30340886fcbac1d2c03fbea4ee41ffa9464fb11.tar.gz
barebox-e30340886fcbac1d2c03fbea4ee41ffa9464fb11.tar.xz
ARM: Initial OP-TEE support
This adds initial support for OP-TEE, see https://www.op-tee.org/ barebox starts in secure mode as usual. When booting a kernel the bootm code also loads the optee_os binary. Instead of jumping into the kernel barebox jumps into the optee_os binary and puts the kernel execution address into the lr register. OP-TEE then jumps into the kernel in nonsecure mode. The optee_os binary is passed with the -t option to bootm or with global.bootm.tee. Optionally OP-TEE can be compiled into barebox using the builtin firmware feature. Enable the Kconfig option and place or link your tee binary as optee.bin into the firmware directory. The amount of SDRAM which is kept free for OP-TEE is configurable. This patch was tested on a i.MX6 Nitrogen6x board. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/lib32')
-rw-r--r--arch/arm/lib32/armlinux.c10
-rw-r--r--arch/arm/lib32/bootm.c80
-rw-r--r--arch/arm/lib32/bootu.c2
-rw-r--r--arch/arm/lib32/bootz.c2
4 files changed, 89 insertions, 5 deletions
diff --git a/arch/arm/lib32/armlinux.c b/arch/arm/lib32/armlinux.c
index c970f029c5..1cb9fd2e51 100644
--- a/arch/arm/lib32/armlinux.c
+++ b/arch/arm/lib32/armlinux.c
@@ -258,9 +258,11 @@ static void setup_tags(unsigned long initrd_address,
}
+void start_kernel_optee(void *optee, void *kernel, void *oftree);
+
void start_linux(void *adr, int swap, unsigned long initrd_address,
unsigned long initrd_size, void *oftree,
- enum arm_security_state state)
+ enum arm_security_state state, void *optee)
{
void (*kernel)(int zero, int arch, void *params) = adr;
void *params = NULL;
@@ -294,5 +296,9 @@ void start_linux(void *adr, int swap, unsigned long initrd_address,
__asm__ __volatile__("mcr p15, 0, %0, c1, c0" :: "r" (reg));
}
- kernel(0, architecture, params);
+ if (optee && IS_ENABLED(CONFIG_BOOTM_OPTEE)) {
+ start_kernel_optee(optee, kernel, oftree);
+ } else {
+ kernel(0, architecture, params);
+ }
}
diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c
index 4cf570e577..180624445d 100644
--- a/arch/arm/lib32/bootm.c
+++ b/arch/arm/lib32/bootm.c
@@ -19,6 +19,7 @@
#include <binfmt.h>
#include <restart.h>
#include <globalvar.h>
+#include <tee/optee.h>
#include <asm/byteorder.h>
#include <asm/setup.h>
@@ -133,11 +134,76 @@ static int get_kernel_addresses(size_t image_size,
return 0;
}
+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;
+ }
+
+ data->tee_res = request_sdram_region("TEE", hdr->init_load_addr_lo, hdr->init_size);
+ if (!data->tee_res) {
+ pr_err("Cannot request SDRAM region 0x%08x-0x%08x: %s\n",
+ hdr->init_load_addr_lo, hdr->init_load_addr_lo + hdr->init_size - 1,
+ strerror(-EINVAL));
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int bootm_load_tee_from_file(struct image_data *data)
+{
+ int fd, ret;
+ struct optee_header hdr;
+
+ fd = open(data->tee_file, O_RDONLY);
+ if (fd < 0) {
+ pr_err("%s", strerror(errno));
+ return -errno;
+ }
+
+ if (read_full(fd, &hdr, sizeof(hdr)) < 0) {
+ pr_err("%s", strerror(errno));
+ ret = -errno;
+ goto out;
+ }
+
+ if (optee_verify_header_request_region(data, &hdr) < 0) {
+ pr_err("%s", strerror(errno));
+ ret = -errno;
+ goto out;
+ }
+
+ if (read_full(fd, (void *)data->tee_res->start, hdr.init_size) < 0) {
+ pr_err("%s", strerror(errno));
+ ret = -errno;
+ release_region(data->tee_res);
+ goto out;
+ }
+
+ printf("Read optee file to %pa, size 0x%08x\n", (void *)data->tee_res->start, hdr.init_size);
+
+ ret = 0;
+out:
+ close(fd);
+
+ return ret;
+}
+
static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
int swap, void *fdt)
{
unsigned long kernel;
unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0;
+ void *tee;
enum arm_security_state state = bootm_arm_security_state();
void *fdt_load_address = NULL;
int ret;
@@ -189,6 +255,13 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
return ret;
}
+ if (IS_ENABLED(CONFIG_BOOTM_OPTEE) && data->tee_file) {
+ ret = bootm_load_tee_from_file(data);
+ if (ret)
+ return ret;
+ }
+
+
if (bootm_verbose(data)) {
printf("\nStarting kernel at 0x%08lx", kernel);
if (initrd_size)
@@ -210,8 +283,13 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
if (data->dryrun)
return 0;
+ if (data->tee_res)
+ tee = (void *)data->tee_res->start;
+ else
+ tee = NULL;
+
start_linux((void *)kernel, swap, initrd_start, initrd_size,
- fdt_load_address, state);
+ fdt_load_address, state, tee);
restart_machine();
diff --git a/arch/arm/lib32/bootu.c b/arch/arm/lib32/bootu.c
index d811da39ce..24c744da58 100644
--- a/arch/arm/lib32/bootu.c
+++ b/arch/arm/lib32/bootu.c
@@ -26,7 +26,7 @@ static int do_bootu(int argc, char *argv[])
oftree = of_get_fixed_tree(NULL);
#endif
- start_linux(kernel, 0, 0, 0, oftree, ARM_STATE_SECURE);
+ start_linux(kernel, 0, 0, 0, oftree, ARM_STATE_SECURE, NULL);
return 1;
}
diff --git a/arch/arm/lib32/bootz.c b/arch/arm/lib32/bootz.c
index c0ffd93c2b..a2a26ac2f9 100644
--- a/arch/arm/lib32/bootz.c
+++ b/arch/arm/lib32/bootz.c
@@ -112,7 +112,7 @@ static int do_bootz(int argc, char *argv[])
oftree = of_get_fixed_tree(NULL);
#endif
- start_linux(zimage, swap, 0, 0, oftree, ARM_STATE_SECURE);
+ start_linux(zimage, swap, 0, 0, oftree, ARM_STATE_SECURE, NULL);
return 0;