The loading convention for optee or any other tee on arm64 is as bl32 parameter to the trusted-firmware. So TF-A gets invoked with the TEE as bl32 and main u-boot as bl33. Once it has done its startup TF-A jumps into the bl32 for the TEE startup, returns to TF-A and then jumps to bl33.
All of them get passed a devicetree as parameter and all components often get loaded from a FIT image. OP-TEE will create additional nodes in that devicetree namely a firmware node and possibly multiple reserved-memory nodes. While this devicetree is used in main u-boot, in most cases it won't be the one passed to the actual kernel. Instead most boot commands will load a new devicetree from somewhere like mass storage of the network, so if that happens u-boot should transfer the optee nodes to that new devicetree. To make that happen introduce optee_copy_fdt_nodes() called from the dt setup function in image-fdt which after checking for the optee presence in the u-boot dt will make sure a optee node is present in the kernel dt and transfer any reserved-memory regions it can find. Signed-off-by: Heiko Stuebner <he...@sntech.de> --- This goes together with my bl32 work for the spl_atf loader in https://patchwork.ozlabs.org/patch/1172565/ common/image-fdt.c | 8 ++++ include/tee/optee.h | 9 ++++ lib/optee/optee.c | 112 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) diff --git a/common/image-fdt.c b/common/image-fdt.c index 4247dcee0c..48388488d9 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -17,6 +17,7 @@ #include <linux/libfdt.h> #include <mapmem.h> #include <asm/io.h> +#include <tee/optee.h> #ifndef CONFIG_SYS_FDT_PAD #define CONFIG_SYS_FDT_PAD 0x3000 @@ -561,6 +562,13 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, } } + fdt_ret = optee_copy_fdt_nodes(gd->fdt_blob, blob); + if (fdt_ret) { + printf("ERROR: transfer of optee nodes to new fdt failed: %s\n", + fdt_strerror(fdt_ret)); + goto err; + } + /* Delete the old LMB reservation */ if (lmb) lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob, diff --git a/include/tee/optee.h b/include/tee/optee.h index 9446928fd4..121b30a303 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h @@ -67,4 +67,13 @@ static inline int optee_verify_bootm_image(unsigned long image_addr, } #endif +#if defined(CONFIG_OPTEE) && defined(CONFIG_OF_LIBFDT) +int optee_copy_fdt_nodes(const void *old_blob, void *new_blob); +#else +static inline int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) +{ + return 0; +} +#endif + #endif /* _OPTEE_H */ diff --git a/lib/optee/optee.c b/lib/optee/optee.c index db92cd9af2..f484b12e67 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -5,6 +5,8 @@ */ #include <common.h> +#include <malloc.h> +#include <linux/libfdt.h> #include <tee/optee.h> #define optee_hdr_err_msg \ @@ -63,3 +65,113 @@ error: return ret; } + +#if defined(CONFIG_OF_LIBFDT) +static int optee_add_firmware_node(void *fdt_blob) +{ + int offs, ret; + + if (fdt_path_offset(fdt_blob, "/firmware/optee") >= 0) { + debug("OP-TEE Device Tree node already exists"); + return 0; + } + + offs = fdt_path_offset(fdt_blob, "/firmware"); + if (offs < 0) { + offs = fdt_path_offset(fdt_blob, "/"); + if (offs < 0) + return offs; + + offs = fdt_add_subnode(fdt_blob, offs, "firmware"); + if (offs < 0) + return offs; + } + + offs = fdt_add_subnode(fdt_blob, offs, "optee"); + if (offs < 0) + return ret; + + ret = fdt_setprop_string(fdt_blob, offs, "compatible", + "linaro,optee-tz"); + if (ret < 0) + return ret; + + ret = fdt_setprop_string(fdt_blob, offs, "method", "smc"); + if (ret < 0) + return ret; + + return 0; +} + +int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) +{ + int nodeoffset, subnode, ret; + struct fdt_resource res; + + if (fdt_check_header(old_blob)) + return -EINVAL; + + /* only proceed if there is an /firmware/optee node */ + if (fdt_path_offset(old_blob, "/firmware/optee") < 0) { + debug("No OP-TEE firmware node in old fdt, nothing to do"); + return 0; + } + + ret = optee_add_firmware_node(new_blob); + if (ret < 0) { + printf("Failed to add OP-TEE firmware node\n"); + return ret; + } + + /* optee inserts its memory regions as reserved-memory nodes */ + nodeoffset = fdt_subnode_offset(old_blob, 0, "reserved-memory"); + if (nodeoffset >= 0) { + subnode = fdt_first_subnode(old_blob, nodeoffset); + while (subnode >= 0) { + const char *name = fdt_get_name(old_blob, + subnode, NULL); + if (!name) + return -EINVAL; + + /* only handle optee reservations */ + if (strncmp(name, "optee", 5)) + continue; + + /* check if this subnode has a reg property */ + ret = fdt_get_resource(old_blob, subnode, "reg", 0, + &res); + if (!ret) { + struct fdt_memory carveout = { + .start = res.start, + .end = res.end, + }; + char *oldname, *nodename, *tmp; + + oldname = strdup(name); + if (!oldname) + return -ENOMEM; + + tmp = oldname; + nodename = strsep(&tmp, "@"); + if (!nodename) { + free(oldname); + return -EINVAL; + } + + ret = fdtdec_add_reserved_memory(new_blob, + nodename, + &carveout, + NULL); + free(oldname); + + if (ret < 0) + return ret; + } + + subnode = fdt_next_subnode(old_blob, subnode); + } + } + + return 0; +} +#endif -- 2.23.0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot