mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 12/29] of: make unflatten independent of libfdt
Date: Tue, 26 Feb 2013 21:18:39 +0100	[thread overview]
Message-ID: <1361909936-2665-13-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1361909936-2665-1-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/of/base.c |  160 +++++++++++++++++++++++++++++++++++++++++------------
 include/of.h      |    2 +-
 2 files changed, 127 insertions(+), 35 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 9f1f3cf..d6ca949 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -969,92 +969,184 @@ out:
 	return dn;
 }
 
+static inline uint32_t dt_struct_advance(struct fdt_header *f, uint32_t dt, int size)
+{
+	dt += size;
+	dt = ALIGN(dt, 4);
+
+	if (dt > f->off_dt_struct + f->size_dt_struct)
+		return 0;
+
+	return dt;
+}
+
+static inline char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs)
+{
+	if (ofs > f->size_dt_strings)
+		return NULL;
+	else
+		return strstart + ofs;
+}
+
 /**
- * of_unflatten_dtb - unflatten a fdt blob
+ * of_unflatten_dtb - unflatten a dtb binary blob
  * @root - node in which the fdt blob should be merged into or NULL
- * @fdt - the fdt blob to unflatten
+ * @infdt - the fdt blob to unflatten
  *
  * Parse a flat device tree binary blob and return a pointer to the
  * unflattened tree.
  */
-struct device_node *of_unflatten_dtb(struct device_node *root, struct fdt_header *fdt)
+struct device_node *of_unflatten_dtb(struct device_node *root, void *infdt)
 {
 	const void *nodep;	/* property node pointer */
-	int  nodeoffset;	/* node offset from libfdt */
-	int  nextoffset;	/* next node offset from libfdt */
 	uint32_t tag;		/* tag */
 	int  len;		/* length of the property */
 	const struct fdt_property *fdt_prop;
-	const char *pathp;
+	const char *pathp, *name;
 	struct device_node *node = NULL, *n;
 	struct property *p;
-	int ret;
+	uint32_t dt_struct;
+	struct fdt_node_header *fnh;
+	void *dt_strings;
+	struct fdt_header f;
+	int ret, merge = 0;
+	unsigned int maxlen;
+	struct fdt_header *fdt = infdt;
+
+	if (fdt->magic != cpu_to_fdt32(FDT_MAGIC)) {
+		pr_err("bad magic: 0x%08x\n", fdt32_to_cpu(fdt->magic));
+		return ERR_PTR(-EINVAL);
+	}
 
-	nodeoffset = fdt_path_offset(fdt, "/");
-	if (nodeoffset < 0) {
-		/*
-		 * Not found or something else bad happened.
-		 */
-		printf ("libfdt fdt_path_offset() returned %s\n",
-			fdt_strerror(nodeoffset));
+	if (fdt->version != cpu_to_fdt32(17)) {
+		pr_err("bad dt version: 0x%08x\n", fdt32_to_cpu(fdt->version));
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (!root) {
+	f.totalsize = fdt32_to_cpu(fdt->totalsize);
+	f.off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct);
+	f.size_dt_struct = fdt32_to_cpu(fdt->size_dt_struct);
+	f.off_dt_strings = fdt32_to_cpu(fdt->off_dt_strings);
+	f.size_dt_strings = fdt32_to_cpu(fdt->size_dt_strings);
+
+	if (f.off_dt_struct + f.size_dt_struct > f.totalsize) {
+		pr_err("unflatten: dt size exceeds total size\n");
+		return ERR_PTR(-ESPIPE);
+	}
+
+	if (f.off_dt_strings + f.size_dt_strings > f.totalsize) {
+		pr_err("unflatten: string size exceeds total size\n");
+		return ERR_PTR(-ESPIPE);
+	}
+
+	dt_struct = f.off_dt_struct;
+	dt_strings = (void *)fdt + f.off_dt_strings;
+
+	if (root) {
+		pr_debug("unflatten: merging into existing tree\n");
+		merge = 1;
+	} else {
 		root = of_new_node(NULL, NULL);
 		if (!root)
 			return ERR_PTR(-ENOMEM);
 	}
 
 	while (1) {
-		tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+		tag = be32_to_cpu(*(uint32_t *)(infdt + dt_struct));
+
 		switch (tag) {
 		case FDT_BEGIN_NODE:
-			pathp = fdt_get_name(fdt, nodeoffset, NULL);
+			fnh = infdt + dt_struct;
+			pathp = name = fnh->name;
+			maxlen = (unsigned long)fdt + f.off_dt_struct +
+				f.size_dt_struct - (unsigned long)name;
+
+			len = strnlen(name, maxlen + 1);
+			if (len > maxlen) {
+				ret = -ESPIPE;
+				goto err;
+			}
 
-			if (pathp == NULL)
-				pathp = "/* NULL pointer error */";
+			dt_struct = dt_struct_advance(&f, dt_struct,
+					sizeof(struct fdt_node_header) + len + 1);
+			if (!dt_struct) {
+				ret = -ESPIPE;
+				goto err;
+			}
 
 			if (!node) {
 				node = root;
 			} else {
-				if ((n = of_find_child_by_name(node, pathp))) {
+				if (merge && (n = of_find_child_by_name(node, pathp)))
 					node = n;
-				} else {
+				else
 					node = of_new_node(node, pathp);
-				}
 			}
+
 			break;
+
 		case FDT_END_NODE:
+			if (!node) {
+				pr_err("unflatten: too many end nodes\n");
+				ret = -EINVAL;
+				goto err;
+			}
+
 			node = node->parent;
+
+			dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+			if (!dt_struct) {
+				ret = -ESPIPE;
+				goto err;
+			}
+
 			break;
+
 		case FDT_PROP:
-			fdt_prop = fdt_offset_ptr(fdt, nodeoffset,
-					sizeof(*fdt_prop));
-			pathp    = fdt_string(fdt,
-					fdt32_to_cpu(fdt_prop->nameoff));
-			len      = fdt32_to_cpu(fdt_prop->len);
-			nodep    = fdt_prop->data;
-
-			p = of_find_property(node, pathp);
-			if (p) {
+			fdt_prop = infdt + dt_struct;
+			len = fdt32_to_cpu(fdt_prop->len);
+			nodep = fdt_prop->data;
+
+			name = dt_string(&f, dt_strings, fdt32_to_cpu(fdt_prop->nameoff));
+			if (!name) {
+				ret = -ESPIPE;
+				goto err;
+			}
+
+			dt_struct = dt_struct_advance(&f, dt_struct,
+					sizeof(struct fdt_property) + len);
+			if (!dt_struct) {
+				ret = -ESPIPE;
+				goto err;
+			}
+
+			if (merge && (p = of_find_property(node, name))) {
 				free(p->value);
 				p->value = xzalloc(len);
 				memcpy(p->value, nodep, len);
 			} else {
-				of_new_property(node, pathp, nodep, len);
+				of_new_property(node, name, nodep, len);
 			}
+
 			break;
+
 		case FDT_NOP:
+			dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+			if (!dt_struct) {
+				ret = -ESPIPE;
+				goto err;
+			}
+
 			break;
+
 		case FDT_END:
 			return root;
+
 		default:
-			printf("Unknown tag 0x%08X\n", tag);
+			pr_err("unflatten: Unknown tag 0x%08X\n", tag);
 			ret = -EINVAL;
 			goto err;
 		}
-		nodeoffset = nextoffset;
 	}
 err:
 	of_free(root);
diff --git a/include/of.h b/include/of.h
index 89ce64c..f2fd84b 100644
--- a/include/of.h
+++ b/include/of.h
@@ -119,7 +119,7 @@ void of_print_nodes(struct device_node *node, int indent);
 int of_probe(void);
 int of_parse_dtb(struct fdt_header *fdt);
 void of_free(struct device_node *node);
-struct device_node *of_unflatten_dtb(struct device_node *root, struct fdt_header *fdt);
+struct device_node *of_unflatten_dtb(struct device_node *root, void *fdt);
 struct device_node *of_new_node(struct device_node *parent, const char *name);
 struct property *of_new_property(struct device_node *node, const char *name,
 		const void *data, int len);
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2013-02-26 20:19 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer
2013-02-26 20:18 ` [PATCH 01/29] of: unflatten: allocate root node explicitly Sascha Hauer
2013-02-26 20:18 ` [PATCH 02/29] of: export of_find_child Sascha Hauer
2013-02-26 20:18 ` [PATCH 03/29] of: removed unused variables Sascha Hauer
2013-02-26 20:18 ` [PATCH 04/29] of: Let of_find_node_by_path iterate over tree Sascha Hauer
2013-02-26 20:18 ` [PATCH 05/29] of: remove allnodes list Sascha Hauer
2013-02-26 20:18 ` [PATCH 06/29] ARM bootm: Use of_get_fixed_tree Sascha Hauer
2013-02-26 20:18 ` [PATCH 07/29] of: Add of_set_property and of_create_node Sascha Hauer
2013-02-26 20:18 ` [PATCH 08/29] of_node command: use of_create_node Sascha Hauer
2013-02-26 20:18 ` [PATCH 09/29] of: Add root node argument to of_find_node_by_path Sascha Hauer
2013-02-26 20:18 ` [PATCH 10/29] of: Add missing prototype for of_device_is_compatible Sascha Hauer
2013-02-26 20:18 ` [PATCH 11/29] of: let of_unflatten_dtb return the unflattened tree Sascha Hauer
2013-02-26 20:18 ` Sascha Hauer [this message]
2013-02-26 20:18 ` [PATCH 13/29] of: make flatten independent of libfdt Sascha Hauer
2013-02-26 21:05   ` Alexander Aring
2013-02-27  8:40     ` Sascha Hauer
2013-02-27 19:52       ` Alexander Aring
2013-02-26 20:18 ` [PATCH 14/29] of/fdt: use optimized endianess conversion Sascha Hauer
2013-02-26 20:18 ` [PATCH 15/29] oftree command: Use of_print_nodes Sascha Hauer
2013-02-26 20:18 ` [PATCH 16/29] of: move OFTREE Kconfig option to drivers/of/ Sascha Hauer
2013-02-26 20:18 ` [PATCH 17/29] of: make OFDEVICE a user selectable option Sascha Hauer
2013-02-26 20:18 ` [PATCH 18/29] oftree command: retire CMD_OFTREE_PROBE Kconfig option Sascha Hauer
2013-02-26 20:18 ` [PATCH 19/29] of: move oftree Kconfig to the top of the drivers menu Sascha Hauer
2013-02-26 20:18 ` [PATCH 20/29] of: Pass barebox internal format devicetree to of_get_fixed_tree Sascha Hauer
2013-02-26 20:18 ` [PATCH 21/29] bootm: Use of_print_nodes instead of fdt_print Sascha Hauer
2013-02-26 20:18 ` [PATCH 22/29] of: move flat devicetree functions to separate file Sascha Hauer
2013-02-26 20:18 ` [PATCH 23/29] of: Add of property write functions for u32 Sascha Hauer
2013-02-26 20:18 ` [PATCH 24/29] of: make value of property in of_new_property optional Sascha Hauer
2013-02-26 20:18 ` [PATCH 25/29] of: Add missing prototype for size/address counting functions Sascha Hauer
2013-02-26 20:18 ` [PATCH 26/29] of: fixup unflattened devicetree Sascha Hauer
2013-02-26 20:18 ` [PATCH 27/29] of: remove unused libfdt Sascha Hauer
2013-02-26 20:18 ` [PATCH 28/29] of_* commands: print usage when insufficient arguments are given Sascha Hauer
2013-02-26 20:18 ` [PATCH 29/29] of_property command: Fix crash with empty property value Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1361909936-2665-13-git-send-email-s.hauer@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox