[U-Boot] [PATCH 3/3] image: fdt: copy possible optee nodes to a loaded devicetree

Jens Wiklander jens.wiklander at linaro.org
Tue Oct 22 06:16:40 UTC 2019


Hi Heiko,

[+Igor]

On Tue, Oct 8, 2019 at 2:22 AM Heiko Stuebner <heiko at sntech.de> 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 <heiko at 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);

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
>


More information about the U-Boot mailing list