diff options
Diffstat (limited to 'arch/arm/lib32/bootm.c')
-rw-r--r-- | arch/arm/lib32/bootm.c | 72 |
1 files changed, 63 insertions, 9 deletions
diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c index d64e705c40..e814593dce 100644 --- a/arch/arm/lib32/bootm.c +++ b/arch/arm/lib32/bootm.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only + #include <bootm.h> #include <boot.h> #include <common.h> @@ -20,7 +22,7 @@ #include <restart.h> #include <globalvar.h> #include <tee/optee.h> - +#include <image-fit.h> #include <asm/byteorder.h> #include <asm/setup.h> #include <asm/barebox-arm.h> @@ -104,11 +106,25 @@ static int get_kernel_addresses(size_t image_size, spacing = SZ_1M; if (*load_address == UIMAGE_INVALID_ADDRESS) { + unsigned long mem_end = mem_start + mem_size - 1; + unsigned long kaddr; + /* * Place the kernel at an address where it does not need to * relocate itself before decompression. */ - *load_address = mem_start + image_decomp_size; + kaddr = mem_start + image_decomp_size; + + /* + * Make sure we do not place the image outside of the + * available memory. + */ + if (((kaddr + image_size + spacing) > mem_end) && + ((mem_end - image_size - spacing) >= mem_start)) + kaddr = mem_end - image_size - spacing; + + *load_address = PAGE_ALIGN_DOWN(kaddr); + if (verbose) printf("no OS load address, defaulting to 0x%08lx\n", *load_address); @@ -153,6 +169,34 @@ static int optee_verify_header_request_region(struct image_data *data, struct op return ret; } +static int bootm_load_tee_from_fit(struct image_data *data) +{ + int ret = 0; + struct optee_header hdr; + + if (data->os_fit && + fit_has_image(data->os_fit, data->fit_config, "tee")) { + const void *tee; + unsigned long tee_size; + + ret = fit_open_image(data->os_fit, data->fit_config, "tee", + &tee, &tee_size); + if (ret) { + pr_err("Error opening tee fit image: %s\n", strerror(-ret)); + return ret; + } + memcpy(&hdr, tee, sizeof(hdr)); + if (optee_verify_header_request_region(data, &hdr) < 0) { + pr_err("%s", strerror(errno)); + ret = -errno; + goto out; + } + memcpy((void *)data->tee_res->start, tee + sizeof(hdr), hdr.init_size); + printf("Read optee image to %pa, size 0x%08x\n", (void *)data->tee_res->start, hdr.init_size); + } +out: + return ret; +} static int bootm_load_tee_from_file(struct image_data *data) { int fd, ret; @@ -249,10 +293,16 @@ 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 (IS_ENABLED(CONFIG_BOOTM_OPTEE)) { + if (data->tee_file && !IS_ENABLED(CONFIG_BOOTM_FORCE_SIGNED_IMAGES)) { + ret = bootm_load_tee_from_file(data); + if (ret) + return ret; + } else if (IS_ENABLED(CONFIG_FITIMAGE)) { + ret = bootm_load_tee_from_fit(data); + if (ret) + return ret; + } } @@ -277,6 +327,10 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, if (data->dryrun) return 0; + ret = of_overlay_load_firmware(); + if (ret) + return ret; + if (data->tee_res) tee = (void *)data->tee_res->start; else @@ -373,7 +427,7 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data, void **outfdt) if (IS_BUILTIN(CONFIG_OFTREE)) { struct device_node *root; - root = of_unflatten_dtb(oftree); + root = of_unflatten_dtb(oftree, header->totalsize); if (IS_ERR(root)) { pr_err("unable to unflatten devicetree\n"); goto err_free; @@ -698,8 +752,8 @@ static struct binfmt_hook binfmt_barebox_hook = { .exec = "bootm", }; -BAREBOX_MAGICVAR_NAMED(global_bootm_boot_atag, global.bootm.boot_atag, - "If true, ignore device tree and boot using ATAGs"); +BAREBOX_MAGICVAR(global.bootm.boot_atag, + "If true, ignore device tree and boot using ATAGs"); static int armlinux_register_image_handler(void) { |