From patchwork Tue Oct 8 00:22:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiko Stuebner X-Patchwork-Id: 1173030 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sntech.de Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46nJ332Wv1z9s4Y for ; Tue, 8 Oct 2019 11:22:54 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 91CFBC21F49; Tue, 8 Oct 2019 00:22:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 2C2C8C21F74; Tue, 8 Oct 2019 00:22:16 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3BE19C21D65; Tue, 8 Oct 2019 00:22:14 +0000 (UTC) Received: from gloria.sntech.de (gloria.sntech.de [185.11.138.130]) by lists.denx.de (Postfix) with ESMTPS id F1D1CC21EE7 for ; Tue, 8 Oct 2019 00:22:13 +0000 (UTC) Received: from ip5f5a6266.dynamic.kabel-deutschland.de ([95.90.98.102] helo=phil.fritz.box) by gloria.sntech.de with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1iHdGW-0006GU-3M; Tue, 08 Oct 2019 02:22:12 +0200 From: Heiko Stuebner To: u-boot@lists.denx.de Date: Tue, 8 Oct 2019 02:22:07 +0200 Message-Id: <20191008002207.14396-3-heiko@sntech.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191008002207.14396-1-heiko@sntech.de> References: <20191008002207.14396-1-heiko@sntech.de> MIME-Version: 1.0 Cc: andre.przywara@arm.com, robin.murphy@arm.com, christoph.muellner@theobroma-systems.com Subject: [U-Boot] [PATCH 3/3] image: fdt: copy possible optee nodes to a loaded devicetree X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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); + 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