From: Sascha Hauer <s.hauer@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 14/37] of: make unflatten independent of libfdt
Date: Mon, 4 Mar 2013 10:53:17 +0100 [thread overview]
Message-ID: <1362390820-10333-15-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1362390820-10333-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 4dbe11e..8bb80e6 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1025,92 +1025,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 1562f4e..4622b80 100644
--- a/include/of.h
+++ b/include/of.h
@@ -147,7 +147,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
next prev parent reply other threads:[~2013-03-04 9:53 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-04 9:53 [PATCH v2] remove libfdt Sascha Hauer
2013-03-04 9:53 ` [PATCH 01/37] of: unflatten: allocate root node explicitly Sascha Hauer
2013-03-04 9:53 ` [PATCH 02/37] of: export of_find_child Sascha Hauer
2013-03-04 9:53 ` [PATCH 03/37] of: removed unused variables Sascha Hauer
2013-03-04 9:53 ` [PATCH 04/37] of: Let of_find_node_by_path iterate over tree Sascha Hauer
2013-03-04 9:53 ` [PATCH 05/37] of: remove allnodes list Sascha Hauer
2013-03-04 9:53 ` [PATCH 06/37] ARM bootm: Use of_get_fixed_tree Sascha Hauer
2013-03-04 9:53 ` [PATCH 07/37] of: Add of_set_property and of_create_node Sascha Hauer
2013-03-04 9:53 ` [PATCH 08/37] of_node command: use of_create_node Sascha Hauer
2013-03-04 9:53 ` [PATCH 09/37] of: Add missing prototype for of_device_is_compatible Sascha Hauer
2013-03-04 9:53 ` [PATCH 10/37] of: let of_unflatten_dtb return the unflattened tree Sascha Hauer
2013-03-04 9:53 ` [PATCH 11/37] of: Add root node argument to of_find_node_by_path Sascha Hauer
2013-03-04 9:53 ` [PATCH 12/37] of: Add of_write_number helper Sascha Hauer
2013-03-04 9:53 ` [PATCH 13/37] of: Add initrd helper Sascha Hauer
2013-03-04 12:01 ` Alexander Aring
2013-03-04 9:53 ` Sascha Hauer [this message]
2013-03-04 9:53 ` [PATCH 15/37] of: make flatten independent of libfdt Sascha Hauer
2013-03-04 9:53 ` [PATCH 16/37] of/fdt: use optimized endianess conversion Sascha Hauer
2013-03-04 9:53 ` [PATCH 17/37] oftree command: Use of_print_nodes Sascha Hauer
2013-03-04 9:53 ` [PATCH 18/37] of: move OFTREE Kconfig option to drivers/of/ Sascha Hauer
2013-03-04 9:53 ` [PATCH 19/37] of: make OFDEVICE a user selectable option Sascha Hauer
2013-03-04 9:53 ` [PATCH 20/37] oftree command: retire CMD_OFTREE_PROBE Kconfig option Sascha Hauer
2013-03-04 9:53 ` [PATCH 21/37] of: move oftree Kconfig to the top of the drivers menu Sascha Hauer
2013-03-04 9:53 ` [PATCH 22/37] of: Pass barebox internal format devicetree to of_get_fixed_tree Sascha Hauer
2013-03-04 9:53 ` [PATCH 23/37] bootm: Use of_print_nodes instead of fdt_print Sascha Hauer
2013-03-04 9:53 ` [PATCH 24/37] of: move flat devicetree functions to separate file Sascha Hauer
2013-03-04 9:53 ` [PATCH 25/37] of: Add of property write functions for u32 Sascha Hauer
2013-03-04 9:53 ` [PATCH 26/37] of: make value of property in of_new_property optional Sascha Hauer
2013-03-04 9:53 ` [PATCH 27/37] of: Add missing prototype for size/address counting functions Sascha Hauer
2013-03-04 9:53 ` [PATCH 28/37] of: fixup unflattened devicetree Sascha Hauer
2013-03-04 9:53 ` [PATCH 29/37] of_* commands: print usage when insufficient arguments are given Sascha Hauer
2013-03-04 9:53 ` [PATCH 30/37] of_property command: Fix crash with empty property value Sascha Hauer
2013-03-04 9:53 ` [PATCH 31/37] ARM: bootm: rework concatenated oftree Sascha Hauer
2013-03-04 9:53 ` [PATCH 32/37] of: memory: Use of_write_number Sascha Hauer
2013-03-04 9:53 ` [PATCH 33/37] of: Add reservemap handling Sascha Hauer
2013-03-04 9:53 ` [PATCH 34/37] bootm: Pass unflattened devicetree to handlers Sascha Hauer
2013-03-04 9:53 ` [PATCH 35/37] ARM bootm: Switch initrd support to unflattened tree Sascha Hauer
2013-03-04 9:53 ` [PATCH 36/37] of: remove unused libfdt Sascha Hauer
2013-03-04 9:53 ` [PATCH 37/37] of: make locally used functions static 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=1362390820-10333-15-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