From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jens Wiklander Date: Tue, 22 Oct 2019 08:16:40 +0200 Subject: [U-Boot] [PATCH 3/3] image: fdt: copy possible optee nodes to a loaded devicetree In-Reply-To: <20191008002207.14396-3-heiko@sntech.de> References: <20191008002207.14396-1-heiko@sntech.de> <20191008002207.14396-3-heiko@sntech.de> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Heiko, [+Igor] On Tue, Oct 8, 2019 at 2:22 AM Heiko Stuebner wrote: > > 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 > --- > 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 > #include > #include > +#include > > #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 > +#include > +#include > #include > > #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); I think it's more safe to copy the OP-TEE node instead. The values of "compatible" and "method" may be different on other platforms, "hvc" instead of "smc" for instance. Thanks, Jens > + 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 >