diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-05-22 10:05:17 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-06-07 08:42:05 +0200 |
commit | e30340886fcbac1d2c03fbea4ee41ffa9464fb11 (patch) | |
tree | d6aec9dde274cafbdce1c8beca4699c05fd17f98 /arch/arm/lib32 | |
parent | ab06d72a6ef8939831b8c0b1c412d9a11fc06889 (diff) | |
download | barebox-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.c | 10 | ||||
-rw-r--r-- | arch/arm/lib32/bootm.c | 80 | ||||
-rw-r--r-- | arch/arm/lib32/bootu.c | 2 | ||||
-rw-r--r-- | arch/arm/lib32/bootz.c | 2 |
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; |