[U-Boot] [PATCH v2 05/71] dm: Add a function to create a 'live' device tree
Lothar Waßmann
LW at KARO-electronics.de
Thu May 11 14:59:04 UTC 2017
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 <sjg at 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 <sjg at 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
> + * benh at 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
More information about the U-Boot
mailing list