Hi Lothar, On 11 May 2017 at 08:59, Lothar Waßmann <l...@karo-electronics.de> wrote: > 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?
The size has been calculated the code above. This is a two-pass approach - one pass figures out the total size of the required buffer, and the next pass actually copies in the data. If the length were wrong that would indicate a bug in the code above. See the part where it sets new_format to 1. Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot