From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lothar =?UTF-8?B?V2HDn21hbm4=?= Date: Thu, 11 May 2017 16:59:04 +0200 Subject: [U-Boot] [PATCH v2 05/71] dm: Add a function to create a 'live' device tree In-Reply-To: <20170510142150.30515-6-sjg@chromium.org> References: <20170510142150.30515-1-sjg@chromium.org> <20170510142150.30515-6-sjg@chromium.org> Message-ID: <20170511165904.7eb355d2@ipc1.ka-ro> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: quoted-printable To: u-boot@lists.denx.de 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. >=20 > Signed-off-by: Simon Glass > --- >=20 > Changes in v2: None >=20 > 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 >=20 > 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 > + * > + * 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) +=3D zlib/ > obj-$(CONFIG_BZIP2) +=3D bzip2/ > obj-$(CONFIG_TIZEN) +=3D tizen/ > obj-$(CONFIG_FIT) +=3D libfdt/ > +obj-$(CONFIG_OF_LIVE) +=3D of_live.o > obj-$(CONFIG_CMD_DHRYSTONE) +=3D dhry/ > =20 > obj-$(CONFIG_AES) +=3D 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 > +#include > +#include > +#include > +#include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > + > +static void *unflatten_dt_alloc(void **mem, unsigned long size, > + unsigned long align) > +{ > + void *res; > + > + *mem =3D PTR_ALIGN(*mem, align); > + res =3D *mem; > + *mem +=3D 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 ne= eded > + * 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 =3D NULL; > + const char *pathp; > + int l; > + unsigned int allocl; > + static int depth; > + int old_depth; > + int offset; > + int has_name =3D 0; > + int new_format =3D 0; > + > + pathp =3D fdt_get_name(blob, *poffset, &l); > + if (!pathp) > + return mem; > + > + allocl =3D ++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) !=3D '/') { > + new_format =3D 1; > + if (fpsize =3D=3D 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 =3D 1; > + allocl =3D 2; > + l =3D 1; > + pathp =3D ""; > + } else { > + /* > + * account for '/' and path size minus terminal 0 > + * already in 'l' > + */ > + fpsize +=3D l; > + allocl =3D fpsize; > + } > + } > + > + np =3D unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, > + __alignof__(struct device_node)); > + if (!dryrun) { > + char *fn; > + > + fn =3D (char *)np + sizeof(*np); > + np->full_name =3D 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? =20 Lothar Wa=C3=9Fmann