Hi,

On Wed, 10 May 2017 08:20:44 -0600 Simon Glass wrote:
> This function converts the flat device tree into a hierarchical one with
> C structures and pointers. This is easier to access.
> 
> Signed-off-by: Simon Glass <s...@chromium.org>
> ---
> 
> Changes in v2: None
> 
>  include/of_live.h |  24 ++++
>  lib/Makefile      |   1 +
>  lib/of_live.c     | 333 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 358 insertions(+)
>  create mode 100644 include/of_live.h
>  create mode 100644 lib/of_live.c
> 
> diff --git a/include/of_live.h b/include/of_live.h
> new file mode 100644
> index 0000000000..f5303bb018
> --- /dev/null
> +++ b/include/of_live.h
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (c) 2017 Google, Inc
> + * Written by Simon Glass <s...@chromium.org>
> + *
> + * SPDX-License-Identifier:  GPL-2.0+
> + *
> + * Support for a 'live' (as opposed to flat) device tree
> + */
> +
> +#ifndef _OF_LIVE_H
> +#define _OF_LIVE_H
> +
> +struct device_node;
> +
> +/**
> + * of_live_build() - build a live (hierarchical) tree from a flat DT
> + *
> + * @fdt_blob: Input tree to convert
> + * @rootp: Returns live tree that was created
> + * @return 0 if OK, -ve on error
> + */
> +int of_live_build(const void *fdt_blob, struct device_node **rootp);
> +
> +#endif
> diff --git a/lib/Makefile b/lib/Makefile
> index 23e9f1ef11..bc2fb0a361 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_ZLIB) += zlib/
>  obj-$(CONFIG_BZIP2) += bzip2/
>  obj-$(CONFIG_TIZEN) += tizen/
>  obj-$(CONFIG_FIT) += libfdt/
> +obj-$(CONFIG_OF_LIVE) += of_live.o
>  obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
>  
>  obj-$(CONFIG_AES) += aes.o
> diff --git a/lib/of_live.c b/lib/of_live.c
> new file mode 100644
> index 0000000000..51927f9e91
> --- /dev/null
> +++ b/lib/of_live.c
> @@ -0,0 +1,333 @@
> +/*
> + * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
> + * b...@kernel.crashing.org
> + *
> + * Based on parts of drivers/of/fdt.c from Linux v4.9
> + * Modifications for U-Boot
> + * Copyright (c) 2017 Google, Inc
> + *
> + * SPDX-License-Identifier:  GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <libfdt.h>
> +#include <of_live.h>
> +#include <malloc.h>
> +#include <dm/of_access.h>
> +#include <linux/err.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static void *unflatten_dt_alloc(void **mem, unsigned long size,
> +                             unsigned long align)
> +{
> +     void *res;
> +
> +     *mem = PTR_ALIGN(*mem, align);
> +     res = *mem;
> +     *mem += size;
> +
> +     return res;
> +}
> +
> +/**
> + * unflatten_dt_node() - Alloc and populate a device_node from the flat tree
> + * @blob: The parent device tree blob
> + * @mem: Memory chunk to use for allocating device nodes and properties
> + * @poffset: pointer to node in flat tree
> + * @dad: Parent struct device_node
> + * @nodepp: The device_node tree created by the call
> + * @fpsize: Size of the node path up at t05he current depth.
> + * @dryrun: If true, do not allocate device nodes but still calculate needed
> + * memory size
> + */
> +static void *unflatten_dt_node(const void *blob, void *mem, int *poffset,
> +                            struct device_node *dad,
> +                            struct device_node **nodepp,
> +                            unsigned long fpsize, bool dryrun)
> +{
> +     const __be32 *p;
> +     struct device_node *np;
> +     struct property *pp, **prev_pp = NULL;
> +     const char *pathp;
> +     int l;
> +     unsigned int allocl;
> +     static int depth;
> +     int old_depth;
> +     int offset;
> +     int has_name = 0;
> +     int new_format = 0;
> +
> +     pathp = fdt_get_name(blob, *poffset, &l);
> +     if (!pathp)
> +             return mem;
> +
> +     allocl = ++l;
> +
> +     /*
> +      * version 0x10 has a more compact unit name here instead of the full
> +      * path. we accumulate the full path size using "fpsize", we'll rebuild
> +      * it later. We detect this because the first character of the name is
> +      * not '/'.
> +      */
> +     if ((*pathp) != '/') {
> +             new_format = 1;
> +             if (fpsize == 0) {
> +                     /*
> +                      * root node: special case. fpsize accounts for path
> +                      * plus terminating zero. root node only has '/', so
> +                      * fpsize should be 2, but we want to avoid the first
> +                      * level nodes to have two '/' so we use fpsize 1 here
> +                      */
> +                     fpsize = 1;
> +                     allocl = 2;
> +                     l = 1;
> +                     pathp = "";
> +             } else {
> +                     /*
> +                      * account for '/' and path size minus terminal 0
> +                      * already in 'l'
> +                      */
> +                     fpsize += l;
> +                     allocl = fpsize;
> +             }
> +     }
> +
> +     np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
> +                             __alignof__(struct device_node));
> +     if (!dryrun) {
> +             char *fn;
> +
> +             fn = (char *)np + sizeof(*np);
> +             np->full_name = fn;
> +             if (new_format) {
> +                     /* rebuild full path for new format */
> +                     if (dad && dad->parent) {
> +                             strcpy(fn, dad->full_name);
>
strcpy() is EVIL! How do you ascertain, that the string
at dad->full_name cannot overflow the buffer at fn?
 

Lothar Waßmann
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to