* [PATCH] remove libfdt @ 2013-02-26 20:18 Sascha Hauer 2013-02-26 20:18 ` [PATCH 01/29] of: unflatten: allocate root node explicitly Sascha Hauer ` (28 more replies) 0 siblings, 29 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox In the beginning we only had libfdt to handle devicetrees. With devicetree probing support we gained two parallel universes for handling devicetrees. This series cleans this up by switching to the internal devicetree completely and removing libfdt. The dtb format is now only used while flattening/unflattening the tree. All tree manipulation is done on the internal tree format only. This introduces some time overhead (~2ms on a i.MX51) needed for (un)flattening the tree, but actually manipulating the tree is a factor of about 50 faster compared to libfdt. This means the overhead can become more than compensated once we start manipulating the tree in more places. The overall code and binary size becomes a bit smaller with this due to less duplicated code. Sascha The following changes since commit 8c82b1b2021591a8c3537958c7fa60816c584d8a: OMAP4 USB BOOT: remove double line endings (2013-02-25 09:18:03 +0100) are available in the git repository at: git://git.pengutronix.de/git/barebox.git pu/oftree for you to fetch changes up to 417227b61e2331fa4285aaac42ee22f5db84cbc1: of_property command: Fix crash with empty property value (2013-02-26 20:42:46 +0100) ---------------------------------------------------------------- Sascha Hauer (29): of: unflatten: allocate root node explicitly of: export of_find_child of: removed unused variables of: Let of_find_node_by_path iterate over tree of: remove allnodes list ARM bootm: Use of_get_fixed_tree of: Add of_set_property and of_create_node of_node command: use of_create_node of: Add root node argument to of_find_node_by_path of: Add missing prototype for of_device_is_compatible of: let of_unflatten_dtb return the unflattened tree of: make unflatten independent of libfdt of: make flatten independent of libfdt of/fdt: use optimized endianess conversion oftree command: Use of_print_nodes of: move OFTREE Kconfig option to drivers/of/ of: make OFDEVICE a user selectable option oftree command: retire CMD_OFTREE_PROBE Kconfig option of: move oftree Kconfig to the top of the drivers menu of: Pass barebox internal format devicetree to of_get_fixed_tree bootm: Use of_print_nodes instead of fdt_print of: move flat devicetree functions to separate file of: Add of property write functions for u32 of: make value of property in of_new_property optional of: Add missing prototype for size/address counting functions of: fixup unflattened devicetree of: remove unused libfdt of_* commands: print usage when insufficient arguments are given of_property command: Fix crash with empty property value arch/arm/boards/at91sam9m10ihd/hw_version.c | 1 - arch/arm/boards/at91sam9x5ek/hw_version.c | 32 +- arch/arm/boards/sama5d3xek/hw_version.c | 1 - arch/arm/lib/bootm.c | 13 +- arch/ppc/mach-mpc5xxx/cpu.c | 26 +- commands/Kconfig | 10 - commands/bootm.c | 16 +- commands/of_node.c | 33 +- commands/of_property.c | 24 +- commands/oftree.c | 42 +- common/memory.c | 49 +- common/oftree.c | 223 +---- drivers/Kconfig | 2 +- drivers/Makefile | 2 +- drivers/of/Kconfig | 6 +- drivers/of/Makefile | 2 +- drivers/of/base.c | 319 ++++--- drivers/of/dtb.c | 400 +++++++++ include/fdt.h | 13 + include/libfdt.h | 1235 --------------------------- include/libfdt_env.h | 22 - include/of.h | 68 +- lib/Kconfig | 7 - lib/Makefile | 1 - lib/fdt/Makefile | 2 - lib/fdt/TODO | 3 - lib/fdt/fdt.c | 222 ----- lib/fdt/fdt_ro.c | 574 ------------- lib/fdt/fdt_rw.c | 465 ---------- lib/fdt/fdt_strerror.c | 96 --- lib/fdt/fdt_sw.c | 256 ------ lib/fdt/fdt_wip.c | 118 --- lib/fdt/libfdt_internal.h | 95 --- 33 files changed, 770 insertions(+), 3608 deletions(-) create mode 100644 drivers/of/dtb.c delete mode 100644 include/libfdt.h delete mode 100644 include/libfdt_env.h delete mode 100644 lib/fdt/Makefile delete mode 100644 lib/fdt/TODO delete mode 100644 lib/fdt/fdt.c delete mode 100644 lib/fdt/fdt_ro.c delete mode 100644 lib/fdt/fdt_rw.c delete mode 100644 lib/fdt/fdt_strerror.c delete mode 100644 lib/fdt/fdt_sw.c delete mode 100644 lib/fdt/fdt_wip.c delete mode 100644 lib/fdt/libfdt_internal.h _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 01/29] of: unflatten: allocate root node explicitly 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 02/29] of: export of_find_child Sascha Hauer ` (27 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox By doing so of_new_node does not depend on the global root_node anymore. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index eaaeaf4..e853add 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -890,7 +890,7 @@ int of_unflatten_dtb(struct fdt_header *fdt) const struct fdt_property *fdt_prop; const char *pathp; int depth = 10000; - struct device_node *node = NULL, *n; + struct device_node *node = NULL, *n, *root = NULL; struct property *p; nodeoffset = fdt_path_offset(fdt, "/"); @@ -903,6 +903,10 @@ int of_unflatten_dtb(struct fdt_header *fdt) return -EINVAL; } + root = of_new_node(NULL, NULL); + if (!root) + return -ENOMEM; + while (1) { tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); switch (tag) { @@ -912,11 +916,14 @@ int of_unflatten_dtb(struct fdt_header *fdt) if (pathp == NULL) pathp = "/* NULL pointer error */"; - n = of_find_child(node, pathp); - if (n) { - node = n; + if (!node) { + node = root; } else { - node = of_new_node(node, pathp); + if ((n = of_find_child(node, pathp))) { + node = n; + } else { + node = of_new_node(node, pathp); + } } break; case FDT_END_NODE: -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 02/29] of: export of_find_child 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 03/29] of: removed unused variables Sascha Hauer ` (26 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox of_find_child is a useful function. Export it and rename it to of_find_child_by_name. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 16 +++------------- include/of.h | 2 ++ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index e853add..f016f90 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -854,23 +854,13 @@ int of_probe(void) return 0; } -static struct device_node *of_find_child(struct device_node *node, const char *name) +struct device_node *of_find_child_by_name(struct device_node *node, const char *name) { struct device_node *_n; - if (!root_node) - return NULL; - - if (!node && !*name) - return root_node; - - if (!node) - node = root_node; - - list_for_each_entry(_n, &node->children, parent_list) { + device_node_for_nach_child(node, _n) if (!strcmp(_n->name, name)) return _n; - } return NULL; } @@ -919,7 +909,7 @@ int of_unflatten_dtb(struct fdt_header *fdt) if (!node) { node = root; } else { - if ((n = of_find_child(node, pathp))) { + if ((n = of_find_child_by_name(node, pathp))) { node = n; } else { node = of_new_node(node, pathp); diff --git a/include/of.h b/include/of.h index d3a310f..59bdc6e 100644 --- a/include/of.h +++ b/include/of.h @@ -58,6 +58,8 @@ struct property *of_find_property(const struct device_node *node, const char *na struct device_node *of_find_node_by_path(const char *path); +struct device_node *of_find_child_by_name(struct device_node *node, const char *name); + struct fdt_header *fdt_get_tree(void); #define device_node_for_nach_child(node, child) \ -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 03/29] of: removed unused variables 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 04/29] of: Let of_find_node_by_path iterate over tree Sascha Hauer ` (25 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index f016f90..704ba8e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -876,10 +876,8 @@ int of_unflatten_dtb(struct fdt_header *fdt) int nextoffset; /* next node offset from libfdt */ uint32_t tag; /* tag */ int len; /* length of the property */ - int level = 0; /* keep track of nesting level */ const struct fdt_property *fdt_prop; const char *pathp; - int depth = 10000; struct device_node *node = NULL, *n, *root = NULL; struct property *p; @@ -942,8 +940,7 @@ int of_unflatten_dtb(struct fdt_header *fdt) of_alias_scan(); return 0; default: - if (level <= depth) - printf("Unknown tag 0x%08X\n", tag); + printf("Unknown tag 0x%08X\n", tag); return -EINVAL; } nodeoffset = nextoffset; -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 04/29] of: Let of_find_node_by_path iterate over tree 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (2 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 03/29] of: removed unused variables Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 05/29] of: remove allnodes list Sascha Hauer ` (24 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox of_find_node_by_path iterates over the allnodes list. Depending on where the node we look for is, this can be significantly slower than using the tree structure to look for a node, so iterate over the tree instead. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 704ba8e..1c33be1 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -490,17 +490,40 @@ EXPORT_SYMBOL(of_machine_is_compatible); */ struct device_node *of_find_node_by_path(const char *path) { - struct device_node *np; + char *slash, *p, *freep; + struct device_node *dn = root_node; + + if (!root_node) + return NULL; + + if (*path != '/') + return NULL; + + path++; - if (!strcmp(path, "/")) - return root_node; + freep = p = xstrdup(path); - list_for_each_entry(np, &allnodes, list) { - if (np->full_name && (strcmp(np->full_name, path) == 0)) - return np; + while (1) { + if (!*p) + goto out; + + slash = strchr(p, '/'); + if (slash) + *slash = 0; + + dn = of_find_child_by_name(dn, p); + if (!dn) + goto out; + + if (!slash) + goto out; + + p = slash + 1; } +out: + free(freep); - return NULL; + return dn; } EXPORT_SYMBOL(of_find_node_by_path); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 05/29] of: remove allnodes list 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (3 preceding siblings ...) 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 06/29] ARM bootm: Use of_get_fixed_tree Sascha Hauer ` (23 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox The allnodes list makes it hard to handle multiple devicetrees. Having a list to iterate over all nodes of a tree is still good to have though. This patch uses the list_head of the root node as the head of the list. This way the root node is no longer part of the list, but when iterating over a tree the root node is not interesting anyway. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 12 +++++------- include/of.h | 8 ++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 1c33be1..d6c346d 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -50,8 +50,6 @@ static LIST_HEAD(aliases_lookup); static LIST_HEAD(phandle_list); -static LIST_HEAD(allnodes); - struct device_node *root_node; struct device_node *of_aliases; @@ -628,13 +626,13 @@ struct device_node *of_new_node(struct device_node *parent, const char *name) if (parent) { node->name = xstrdup(name); node->full_name = asprintf("%s/%s", node->parent->full_name, name); + list_add(&node->list, &parent->list); } else { node->name = xstrdup(""); node->full_name = xstrdup(""); + INIT_LIST_HEAD(&node->list); } - list_add_tail(&node->list, &allnodes); - return node; } @@ -812,8 +810,6 @@ void of_free(struct device_node *node) if (!node) return; - list_del(&node->list); - list_for_each_entry_safe(p, pt, &node->properties, list) { list_del(&p->list); free(p->name); @@ -825,8 +821,10 @@ void of_free(struct device_node *node) of_free(n); } - if (node->parent) + if (node->parent) { list_del(&node->parent_list); + list_del(&node->list); + } if (node->device) node->device->device_node = NULL; diff --git a/include/of.h b/include/of.h index 59bdc6e..933e855 100644 --- a/include/of.h +++ b/include/of.h @@ -65,6 +65,14 @@ struct fdt_header *fdt_get_tree(void); #define device_node_for_nach_child(node, child) \ list_for_each_entry(child, &node->children, parent_list) +/* + * Iterate over all nodes of a tree. As a devicetree does not + * have a dedicated list head, the start node (usually the root + * node) will not be iterated over. + */ +#define of_tree_for_each_node(node, root) \ + list_for_each_entry(node, &root->list, list) + /* Helper to read a big number; size is in cells (not bytes) */ static inline u64 of_read_number(const __be32 *cell, int size) { -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 06/29] ARM bootm: Use of_get_fixed_tree 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (4 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 05/29] of: remove allnodes list Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 07/29] of: Add of_set_property and of_create_node Sascha Hauer ` (22 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/lib/bootm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index dc29004..cf192cf 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -181,13 +181,7 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data) } if (IS_BUILTIN(CONFIG_OFTREE)) { - fdt_open_into(oftree, oftree, end + 0x8000); - - ret = of_fix_tree(oftree); - if (ret) - return ret; - - data->oftree = oftree; + data->oftree = of_get_fixed_tree(oftree); } pr_info("zImage: concatenated oftree detected\n"); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 07/29] of: Add of_set_property and of_create_node 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (5 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 06/29] ARM bootm: Use of_get_fixed_tree Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 08/29] of_node command: use of_create_node Sascha Hauer ` (21 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Add functions to create a new device node and to create/set a new property based on the nodepath. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/of.h | 3 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index d6c346d..ecc49c4 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -662,6 +662,41 @@ void of_delete_property(struct property *pp) free(pp); } +/** + * of_set_property - create a property for a given node + * @node - the node + * @name - the name of the property + * @val - the value for the property + * @len - the length of the properties value + * @create - if true, the property is created if not existing already + */ +int of_set_property(struct device_node *np, const char *name, const void *val, int len, + int create) +{ + struct property *pp; + + if (!np) + return -ENOENT; + + pp = of_find_property(np, name); + if (pp) { + void *data; + + free(pp->value); + data = xzalloc(len); + memcpy(data, val, len); + pp->value = data; + pp->length = len; + } else { + if (!create) + return -ENOENT; + + pp = of_new_property(np, name, val, len); + } + + return 0; +} + static struct device_d *add_of_device(struct device_node *node) { struct device_d *dev; @@ -886,6 +921,50 @@ struct device_node *of_find_child_by_name(struct device_node *node, const char * return NULL; } +/** + * of_create_node - create a new node including its parents + * @path - the nodepath to create + */ +struct device_node *of_create_node(struct device_node *root, const char *path) +{ + char *slash, *p, *freep; + struct device_node *tmp, *dn = root; + + if (*path != '/') + return NULL; + + path++; + + p = freep = xstrdup(path); + + while (1) { + if (!*p) + goto out; + + slash = strchr(p, '/'); + if (slash) + *slash = 0; + + tmp = of_find_child_by_name(dn, p); + if (tmp) + dn = tmp; + else + dn = of_new_node(dn, p); + + if (!dn) + goto out; + + if (!slash) + goto out; + + p = slash + 1; + } +out: + free(freep); + + return dn; +} + /* * Parse a flat device tree binary blob and store it in the barebox * internal tree format, diff --git a/include/of.h b/include/of.h index 933e855..12c5703 100644 --- a/include/of.h +++ b/include/of.h @@ -124,6 +124,9 @@ void of_delete_property(struct property *pp); int of_property_read_string(struct device_node *np, const char *propname, const char **out_string); +int of_set_property(struct device_node *node, const char *p, const void *val, int len, + int create); +struct device_node *of_create_node(struct device_node *root, const char *path); #ifdef CONFIG_OFDEVICE int of_parse_partitions(const char *cdevname, -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 08/29] of_node command: use of_create_node 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (6 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 07/29] of: Add of_set_property and of_create_node Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 09/29] of: Add root node argument to of_find_node_by_path Sascha Hauer ` (20 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/of_node.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/commands/of_node.c b/commands/of_node.c index a370e26..bf9799c 100644 --- a/commands/of_node.c +++ b/commands/of_node.c @@ -39,6 +39,7 @@ static int do_of_node(int argc, char *argv[]) int create = 0; char *path = NULL; struct device_node *node = NULL; + struct device_node *root; while ((opt = getopt(argc, argv, "cd")) > 0) { switch (opt) { @@ -57,27 +58,19 @@ static int do_of_node(int argc, char *argv[]) path = argv[optind]; } - if (create) { - char *name; + root = of_get_root_node(); + if (!root) { + printf("root node not set\n"); + return -ENOENT; + } + if (create) { if (!path) return COMMAND_ERROR_USAGE; - name = xstrdup(basename(path)); - path = dirname(path); - - node = of_find_node_by_path(path); - if (!node) { - printf("Cannot find nodepath %s\n", path); - free(name); - return -ENOENT; - } - - debug("create node \"%s\" \"%s\"\n", path, name); - - of_new_node(node, name); - - free(name); + node = of_create_node(root, path); + if (!node) + return -EINVAL; return 0; } -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 09/29] of: Add root node argument to of_find_node_by_path 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (7 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 08/29] of_node command: use of_create_node Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 10/29] of: Add missing prototype for of_device_is_compatible Sascha Hauer ` (19 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox This makes of_find_node_by_path usable with multiple trees. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/of_node.c | 2 +- commands/of_property.c | 10 ++++++++-- commands/oftree.c | 10 +++++++++- drivers/of/base.c | 16 +++++++--------- include/of.h | 2 +- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/commands/of_node.c b/commands/of_node.c index bf9799c..2f6ecae 100644 --- a/commands/of_node.c +++ b/commands/of_node.c @@ -79,7 +79,7 @@ static int do_of_node(int argc, char *argv[]) if (!path) return COMMAND_ERROR_USAGE; - node = of_find_node_by_path(path); + node = of_find_node_by_path(root, path); if (!node) { printf("Cannot find nodepath %s\n", path); return -ENOENT; diff --git a/commands/of_property.c b/commands/of_property.c index 42b6f11..585522c 100644 --- a/commands/of_property.c +++ b/commands/of_property.c @@ -176,7 +176,7 @@ static int do_of_property(int argc, char *argv[]) int set = 0; int ret; char *path = NULL, *propname = NULL; - struct device_node *node = NULL; + struct device_node *root, *node = NULL; struct property *pp = NULL; while ((opt = getopt(argc, argv, "ds")) > 0) { @@ -192,9 +192,15 @@ static int do_of_property(int argc, char *argv[]) } } + root = of_get_root_node(); + if (!root) { + printf("root node not set\n"); + return -ENOENT; + } + if (optind < argc) { path = argv[optind]; - node = of_find_node_by_path(path); + node = of_find_node_by_path(root, path); if (!node) { printf("Cannot find nodepath %s\n", path); return -ENOENT; diff --git a/commands/oftree.c b/commands/oftree.c index ddbff3e..0ee787e 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -146,7 +146,15 @@ static int do_oftree(int argc, char *argv[]) if (fdt) { ret = fdt_print(fdt, node); } else { - struct device_node *n = of_find_node_by_path(node); + struct device_node *root, *n; + + root = of_get_root_node(); + if (!root) { + ret = -ENOENT; + goto out; + } + + n = of_find_node_by_path(root, node); if (!n) { ret = -ENOENT; diff --git a/drivers/of/base.c b/drivers/of/base.c index ecc49c4..0eafa39 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -144,7 +144,7 @@ void of_alias_scan(void) INIT_LIST_HEAD(&aliases_lookup); - of_aliases = of_find_node_by_path("/aliases"); + of_aliases = of_find_node_by_path(root_node, "/aliases"); if (!of_aliases) return; @@ -161,7 +161,7 @@ void of_alias_scan(void) !strcmp(pp->name, "linux,phandle")) continue; - np = of_find_node_by_path(pp->value); + np = of_find_node_by_path(root_node, pp->value); if (!np) continue; @@ -481,18 +481,16 @@ EXPORT_SYMBOL(of_machine_is_compatible); /** * of_find_node_by_path - Find a node matching a full OF path + * @root: The root node of this tree * @path: The full path to match * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ -struct device_node *of_find_node_by_path(const char *path) +struct device_node *of_find_node_by_path(struct device_node *root, const char *path) { char *slash, *p, *freep; - struct device_node *dn = root_node; - - if (!root_node) - return NULL; + struct device_node *dn = root; if (*path != '/') return NULL; @@ -902,7 +900,7 @@ int of_probe(void) if(!root_node) return -ENODEV; - of_chosen = of_find_node_by_path("/chosen"); + of_chosen = of_find_node_by_path(root_node, "/chosen"); of_property_read_string(root_node, "model", &of_model); __of_probe(root_node); @@ -1122,7 +1120,7 @@ int of_device_is_stdout_path(struct device_d *dev) name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name == NULL) return 0; - dn = of_find_node_by_path(name); + dn = of_find_node_by_path(root_node, name); if (!dn) return 0; diff --git a/include/of.h b/include/of.h index 12c5703..82475c3 100644 --- a/include/of.h +++ b/include/of.h @@ -56,7 +56,7 @@ int of_match(struct device_d *dev, struct driver_d *drv); struct property *of_find_property(const struct device_node *node, const char *name); -struct device_node *of_find_node_by_path(const char *path); +struct device_node *of_find_node_by_path(struct device_node *root, const char *path); struct device_node *of_find_child_by_name(struct device_node *node, const char *name); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 10/29] of: Add missing prototype for of_device_is_compatible 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (8 preceding siblings ...) 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 11/29] of: let of_unflatten_dtb return the unflattened tree Sascha Hauer ` (18 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- include/of.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/of.h b/include/of.h index 82475c3..c324c74 100644 --- a/include/of.h +++ b/include/of.h @@ -107,6 +107,9 @@ int of_get_named_gpio(struct device_node *np, struct device_node *of_find_node_by_phandle(phandle phandle); void of_print_property(const void *data, int len); +int of_device_is_compatible(const struct device_node *device, + const char *compat); + int of_machine_is_compatible(const char *compat); #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 11/29] of: let of_unflatten_dtb return the unflattened tree 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (9 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 10/29] of: Add missing prototype for of_device_is_compatible Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 12/29] of: make unflatten independent of libfdt Sascha Hauer ` (17 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox In order to be able to handle multiple devicetrees, do not assume the tree to be unflattened is the barebox internal one. Instead, just return a pointer to it and assign the barebox internal root_node external to the unflatten function. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/oftree.c | 14 ++++++++++++- drivers/of/base.c | 57 +++++++++++++++++++++++++++++++++-------------------- include/of.h | 3 ++- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/commands/oftree.c b/commands/oftree.c index 0ee787e..83ffe12 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -32,6 +32,7 @@ #include <malloc.h> #include <libfdt.h> #include <linux/ctype.h> +#include <linux/err.h> #include <asm/byteorder.h> #include <errno.h> #include <getopt.h> @@ -52,6 +53,7 @@ static int do_oftree(int argc, char *argv[]) int save = 0; int free_of = 0; int ret; + struct device_node *n, *root; while ((opt = getopt(argc, argv, "dpfn:ls")) > 0) { switch (opt) { @@ -135,7 +137,17 @@ static int do_oftree(int argc, char *argv[]) goto out; } - ret = of_unflatten_dtb(fdt); + n = of_get_root_node(); + + root = of_unflatten_dtb(n, fdt); + if (IS_ERR(root)) + ret = PTR_ERR(root); + else + ret = 0; + + if (!n) + ret = of_set_root_node(root); + if (ret) { printf("parse oftree: %s\n", strerror(-ret)); goto out; diff --git a/drivers/of/base.c b/drivers/of/base.c index 0eafa39..9f1f3cf 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -26,6 +26,7 @@ #include <memory.h> #include <sizes.h> #include <linux/ctype.h> +#include <linux/err.h> /** * struct alias_prop - Alias property in 'aliases' node @@ -558,6 +559,18 @@ struct device_node *of_get_root_node(void) return root_node; } +int of_set_root_node(struct device_node *node) +{ + if (node && root_node) + return -EBUSY; + + root_node = node; + + of_alias_scan(); + + return 0; +} + static int of_node_disabled(struct device_node *node) { struct property *p; @@ -608,15 +621,10 @@ struct device_node *of_new_node(struct device_node *parent, const char *name) { struct device_node *node; - if (!parent && root_node) - return NULL; - node = xzalloc(sizeof(*node)); node->parent = parent; if (parent) list_add_tail(&node->parent_list, &parent->children); - else - root_node = node; INIT_LIST_HEAD(&node->children); INIT_LIST_HEAD(&node->properties); @@ -869,9 +877,7 @@ void of_free(struct device_node *node) free(node); if (node == root_node) - root_node = NULL; - - of_alias_scan(); + of_set_root_node(NULL); } static void __of_probe(struct device_node *node) @@ -963,11 +969,15 @@ out: return dn; } -/* - * Parse a flat device tree binary blob and store it in the barebox - * internal tree format, +/** + * of_unflatten_dtb - unflatten a fdt blob + * @root - node in which the fdt blob should be merged into or NULL + * @fdt - the fdt blob to unflatten + * + * Parse a flat device tree binary blob and return a pointer to the + * unflattened tree. */ -int of_unflatten_dtb(struct fdt_header *fdt) +struct device_node *of_unflatten_dtb(struct device_node *root, struct fdt_header *fdt) { const void *nodep; /* property node pointer */ int nodeoffset; /* node offset from libfdt */ @@ -976,8 +986,9 @@ int of_unflatten_dtb(struct fdt_header *fdt) int len; /* length of the property */ const struct fdt_property *fdt_prop; const char *pathp; - struct device_node *node = NULL, *n, *root = NULL; + struct device_node *node = NULL, *n; struct property *p; + int ret; nodeoffset = fdt_path_offset(fdt, "/"); if (nodeoffset < 0) { @@ -986,12 +997,14 @@ int of_unflatten_dtb(struct fdt_header *fdt) */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); - return -EINVAL; + return ERR_PTR(-EINVAL); } - root = of_new_node(NULL, NULL); - if (!root) - return -ENOMEM; + if (!root) { + root = of_new_node(NULL, NULL); + if (!root) + return ERR_PTR(-ENOMEM); + } while (1) { tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); @@ -1035,16 +1048,18 @@ int of_unflatten_dtb(struct fdt_header *fdt) case FDT_NOP: break; case FDT_END: - of_alias_scan(); - return 0; + return root; default: printf("Unknown tag 0x%08X\n", tag); - return -EINVAL; + ret = -EINVAL; + goto err; } nodeoffset = nextoffset; } +err: + of_free(root); - return 0; + return ERR_PTR(ret); } static int __of_flatten_dtb(void *fdt, struct device_node *node) diff --git a/include/of.h b/include/of.h index c324c74..89ce64c 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); -int of_unflatten_dtb(struct fdt_header *fdt); +struct device_node *of_unflatten_dtb(struct device_node *root, struct fdt_header *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); @@ -136,6 +136,7 @@ int of_parse_partitions(const char *cdevname, struct device_node *node); struct device_node *of_get_root_node(void); +int of_set_root_node(struct device_node *); int of_alias_get_id(struct device_node *np, const char *stem); int of_device_is_stdout_path(struct device_d *dev); const char *of_get_model(void); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 12/29] of: make unflatten independent of libfdt 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (10 preceding siblings ...) 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 2013-02-26 20:18 ` [PATCH 13/29] of: make flatten " Sascha Hauer ` (16 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox 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 ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 13/29] of: make flatten independent of libfdt 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (11 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 12/29] of: make unflatten independent of libfdt Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 21:05 ` Alexander Aring 2013-02-26 20:18 ` [PATCH 14/29] of/fdt: use optimized endianess conversion Sascha Hauer ` (15 subsequent siblings) 28 siblings, 1 reply; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- common/oftree.c | 8 ++- drivers/of/base.c | 180 ++++++++++++++++++++++++++++++++++++++++++++--------- include/of.h | 4 +- 3 files changed, 160 insertions(+), 32 deletions(-) diff --git a/common/oftree.c b/common/oftree.c index 0df5209..841d2c4 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -329,7 +329,13 @@ struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt) int size, align; if (!fdt) { - fdt = internalfdt = of_flatten_dtb(); + struct device_node *root_node; + + root_node = of_get_root_node(); + if (!root_node) + return NULL; + + fdt = internalfdt = of_flatten_dtb(root_node); if (!fdt) return NULL; } diff --git a/drivers/of/base.c b/drivers/of/base.c index d6ca949..cd463e9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1154,20 +1154,108 @@ err: return ERR_PTR(ret); } -static int __of_flatten_dtb(void *fdt, struct device_node *node) +struct fdt { + void *dt; + uint32_t dt_nextofs; + uint32_t dt_size; + char *strings; + uint32_t str_nextofs; + uint32_t str_size; +}; + +static inline uint32_t dt_next_ofs(uint32_t curofs, uint32_t len) +{ + return ALIGN(curofs + len, 4); +} + +static int lstrcpy(char *dest, const char *src) +{ + int len = 0; + int maxlen = 1023; + + while (*src) { + *dest++ = *src++; + len++; + if (!maxlen) + return -ENOSPC; + maxlen--; + } + + return len; +} + +static int fdt_ensure_space(struct fdt *fdt, int dtsize) +{ + /* + * We assume strings and names have a maximum length of 1024 + * whereas properties can be longer. We allocate new memory + * if we have less than 1024 bytes (+ the property size left. + */ + if (fdt->str_size - fdt->str_nextofs < 1024) { + fdt->strings = realloc(fdt->strings, fdt->str_size * 2); + if (!fdt->strings) + return -ENOMEM; + fdt->str_size *= 2; + } + + if (fdt->dt_size - fdt->dt_nextofs < 1024 + dtsize) { + fdt->dt = realloc(fdt->dt, fdt->dt_size * 2); + if (!fdt->dt) + return -ENOMEM; + fdt->dt_size *= 2; + } + + return 0; +} + +static inline int dt_add_string(struct fdt *fdt, const char *str) +{ + uint32_t ret; + int len; + + if (fdt_ensure_space(fdt, 0) < 0) + return -ENOMEM; + + len = lstrcpy(fdt->strings + fdt->str_nextofs, str); + if (len < 0) + return -ENOSPC; + + ret = fdt->str_nextofs; + + fdt->str_nextofs += len + 1; + + return ret; +} + +static int __of_flatten_dtb(struct fdt *fdt, struct device_node *node) { struct property *p; struct device_node *n; int ret; + unsigned int len; + struct fdt_node_header *nh = fdt->dt + fdt->dt_nextofs; - ret = fdt_begin_node(fdt, node->name); - if (ret) - return ret; + if (fdt_ensure_space(fdt, 0) < 0) + return -ENOMEM; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + len = lstrcpy(nh->name, node->name); + fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, 4 + len + 1); list_for_each_entry(p, &node->properties, list) { - ret = fdt_property(fdt, p->name, p->value, p->length); - if (ret) - return ret; + struct fdt_property *fp; + + if (fdt_ensure_space(fdt, p->length) < 0) + return -ENOMEM; + + fp = fdt->dt + fdt->dt_nextofs; + + fp->tag = cpu_to_fdt32(FDT_PROP); + fp->len = cpu_to_fdt32(p->length); + fp->nameoff = cpu_to_fdt32(dt_add_string(fdt, p->name)); + memcpy(fp->data, p->value, p->length); + fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, + sizeof(struct fdt_property) + p->length); } list_for_each_entry(n, &node->children, parent_list) { @@ -1176,45 +1264,79 @@ static int __of_flatten_dtb(void *fdt, struct device_node *node) return ret; } - ret = fdt_end_node(fdt); + nh = fdt->dt + fdt->dt_nextofs; + nh->tag = cpu_to_fdt32(FDT_END_NODE); + fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, + sizeof(struct fdt_node_header)); - return ret; -} + if (fdt_ensure_space(fdt, 0) < 0) + return -ENOMEM; -#define DTB_SIZE SZ_128K + return 0; +} -void *of_flatten_dtb(void) +/** + * of_flatten_dtb - flatten a barebox internal devicetree to a dtb + * @node - the root node of the tree to be unflattened + */ +void *of_flatten_dtb(struct device_node *node) { - void *fdt; int ret; + struct fdt_header header = {}; + struct fdt fdt = {}; + uint32_t ofs; + struct fdt_node_header *nh; - if (!root_node) - return NULL; + header.magic = cpu_to_fdt32(FDT_MAGIC); + header.version = cpu_to_fdt32(0x11); + header.last_comp_version = cpu_to_fdt32(0x10); - fdt = malloc(DTB_SIZE); - if (!fdt) - return NULL; + fdt.dt = xzalloc(SZ_64K); + fdt.dt_size = SZ_64K; - memset(fdt, 0, DTB_SIZE); + fdt.strings = xzalloc(SZ_64K); + fdt.str_size = SZ_64K; - ret = fdt_create(fdt, DTB_SIZE); - if (ret) - goto out_free; + ofs = sizeof(struct fdt_header); - ret = fdt_finish_reservemap(fdt); - if (ret) - goto out_free; + header.off_mem_rsvmap = cpu_to_fdt32(ofs); + ofs += sizeof(struct fdt_reserve_entry); + + fdt.dt_nextofs = ofs; - ret = __of_flatten_dtb(fdt, root_node); + ret = __of_flatten_dtb(&fdt, node); if (ret) goto out_free; + nh = fdt.dt + fdt.dt_nextofs; + nh->tag = cpu_to_fdt32(FDT_END); + fdt.dt_nextofs = dt_next_ofs(fdt.dt_nextofs, sizeof(struct fdt_node_header)); + + header.size_dt_strings = cpu_to_fdt32(fdt.str_nextofs); + header.size_dt_struct = cpu_to_fdt32(fdt.dt_nextofs); + + header.off_dt_struct = cpu_to_fdt32(ofs); + + header.off_dt_strings = cpu_to_fdt32(fdt.dt_nextofs); + + if (fdt.dt_size - fdt.dt_nextofs < fdt.str_nextofs) { + fdt.dt = realloc(fdt.dt, fdt.dt_nextofs + fdt.str_nextofs); + if (!fdt.dt) + goto out_free; + } + + memcpy(fdt.dt + fdt.dt_nextofs, fdt.strings, fdt.str_nextofs); + + header.totalsize = cpu_to_fdt32(fdt.dt_nextofs + fdt.str_nextofs); + + memcpy(fdt.dt, &header, sizeof(header)); - fdt_finish(fdt); + free(fdt.strings); - return fdt; + return fdt.dt; out_free: - free(fdt); + free(fdt.strings); + free(fdt.dt); return NULL; } diff --git a/include/of.h b/include/of.h index f2fd84b..e7d74d8 100644 --- a/include/of.h +++ b/include/of.h @@ -140,7 +140,7 @@ int of_set_root_node(struct device_node *); int of_alias_get_id(struct device_node *np, const char *stem); int of_device_is_stdout_path(struct device_d *dev); const char *of_get_model(void); -void *of_flatten_dtb(void); +void *of_flatten_dtb(struct device_node *node); #else static inline int of_parse_partitions(const char *cdevname, struct device_node *node) @@ -168,7 +168,7 @@ static inline const char *of_get_model(void) return NULL; } -static inline void *of_flatten_dtb(void) +static inline void *of_flatten_dtb(struct device_node *node) { return NULL; } -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 13/29] of: make flatten independent of libfdt 2013-02-26 20:18 ` [PATCH 13/29] of: make flatten " Sascha Hauer @ 2013-02-26 21:05 ` Alexander Aring 2013-02-27 8:40 ` Sascha Hauer 0 siblings, 1 reply; 33+ messages in thread From: Alexander Aring @ 2013-02-26 21:05 UTC (permalink / raw) To: Sascha Hauer; +Cc: barebox Hi Sascha, On Tue, Feb 26, 2013 at 09:18:40PM +0100, Sascha Hauer wrote: > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > common/oftree.c | 8 ++- > drivers/of/base.c | 180 ++++++++++++++++++++++++++++++++++++++++++++--------- > include/of.h | 4 +- > 3 files changed, 160 insertions(+), 32 deletions(-) > > diff --git a/common/oftree.c b/common/oftree.c > index 0df5209..841d2c4 100644 > --- a/common/oftree.c > +++ b/common/oftree.c > @@ -329,7 +329,13 @@ struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt) > int size, align; > > if (!fdt) { > - fdt = internalfdt = of_flatten_dtb(); > + struct device_node *root_node; > + > + root_node = of_get_root_node(); > + if (!root_node) > + return NULL; > + > + fdt = internalfdt = of_flatten_dtb(root_node); > if (!fdt) > return NULL; > } > diff --git a/drivers/of/base.c b/drivers/of/base.c > index d6ca949..cd463e9 100644 > --- a/drivers/of/base.c > +++ b/drivers/of/base.c > @@ -1154,20 +1154,108 @@ err: > return ERR_PTR(ret); > } > > -static int __of_flatten_dtb(void *fdt, struct device_node *node) > +struct fdt { > + void *dt; > + uint32_t dt_nextofs; > + uint32_t dt_size; > + char *strings; > + uint32_t str_nextofs; > + uint32_t str_size; > +}; > + > +static inline uint32_t dt_next_ofs(uint32_t curofs, uint32_t len) > +{ > + return ALIGN(curofs + len, 4); > +} > + > +static int lstrcpy(char *dest, const char *src) > +{ > + int len = 0; > + int maxlen = 1023; > + > + while (*src) { > + *dest++ = *src++; > + len++; > + if (!maxlen) > + return -ENOSPC; > + maxlen--; > + } > + > + return len; > +} > + > +static int fdt_ensure_space(struct fdt *fdt, int dtsize) > +{ > + /* > + * We assume strings and names have a maximum length of 1024 > + * whereas properties can be longer. We allocate new memory > + * if we have less than 1024 bytes (+ the property size left. > + */ > + if (fdt->str_size - fdt->str_nextofs < 1024) { > + fdt->strings = realloc(fdt->strings, fdt->str_size * 2); > + if (!fdt->strings) > + return -ENOMEM; > + fdt->str_size *= 2; > + } > + > + if (fdt->dt_size - fdt->dt_nextofs < 1024 + dtsize) { > + fdt->dt = realloc(fdt->dt, fdt->dt_size * 2); > + if (!fdt->dt) > + return -ENOMEM; Leaking memory here. We need to clean fdt->strings. Regards Alex _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 13/29] of: make flatten independent of libfdt 2013-02-26 21:05 ` Alexander Aring @ 2013-02-27 8:40 ` Sascha Hauer 2013-02-27 19:52 ` Alexander Aring 0 siblings, 1 reply; 33+ messages in thread From: Sascha Hauer @ 2013-02-27 8:40 UTC (permalink / raw) To: Alexander Aring; +Cc: barebox On Tue, Feb 26, 2013 at 10:05:20PM +0100, Alexander Aring wrote: > Hi Sascha, > > On Tue, Feb 26, 2013 at 09:18:40PM +0100, Sascha Hauer wrote: > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > --- > > common/oftree.c | 8 ++- > > drivers/of/base.c | 180 ++++++++++++++++++++++++++++++++++++++++++++--------- > > include/of.h | 4 +- > > 3 files changed, 160 insertions(+), 32 deletions(-) > > > > diff --git a/common/oftree.c b/common/oftree.c > > index 0df5209..841d2c4 100644 > > --- a/common/oftree.c > > +++ b/common/oftree.c > > @@ -329,7 +329,13 @@ struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt) > > int size, align; > > > > if (!fdt) { > > - fdt = internalfdt = of_flatten_dtb(); > > + struct device_node *root_node; > > + > > + root_node = of_get_root_node(); > > + if (!root_node) > > + return NULL; > > + > > + fdt = internalfdt = of_flatten_dtb(root_node); > > if (!fdt) > > return NULL; > > } > > diff --git a/drivers/of/base.c b/drivers/of/base.c > > index d6ca949..cd463e9 100644 > > --- a/drivers/of/base.c > > +++ b/drivers/of/base.c > > @@ -1154,20 +1154,108 @@ err: > > return ERR_PTR(ret); > > } > > > > -static int __of_flatten_dtb(void *fdt, struct device_node *node) > > +struct fdt { > > + void *dt; > > + uint32_t dt_nextofs; > > + uint32_t dt_size; > > + char *strings; > > + uint32_t str_nextofs; > > + uint32_t str_size; > > +}; > > + > > +static inline uint32_t dt_next_ofs(uint32_t curofs, uint32_t len) > > +{ > > + return ALIGN(curofs + len, 4); > > +} > > + > > +static int lstrcpy(char *dest, const char *src) > > +{ > > + int len = 0; > > + int maxlen = 1023; > > + > > + while (*src) { > > + *dest++ = *src++; > > + len++; > > + if (!maxlen) > > + return -ENOSPC; > > + maxlen--; > > + } > > + > > + return len; > > +} > > + > > +static int fdt_ensure_space(struct fdt *fdt, int dtsize) > > +{ > > + /* > > + * We assume strings and names have a maximum length of 1024 > > + * whereas properties can be longer. We allocate new memory > > + * if we have less than 1024 bytes (+ the property size left. > > + */ > > + if (fdt->str_size - fdt->str_nextofs < 1024) { > > + fdt->strings = realloc(fdt->strings, fdt->str_size * 2); > > + if (!fdt->strings) > > + return -ENOMEM; > > + fdt->str_size *= 2; > > + } > > + > > + if (fdt->dt_size - fdt->dt_nextofs < 1024 + dtsize) { > > + fdt->dt = realloc(fdt->dt, fdt->dt_size * 2); > > + if (!fdt->dt) > > + return -ENOMEM; > > Leaking memory here. We need to clean fdt->strings. Nope. When fdt_ensure_space fails we will free both fdt->strings and fdt->dt in the out_free: path in of_flatten_dtb(). Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 13/29] of: make flatten independent of libfdt 2013-02-27 8:40 ` Sascha Hauer @ 2013-02-27 19:52 ` Alexander Aring 0 siblings, 0 replies; 33+ messages in thread From: Alexander Aring @ 2013-02-27 19:52 UTC (permalink / raw) To: Sascha Hauer; +Cc: barebox Hi Sascha, On Wed, Feb 27, 2013 at 09:40:16AM +0100, Sascha Hauer wrote: > On Tue, Feb 26, 2013 at 10:05:20PM +0100, Alexander Aring wrote: > > Hi Sascha, > > > > On Tue, Feb 26, 2013 at 09:18:40PM +0100, Sascha Hauer wrote: > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > > --- > > > common/oftree.c | 8 ++- > > > drivers/of/base.c | 180 ++++++++++++++++++++++++++++++++++++++++++++--------- > > > include/of.h | 4 +- > > > 3 files changed, 160 insertions(+), 32 deletions(-) > > > > > > diff --git a/common/oftree.c b/common/oftree.c > > > index 0df5209..841d2c4 100644 > > > --- a/common/oftree.c > > > +++ b/common/oftree.c > > > @@ -329,7 +329,13 @@ struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt) > > > int size, align; > > > > > > if (!fdt) { > > > - fdt = internalfdt = of_flatten_dtb(); > > > + struct device_node *root_node; > > > + > > > + root_node = of_get_root_node(); > > > + if (!root_node) > > > + return NULL; > > > + > > > + fdt = internalfdt = of_flatten_dtb(root_node); > > > if (!fdt) > > > return NULL; > > > } > > > diff --git a/drivers/of/base.c b/drivers/of/base.c > > > index d6ca949..cd463e9 100644 > > > --- a/drivers/of/base.c > > > +++ b/drivers/of/base.c > > > @@ -1154,20 +1154,108 @@ err: > > > return ERR_PTR(ret); > > > } > > > > > > -static int __of_flatten_dtb(void *fdt, struct device_node *node) > > > +struct fdt { > > > + void *dt; > > > + uint32_t dt_nextofs; > > > + uint32_t dt_size; > > > + char *strings; > > > + uint32_t str_nextofs; > > > + uint32_t str_size; > > > +}; > > > + > > > +static inline uint32_t dt_next_ofs(uint32_t curofs, uint32_t len) > > > +{ > > > + return ALIGN(curofs + len, 4); > > > +} > > > + > > > +static int lstrcpy(char *dest, const char *src) > > > +{ > > > + int len = 0; > > > + int maxlen = 1023; > > > + > > > + while (*src) { > > > + *dest++ = *src++; > > > + len++; > > > + if (!maxlen) > > > + return -ENOSPC; > > > + maxlen--; > > > + } > > > + > > > + return len; > > > +} > > > + > > > +static int fdt_ensure_space(struct fdt *fdt, int dtsize) > > > +{ > > > + /* > > > + * We assume strings and names have a maximum length of 1024 > > > + * whereas properties can be longer. We allocate new memory > > > + * if we have less than 1024 bytes (+ the property size left. > > > + */ > > > + if (fdt->str_size - fdt->str_nextofs < 1024) { > > > + fdt->strings = realloc(fdt->strings, fdt->str_size * 2); > > > + if (!fdt->strings) > > > + return -ENOMEM; > > > + fdt->str_size *= 2; > > > + } > > > + > > > + if (fdt->dt_size - fdt->dt_nextofs < 1024 + dtsize) { > > > + fdt->dt = realloc(fdt->dt, fdt->dt_size * 2); > > > + if (!fdt->dt) > > > + return -ENOMEM; > > > > Leaking memory here. We need to clean fdt->strings. > > Nope. When fdt_ensure_space fails we will free both fdt->strings and > fdt->dt in the out_free: path in of_flatten_dtb(). > oh, yes you are right. Sorry about that. Regards Alex _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 14/29] of/fdt: use optimized endianess conversion 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (12 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 13/29] of: make flatten " Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 15/29] oftree command: Use of_print_nodes Sascha Hauer ` (14 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- include/libfdt_env.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/libfdt_env.h b/include/libfdt_env.h index e83aa96..6486187 100644 --- a/include/libfdt_env.h +++ b/include/libfdt_env.h @@ -3,13 +3,12 @@ #include <linux/types.h> #include <string.h> +#include <asm/byteorder.h> #define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) -static inline uint32_t fdt32_to_cpu(uint32_t x) -{ - return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); -} -#define cpu_to_fdt32(x) fdt32_to_cpu(x) + +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) static inline uint64_t fdt64_to_cpu(uint64_t x) { -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 15/29] oftree command: Use of_print_nodes 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (13 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 14/29] of/fdt: use optimized endianess conversion Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 16/29] of: move OFTREE Kconfig option to drivers/of/ Sascha Hauer ` (13 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/oftree.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/commands/oftree.c b/commands/oftree.c index 83ffe12..612d01a 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -156,7 +156,14 @@ static int do_oftree(int argc, char *argv[]) if (dump) { if (fdt) { - ret = fdt_print(fdt, node); + root = of_unflatten_dtb(NULL, fdt); + if (IS_ERR(root)) { + printf("parse oftree: %s\n", strerror(-PTR_ERR(root))); + ret = 1; + goto out; + } + of_print_nodes(root, 0); + of_free(root); } else { struct device_node *root, *n; @@ -174,10 +181,10 @@ static int do_oftree(int argc, char *argv[]) } of_print_nodes(n, 0); - - ret = 0; } + ret = 0; + goto out; } -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 16/29] of: move OFTREE Kconfig option to drivers/of/ 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (14 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 15/29] oftree command: Use of_print_nodes Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 17/29] of: make OFDEVICE a user selectable option Sascha Hauer ` (12 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/Kconfig | 4 ++++ lib/Kconfig | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 95f10d0..5e53d25 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -1,2 +1,6 @@ +config OFTREE + select FDT + bool + config OFDEVICE bool diff --git a/lib/Kconfig b/lib/Kconfig index 4578353..d58109b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -25,10 +25,6 @@ source lib/lzo/Kconfig config FDT bool -config OFTREE - select FDT - bool - config BCH bool -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 17/29] of: make OFDEVICE a user selectable option 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (15 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 16/29] of: move OFTREE Kconfig option to drivers/of/ Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 18/29] oftree command: retire CMD_OFTREE_PROBE Kconfig option Sascha Hauer ` (11 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox OFDEVICE decides whether or not we compile in support for probing devices from the devicetree. Let the user decide this explicitly. This makes the oftree, of_node and of_property commands independent of devicetree device support since being able to manipulate devicetrees has nothing to do with probing devices from the devicetree. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/Kconfig | 3 --- drivers/Makefile | 2 +- drivers/of/Kconfig | 3 ++- include/of.h | 12 ++++-------- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/commands/Kconfig b/commands/Kconfig index c1454c7..c8f06d8 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -481,7 +481,6 @@ config CMD_GO config CMD_OFTREE tristate select OFTREE - select OFDEVICE prompt "oftree" help The oftree command has support for dumping devicetrees and, if @@ -497,7 +496,6 @@ config CMD_OFTREE_PROBE config CMD_OF_PROPERTY tristate select OFTREE - select OFDEVICE prompt "of_property" help The of_property command allows setting and deleting of properties in @@ -506,7 +504,6 @@ config CMD_OF_PROPERTY config CMD_OF_NODE tristate select OFTREE - select OFDEVICE prompt "of_node" help The of_property command allows adding and removing devicetree nodes. diff --git a/drivers/Makefile b/drivers/Makefile index 1fddee0..0aaae1a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -21,5 +21,5 @@ obj-y += misc/ obj-y += dma/ obj-y += watchdog/ obj-y += gpio/ -obj-$(CONFIG_OFDEVICE) += of/ +obj-$(CONFIG_OFTREE) += of/ obj-$(CONFIG_W1) += w1/ diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 5e53d25..c30b1c1 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -3,4 +3,5 @@ config OFTREE bool config OFDEVICE - bool + select OFTREE + bool "Enable probing of devices from the devicetree" diff --git a/include/of.h b/include/of.h index e7d74d8..2ddbe8d 100644 --- a/include/of.h +++ b/include/of.h @@ -131,12 +131,13 @@ int of_set_property(struct device_node *node, const char *p, const void *val, in int create); struct device_node *of_create_node(struct device_node *root, const char *path); -#ifdef CONFIG_OFDEVICE +struct device_node *of_get_root_node(void); +int of_set_root_node(struct device_node *); + +#ifdef CONFIG_OFTREE int of_parse_partitions(const char *cdevname, struct device_node *node); -struct device_node *of_get_root_node(void); -int of_set_root_node(struct device_node *); int of_alias_get_id(struct device_node *np, const char *stem); int of_device_is_stdout_path(struct device_d *dev); const char *of_get_model(void); @@ -148,11 +149,6 @@ static inline int of_parse_partitions(const char *cdevname, return -EINVAL; } -static inline struct device_node *of_get_root_node(void) -{ - return NULL; -} - static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOENT; -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 18/29] oftree command: retire CMD_OFTREE_PROBE Kconfig option 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (16 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 17/29] of: make OFDEVICE a user selectable option Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 19/29] of: move oftree Kconfig to the top of the drivers menu Sascha Hauer ` (10 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Whether or not the user wishes devicetree probe support can now be decided indepentently of the oftree command, so retire the CMD_OFTREE_PROBE option and use OFDEVICE in the code instead. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/Kconfig | 7 ------- commands/oftree.c | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/commands/Kconfig b/commands/Kconfig index c8f06d8..0062758 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -486,13 +486,6 @@ config CMD_OFTREE The oftree command has support for dumping devicetrees and, if enabled, to probe devices from the devicetree -config CMD_OFTREE_PROBE - bool - depends on CMD_OFTREE - prompt "oftree probe support" - help - This enables the -p option to probe devices from the devicetree - config CMD_OF_PROPERTY tristate select OFTREE diff --git a/commands/oftree.c b/commands/oftree.c index 612d01a..e4f52b8 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -64,7 +64,7 @@ static int do_oftree(int argc, char *argv[]) dump = 1; break; case 'p': - if (IS_ENABLED(CONFIG_CMD_OFTREE_PROBE)) { + if (IS_ENABLED(CONFIG_OFDEVICE)) { probe = 1; } else { printf("oftree device probe support disabled\n"); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 19/29] of: move oftree Kconfig to the top of the drivers menu 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (17 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 18/29] oftree command: retire CMD_OFTREE_PROBE Kconfig option Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 20/29] of: Pass barebox internal format devicetree to of_get_fixed_tree Sascha Hauer ` (9 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Using OFDEVICE is a basic decision, so move it to the top of the driver menu. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Kconfig b/drivers/Kconfig index 988ec9e..70321ea 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -1,5 +1,6 @@ menu "Drivers" +source "drivers/of/Kconfig" source "drivers/serial/Kconfig" source "drivers/net/Kconfig" source "drivers/spi/Kconfig" @@ -21,7 +22,6 @@ source "drivers/watchdog/Kconfig" source "drivers/pwm/Kconfig" source "drivers/dma/Kconfig" source "drivers/gpio/Kconfig" -source "drivers/of/Kconfig" source "drivers/w1/Kconfig" endmenu -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 20/29] of: Pass barebox internal format devicetree to of_get_fixed_tree 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (18 preceding siblings ...) 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 21/29] bootm: Use of_print_nodes instead of fdt_print Sascha Hauer ` (8 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox With this every devicetree is first converted to the barebox internal format before it's converted back to dtb again. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/lib/bootm.c | 10 +++++++++- commands/bootm.c | 9 ++++++++- common/oftree.c | 19 +++++++++---------- include/of.h | 3 ++- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index cf192cf..234f3e0 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -181,7 +181,15 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data) } if (IS_BUILTIN(CONFIG_OFTREE)) { - data->oftree = of_get_fixed_tree(oftree); + struct device_node *node; + + node = of_unflatten_dtb(NULL, oftree); + if (!node) { + pr_err("unable to unflatten devicetree\n"); + return -EINVAL; + } + + data->oftree = of_get_fixed_tree(node); } pr_info("zImage: concatenated oftree detected\n"); diff --git a/commands/bootm.c b/commands/bootm.c index 4d3f022..38233e7 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -140,6 +140,7 @@ static int bootm_open_oftree(struct image_data *data, const char *oftree, int nu enum filetype ft; struct fdt_header *fdt, *fixfdt; size_t size; + struct device_node *node; printf("Loading devicetree from '%s'\n", oftree); @@ -187,7 +188,13 @@ static int bootm_open_oftree(struct image_data *data, const char *oftree, int nu file_type_to_string(ft)); } - fixfdt = of_get_fixed_tree(fdt); + node = of_unflatten_dtb(NULL, fdt); + if (!node) { + pr_err("unable to unflatten devicetree\n"); + return -EINVAL; + } + + fixfdt = of_get_fixed_tree(node); if (!fixfdt) return -EINVAL; diff --git a/common/oftree.c b/common/oftree.c index 841d2c4..b616b59 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -322,24 +322,23 @@ int of_fix_tree(struct fdt_header *fdt) * It increases the size of the tree and applies the registered * fixups. */ -struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt) +struct fdt_header *of_get_fixed_tree(struct device_node *node) { int ret; void *fixfdt, *internalfdt = NULL; int size, align; + struct fdt_header *fdt; - if (!fdt) { - struct device_node *root_node; - - root_node = of_get_root_node(); - if (!root_node) - return NULL; - - fdt = internalfdt = of_flatten_dtb(root_node); - if (!fdt) + if (!node) { + node = of_get_root_node(); + if (!node) return NULL; } + fdt = internalfdt = of_flatten_dtb(node); + if (!fdt) + return NULL; + size = fdt_totalsize(fdt); /* diff --git a/include/of.h b/include/of.h index 2ddbe8d..1db546c 100644 --- a/include/of.h +++ b/include/of.h @@ -7,7 +7,6 @@ int fdt_print(struct fdt_header *working_fdt, const char *pathp); -struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt); int of_fix_tree(struct fdt_header *fdt); int of_register_fixup(int (*fixup)(struct fdt_header *)); @@ -62,6 +61,8 @@ struct device_node *of_find_child_by_name(struct device_node *node, const char * struct fdt_header *fdt_get_tree(void); +struct fdt_header *of_get_fixed_tree(struct device_node *node); + #define device_node_for_nach_child(node, child) \ list_for_each_entry(child, &node->children, parent_list) -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 21/29] bootm: Use of_print_nodes instead of fdt_print 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (19 preceding siblings ...) 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 22/29] of: move flat devicetree functions to separate file Sascha Hauer ` (7 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Now that we use the unflattened tree in bootm we can use of_print_nodes instead of printing the flattened tree. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/bootm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 38233e7..65a75e2 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -194,15 +194,15 @@ static int bootm_open_oftree(struct image_data *data, const char *oftree, int nu return -EINVAL; } + if (bootm_verbose(data) > 1) + of_print_nodes(node, 0); + fixfdt = of_get_fixed_tree(node); if (!fixfdt) return -EINVAL; free(fdt); - if (bootm_verbose(data) > 1) - fdt_print(fixfdt, "/"); - data->oftree = fixfdt; return 0; -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 22/29] of: move flat devicetree functions to separate file 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (20 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 21/29] bootm: Use of_print_nodes instead of fdt_print Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 23/29] of: Add of property write functions for u32 Sascha Hauer ` (6 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/Makefile | 2 +- drivers/of/base.c | 372 ----------------------------------------------- drivers/of/dtb.c | 401 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 402 insertions(+), 373 deletions(-) create mode 100644 drivers/of/dtb.c diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 5a5960d..fc71962 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,3 +1,3 @@ -obj-y += base.o +obj-y += base.o dtb.o obj-$(CONFIG_GPIOLIB) += gpio.o obj-y += partition.o diff --git a/drivers/of/base.c b/drivers/of/base.c index cd463e9..8138a91 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -969,378 +969,6 @@ 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 dtb binary blob - * @root - node in which the fdt blob should be merged into or NULL - * @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, void *infdt) -{ - const void *nodep; /* property node pointer */ - uint32_t tag; /* tag */ - int len; /* length of the property */ - const struct fdt_property *fdt_prop; - const char *pathp, *name; - struct device_node *node = NULL, *n; - struct property *p; - 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); - } - - if (fdt->version != cpu_to_fdt32(17)) { - pr_err("bad dt version: 0x%08x\n", fdt32_to_cpu(fdt->version)); - return ERR_PTR(-EINVAL); - } - - 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 = be32_to_cpu(*(uint32_t *)(infdt + dt_struct)); - - switch (tag) { - case FDT_BEGIN_NODE: - 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; - } - - 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 (merge && (n = of_find_child_by_name(node, pathp))) - node = n; - 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 = 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, 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: - pr_err("unflatten: Unknown tag 0x%08X\n", tag); - ret = -EINVAL; - goto err; - } - } -err: - of_free(root); - - return ERR_PTR(ret); -} - -struct fdt { - void *dt; - uint32_t dt_nextofs; - uint32_t dt_size; - char *strings; - uint32_t str_nextofs; - uint32_t str_size; -}; - -static inline uint32_t dt_next_ofs(uint32_t curofs, uint32_t len) -{ - return ALIGN(curofs + len, 4); -} - -static int lstrcpy(char *dest, const char *src) -{ - int len = 0; - int maxlen = 1023; - - while (*src) { - *dest++ = *src++; - len++; - if (!maxlen) - return -ENOSPC; - maxlen--; - } - - return len; -} - -static int fdt_ensure_space(struct fdt *fdt, int dtsize) -{ - /* - * We assume strings and names have a maximum length of 1024 - * whereas properties can be longer. We allocate new memory - * if we have less than 1024 bytes (+ the property size left. - */ - if (fdt->str_size - fdt->str_nextofs < 1024) { - fdt->strings = realloc(fdt->strings, fdt->str_size * 2); - if (!fdt->strings) - return -ENOMEM; - fdt->str_size *= 2; - } - - if (fdt->dt_size - fdt->dt_nextofs < 1024 + dtsize) { - fdt->dt = realloc(fdt->dt, fdt->dt_size * 2); - if (!fdt->dt) - return -ENOMEM; - fdt->dt_size *= 2; - } - - return 0; -} - -static inline int dt_add_string(struct fdt *fdt, const char *str) -{ - uint32_t ret; - int len; - - if (fdt_ensure_space(fdt, 0) < 0) - return -ENOMEM; - - len = lstrcpy(fdt->strings + fdt->str_nextofs, str); - if (len < 0) - return -ENOSPC; - - ret = fdt->str_nextofs; - - fdt->str_nextofs += len + 1; - - return ret; -} - -static int __of_flatten_dtb(struct fdt *fdt, struct device_node *node) -{ - struct property *p; - struct device_node *n; - int ret; - unsigned int len; - struct fdt_node_header *nh = fdt->dt + fdt->dt_nextofs; - - if (fdt_ensure_space(fdt, 0) < 0) - return -ENOMEM; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - len = lstrcpy(nh->name, node->name); - fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, 4 + len + 1); - - list_for_each_entry(p, &node->properties, list) { - struct fdt_property *fp; - - if (fdt_ensure_space(fdt, p->length) < 0) - return -ENOMEM; - - fp = fdt->dt + fdt->dt_nextofs; - - fp->tag = cpu_to_fdt32(FDT_PROP); - fp->len = cpu_to_fdt32(p->length); - fp->nameoff = cpu_to_fdt32(dt_add_string(fdt, p->name)); - memcpy(fp->data, p->value, p->length); - fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, - sizeof(struct fdt_property) + p->length); - } - - list_for_each_entry(n, &node->children, parent_list) { - ret = __of_flatten_dtb(fdt, n); - if (ret) - return ret; - } - - nh = fdt->dt + fdt->dt_nextofs; - nh->tag = cpu_to_fdt32(FDT_END_NODE); - fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, - sizeof(struct fdt_node_header)); - - if (fdt_ensure_space(fdt, 0) < 0) - return -ENOMEM; - - return 0; -} - -/** - * of_flatten_dtb - flatten a barebox internal devicetree to a dtb - * @node - the root node of the tree to be unflattened - */ -void *of_flatten_dtb(struct device_node *node) -{ - int ret; - struct fdt_header header = {}; - struct fdt fdt = {}; - uint32_t ofs; - struct fdt_node_header *nh; - - header.magic = cpu_to_fdt32(FDT_MAGIC); - header.version = cpu_to_fdt32(0x11); - header.last_comp_version = cpu_to_fdt32(0x10); - - fdt.dt = xzalloc(SZ_64K); - fdt.dt_size = SZ_64K; - - fdt.strings = xzalloc(SZ_64K); - fdt.str_size = SZ_64K; - - ofs = sizeof(struct fdt_header); - - header.off_mem_rsvmap = cpu_to_fdt32(ofs); - ofs += sizeof(struct fdt_reserve_entry); - - fdt.dt_nextofs = ofs; - - ret = __of_flatten_dtb(&fdt, node); - if (ret) - goto out_free; - nh = fdt.dt + fdt.dt_nextofs; - nh->tag = cpu_to_fdt32(FDT_END); - fdt.dt_nextofs = dt_next_ofs(fdt.dt_nextofs, sizeof(struct fdt_node_header)); - - header.size_dt_strings = cpu_to_fdt32(fdt.str_nextofs); - header.size_dt_struct = cpu_to_fdt32(fdt.dt_nextofs); - - header.off_dt_struct = cpu_to_fdt32(ofs); - - header.off_dt_strings = cpu_to_fdt32(fdt.dt_nextofs); - - if (fdt.dt_size - fdt.dt_nextofs < fdt.str_nextofs) { - fdt.dt = realloc(fdt.dt, fdt.dt_nextofs + fdt.str_nextofs); - if (!fdt.dt) - goto out_free; - } - - memcpy(fdt.dt + fdt.dt_nextofs, fdt.strings, fdt.str_nextofs); - - header.totalsize = cpu_to_fdt32(fdt.dt_nextofs + fdt.str_nextofs); - - memcpy(fdt.dt, &header, sizeof(header)); - - free(fdt.strings); - - return fdt.dt; - -out_free: - free(fdt.strings); - free(fdt.dt); - - return NULL; -} - int of_device_is_stdout_path(struct device_d *dev) { struct device_node *dn; diff --git a/drivers/of/dtb.c b/drivers/of/dtb.c new file mode 100644 index 0000000..671ea63 --- /dev/null +++ b/drivers/of/dtb.c @@ -0,0 +1,401 @@ +/* + * dtb.c - flat devicetree functions + * + * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * based on Linux devicetree support + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <common.h> +#include <of.h> +#include <errno.h> +#include <libfdt.h> +#include <malloc.h> +#include <init.h> +#include <memory.h> +#include <sizes.h> +#include <linux/ctype.h> +#include <linux/err.h> + +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 dtb binary blob + * @root - node in which the fdt blob should be merged into or NULL + * @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, void *infdt) +{ + const void *nodep; /* property node pointer */ + uint32_t tag; /* tag */ + int len; /* length of the property */ + const struct fdt_property *fdt_prop; + const char *pathp, *name; + struct device_node *node = NULL, *n; + struct property *p; + 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); + } + + if (fdt->version != cpu_to_fdt32(17)) { + pr_err("bad dt version: 0x%08x\n", fdt32_to_cpu(fdt->version)); + return ERR_PTR(-EINVAL); + } + + 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 = be32_to_cpu(*(uint32_t *)(infdt + dt_struct)); + + switch (tag) { + case FDT_BEGIN_NODE: + 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; + } + + 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 (merge && (n = of_find_child_by_name(node, pathp))) + node = n; + 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 = 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, 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: + pr_err("unflatten: Unknown tag 0x%08X\n", tag); + ret = -EINVAL; + goto err; + } + } +err: + of_free(root); + + return ERR_PTR(ret); +} + +struct fdt { + void *dt; + uint32_t dt_nextofs; + uint32_t dt_size; + char *strings; + uint32_t str_nextofs; + uint32_t str_size; +}; + +static inline uint32_t dt_next_ofs(uint32_t curofs, uint32_t len) +{ + return ALIGN(curofs + len, 4); +} + +static int lstrcpy(char *dest, const char *src) +{ + int len = 0; + int maxlen = 1023; + + while (*src) { + *dest++ = *src++; + len++; + if (!maxlen) + return -ENOSPC; + maxlen--; + } + + return len; +} + +static int fdt_ensure_space(struct fdt *fdt, int dtsize) +{ + /* + * We assume strings and names have a maximum length of 1024 + * whereas properties can be longer. We allocate new memory + * if we have less than 1024 bytes (+ the property size left. + */ + if (fdt->str_size - fdt->str_nextofs < 1024) { + fdt->strings = realloc(fdt->strings, fdt->str_size * 2); + if (!fdt->strings) + return -ENOMEM; + fdt->str_size *= 2; + } + + if (fdt->dt_size - fdt->dt_nextofs < 1024 + dtsize) { + fdt->dt = realloc(fdt->dt, fdt->dt_size * 2); + if (!fdt->dt) + return -ENOMEM; + fdt->dt_size *= 2; + } + + return 0; +} + +static inline int dt_add_string(struct fdt *fdt, const char *str) +{ + uint32_t ret; + int len; + + if (fdt_ensure_space(fdt, 0) < 0) + return -ENOMEM; + + len = lstrcpy(fdt->strings + fdt->str_nextofs, str); + if (len < 0) + return -ENOSPC; + + ret = fdt->str_nextofs; + + fdt->str_nextofs += len + 1; + + return ret; +} + +static int __of_flatten_dtb(struct fdt *fdt, struct device_node *node) +{ + struct property *p; + struct device_node *n; + int ret; + unsigned int len; + struct fdt_node_header *nh = fdt->dt + fdt->dt_nextofs; + + if (fdt_ensure_space(fdt, 0) < 0) + return -ENOMEM; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + len = lstrcpy(nh->name, node->name); + fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, 4 + len + 1); + + list_for_each_entry(p, &node->properties, list) { + struct fdt_property *fp; + + if (fdt_ensure_space(fdt, p->length) < 0) + return -ENOMEM; + + fp = fdt->dt + fdt->dt_nextofs; + + fp->tag = cpu_to_fdt32(FDT_PROP); + fp->len = cpu_to_fdt32(p->length); + fp->nameoff = cpu_to_fdt32(dt_add_string(fdt, p->name)); + memcpy(fp->data, p->value, p->length); + fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, + sizeof(struct fdt_property) + p->length); + } + + list_for_each_entry(n, &node->children, parent_list) { + ret = __of_flatten_dtb(fdt, n); + if (ret) + return ret; + } + + nh = fdt->dt + fdt->dt_nextofs; + nh->tag = cpu_to_fdt32(FDT_END_NODE); + fdt->dt_nextofs = dt_next_ofs(fdt->dt_nextofs, + sizeof(struct fdt_node_header)); + + if (fdt_ensure_space(fdt, 0) < 0) + return -ENOMEM; + + return 0; +} + +/** + * of_flatten_dtb - flatten a barebox internal devicetree to a dtb + * @node - the root node of the tree to be unflattened + */ +void *of_flatten_dtb(struct device_node *node) +{ + int ret; + struct fdt_header header = {}; + struct fdt fdt = {}; + uint32_t ofs; + struct fdt_node_header *nh; + + header.magic = cpu_to_fdt32(FDT_MAGIC); + header.version = cpu_to_fdt32(0x11); + header.last_comp_version = cpu_to_fdt32(0x10); + + fdt.dt = xzalloc(SZ_64K); + fdt.dt_size = SZ_64K; + + fdt.strings = xzalloc(SZ_64K); + fdt.str_size = SZ_64K; + + ofs = sizeof(struct fdt_header); + + header.off_mem_rsvmap = cpu_to_fdt32(ofs); + ofs += sizeof(struct fdt_reserve_entry); + + fdt.dt_nextofs = ofs; + + ret = __of_flatten_dtb(&fdt, node); + if (ret) + goto out_free; + nh = fdt.dt + fdt.dt_nextofs; + nh->tag = cpu_to_fdt32(FDT_END); + fdt.dt_nextofs = dt_next_ofs(fdt.dt_nextofs, sizeof(struct fdt_node_header)); + + header.size_dt_strings = cpu_to_fdt32(fdt.str_nextofs); + header.size_dt_struct = cpu_to_fdt32(fdt.dt_nextofs); + + header.off_dt_struct = cpu_to_fdt32(ofs); + + header.off_dt_strings = cpu_to_fdt32(fdt.dt_nextofs); + + if (fdt.dt_size - fdt.dt_nextofs < fdt.str_nextofs) { + fdt.dt = realloc(fdt.dt, fdt.dt_nextofs + fdt.str_nextofs); + if (!fdt.dt) + goto out_free; + } + + memcpy(fdt.dt + fdt.dt_nextofs, fdt.strings, fdt.str_nextofs); + + header.totalsize = cpu_to_fdt32(fdt.dt_nextofs + fdt.str_nextofs); + + memcpy(fdt.dt, &header, sizeof(header)); + + free(fdt.strings); + + return fdt.dt; + +out_free: + free(fdt.strings); + free(fdt.dt); + + return NULL; +} -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 23/29] of: Add of property write functions for u32 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (21 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 22/29] of: move flat devicetree functions to separate file Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 24/29] of: make value of property in of_new_property optional Sascha Hauer ` (5 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 25 +++++++++++++++++++++++++ include/of.h | 11 +++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 8138a91..6b12979 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -349,6 +349,31 @@ int of_property_read_u32_array(const struct device_node *np, } EXPORT_SYMBOL_GPL(of_property_read_u32_array); +int of_property_write_u32_array(struct device_node *np, + const char *propname, const u32 *values, + size_t sz) +{ + struct property *prop = of_find_property(np, propname); + __be32 *val; + + if (!prop) + prop = of_new_property(np, propname, NULL, 0); + if (!prop) + return -ENOMEM; + + free(prop->value); + + prop->value = malloc(sizeof(__be32) * sz); + if (!prop->value) + return -ENOMEM; + + val = prop->value; + + while (sz--) + *val++ = cpu_to_be32(*values++); + return 0; +} + /** * of_parse_phandles_with_args - Find a node pointed by phandle in a list * @np: pointer to a device tree node containing a list diff --git a/include/of.h b/include/of.h index 1db546c..b2f9ca7 100644 --- a/include/of.h +++ b/include/of.h @@ -94,6 +94,17 @@ static inline int of_property_read_u32(const struct device_node *np, return of_property_read_u32_array(np, propname, out_value, 1); } +int of_property_write_u32_array(struct device_node *np, + const char *propname, const u32 *values, + size_t sz); + +static inline int of_property_write_u32(struct device_node *np, + const char *propname, + u32 value) +{ + return of_property_write_u32_array(np, propname, &value, 1); +} + const void *of_get_property(const struct device_node *np, const char *name, int *lenp); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 24/29] of: make value of property in of_new_property optional 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (22 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 23/29] of: Add of property write functions for u32 Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 25/29] of: Add missing prototype for size/address counting functions Sascha Hauer ` (4 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/of/base.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 6b12979..c47801a 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -676,8 +676,10 @@ struct property *of_new_property(struct device_node *node, const char *name, prop->name = strdup(name); prop->length = len; - prop->value = xzalloc(len); - memcpy(prop->value, data, len); + if (len) { + prop->value = xzalloc(len); + memcpy(prop->value, data, len); + } list_add_tail(&prop->list, &node->properties); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 25/29] of: Add missing prototype for size/address counting functions 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (23 preceding siblings ...) 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 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 26/29] of: fixup unflattened devicetree Sascha Hauer ` (3 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- include/of.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/of.h b/include/of.h index b2f9ca7..21e5687 100644 --- a/include/of.h +++ b/include/of.h @@ -53,6 +53,9 @@ struct driver_d; int of_match(struct device_d *dev, struct driver_d *drv); +int of_n_addr_cells(struct device_node *np); +int of_n_size_cells(struct device_node *np); + struct property *of_find_property(const struct device_node *node, const char *name); struct device_node *of_find_node_by_path(struct device_node *root, const char *path); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 26/29] of: fixup unflattened devicetree 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (24 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 25/29] of: Add missing prototype for size/address counting functions Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 27/29] of: remove unused libfdt Sascha Hauer ` (2 subsequent siblings) 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/boards/at91sam9x5ek/hw_version.c | 31 +++++++------ arch/ppc/mach-mpc5xxx/cpu.c | 26 +++++++---- common/memory.c | 48 ++++++-------------- common/oftree.c | 70 +++++++++-------------------- include/of.h | 6 +-- 5 files changed, 72 insertions(+), 109 deletions(-) diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c index 47c640a..2695faa 100644 --- a/arch/arm/boards/at91sam9x5ek/hw_version.c +++ b/arch/arm/boards/at91sam9x5ek/hw_version.c @@ -232,26 +232,25 @@ static void at91sam9x5ek_devices_detect_one(const char *name) #define NODE_NAME_LEN 128 -static int cm_cogent_fixup(struct fdt_header *fdt) +static int cm_cogent_fixup(struct device_node *root) { - int off, ret; - char node_name[NODE_NAME_LEN]; + int ret; + struct device_node *node; - off = fdt_node_offset_by_compatible(fdt, -1, "atmel,hsmci"); + of_tree_for_each_node(node, root) { + struct device_node *slotnode; - while (off != -FDT_ERR_NOTFOUND) { - off = fdt_subnode_offset(fdt, off, "slot"); - fdt_get_path(fdt, off, node_name, NODE_NAME_LEN); - ret = fdt_setprop(fdt, off, "broken-cd", NULL, 0); - if (ret < 0) { - pr_err("error %d while adding broken-cd property to node %s\n", - ret, node_name); - return ret; - } else { - pr_debug("add broken-cd property to node %s\n", node_name); - } + if (!of_device_is_compatible(node, "atmel,hsmci")) + continue; - off = fdt_node_offset_by_compatible(fdt, off, "atmel,hsmci"); + slotnode = of_find_child_by_name(node, "slot"); + if (!slotnode) + continue; + + ret = of_set_property(slotnode, "broken-cd", NULL, 0, 1); + if (ret) + pr_err("error %d while adding broken-cd property to node %s\n", + ret, slotnode->name); } return 0; diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c index 5bbd49a..99f16eb 100644 --- a/arch/ppc/mach-mpc5xxx/cpu.c +++ b/arch/ppc/mach-mpc5xxx/cpu.c @@ -77,17 +77,27 @@ void __noreturn reset_cpu (unsigned long addr) /* ------------------------------------------------------------------------- */ #ifdef CONFIG_OFTREE -static int of_mpc5200_fixup(struct fdt_header *fdt) +static int of_mpc5200_fixup(struct device_node *root) { - char *cpu_path = "/cpus/PowerPC,5200@0"; + struct device_node *node; + int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4; - do_fixup_by_path_u32(fdt, cpu_path, "timebase-frequency", get_timebase_clock(), 1); - do_fixup_by_path_u32(fdt, cpu_path, "bus-frequency", get_bus_clock(), 1); - do_fixup_by_path_u32(fdt, cpu_path, "clock-frequency", get_cpu_clock(), 1); - do_fixup_by_path_u32(fdt, "/soc5200@f0000000", "bus-frequency", get_ipb_clock(), 1); - do_fixup_by_path_u32(fdt, "/soc5200@f0000000", "system-frequency", - get_bus_clock() * div, 1); + node = of_find_node_by_path(root, "/cpus/PowerPC,5200@0"); + if (!node) + return -EINVAL; + + of_property_write_u32(node, "timebase-frequency", get_timebase_clock()); + of_property_write_u32(node, "bus-frequency", get_bus_clock()); + of_property_write_u32(node, "clock-frequency", get_cpu_clock()); + + node = of_find_node_by_path(root, "/soc5200@f0000000"); + if (!node) + return -EINVAL; + + of_property_write_u32(node, "bus-frequency", get_ipb_clock()); + of_property_write_u32(node, "system-frequency", get_bus_clock() * div); + return 0; } diff --git a/common/memory.c b/common/memory.c index 81641f0..1d2e3a3 100644 --- a/common/memory.c +++ b/common/memory.c @@ -165,22 +165,6 @@ int release_sdram_region(struct resource *res) #ifdef CONFIG_OFTREE /* - * Get cells len in bytes - * if #NNNN-cells property is 2 then len is 8 - * otherwise len is 4 - */ -static int get_cells_len(struct fdt_header *fdt, char *nr_cells_name) -{ - const u32 *cell; - - cell = fdt_getprop(fdt, 0, nr_cells_name, NULL); - if (cell && *cell == 2) - return 8; - - return 4; -} - -/* * Write a 4 or 8 byte big endian cell */ static void write_cell(u8 *addr, u64 val, int size) @@ -193,28 +177,24 @@ static void write_cell(u8 *addr, u64 val, int size) } } -static int of_memory_fixup(struct fdt_header *fdt) +static int of_memory_fixup(struct device_node *node) { struct memory_bank *bank; - int err, nodeoffset; + int err; int addr_cell_len, size_cell_len, len = 0; + struct device_node *memnode; u8 tmp[16 * 16]; /* Up to 64-bit address + 64-bit size */ - /* update, or add and update /memory node */ - nodeoffset = fdt_get_path_or_create(fdt, "/memory"); - if (nodeoffset < 0) - return nodeoffset; + memnode = of_create_node(node, "/memory"); + if (!memnode) + return -ENOMEM; - err = fdt_setprop(fdt, nodeoffset, "device_type", "memory", - sizeof("memory")); - if (err < 0) { - printf("WARNING: could not set %s %s.\n", "device_type", - fdt_strerror(err)); + err = of_set_property(memnode, "device_type", "memory", sizeof("memory"), 1); + if (err) return err; - } - addr_cell_len = get_cells_len(fdt, "#address-cells"); - size_cell_len = get_cells_len(fdt, "#size-cells"); + addr_cell_len = of_n_addr_cells(memnode) * 4; + size_cell_len = of_n_size_cells(memnode) * 4; for_each_memory_bank(bank) { write_cell(tmp + len, bank->start, addr_cell_len); @@ -223,12 +203,12 @@ static int of_memory_fixup(struct fdt_header *fdt) len += size_cell_len; } - err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len); - if (err < 0) { - printf("WARNING: could not set %s %s.\n", - "reg", fdt_strerror(err)); + err = of_set_property(memnode, "reg", tmp, len, 1); + if (err) { + pr_err("could not set reg %s.\n", strerror(-err)); return err; } + return 0; } diff --git a/common/oftree.c b/common/oftree.c index b616b59..abbb7bd 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -246,26 +246,24 @@ int fdt_get_path_or_create(struct fdt_header *fdt, const char *path) return nodeoffset; } -static int of_fixup_bootargs(struct fdt_header *fdt) +static int of_fixup_bootargs(struct device_node *root) { - int nodeoffset; + struct device_node *node; const char *str; int err; - nodeoffset = fdt_get_path_or_create(fdt, "/chosen"); - if (nodeoffset < 0) - return nodeoffset; - str = linux_bootargs_get(); - if (str) { - err = fdt_setprop(fdt, nodeoffset, - "bootargs", str, strlen(str)+1); - if (err < 0) - printf("WARNING: could not set bootargs %s.\n", - fdt_strerror(err)); - } + if (!str) + return 0; - return 0; + node = of_create_node(root, "/chosen"); + if (!node) + return -ENOMEM; + + + err = of_set_property(node, "bootargs", str, strlen(str) + 1, 1); + + return err; } static int of_register_bootargs_fixup(void) @@ -275,13 +273,13 @@ static int of_register_bootargs_fixup(void) late_initcall(of_register_bootargs_fixup); struct of_fixup { - int (*fixup)(struct fdt_header *); + int (*fixup)(struct device_node *); struct list_head list; }; static LIST_HEAD(of_fixup_list); -int of_register_fixup(int (*fixup)(struct fdt_header *)) +int of_register_fixup(int (*fixup)(struct device_node *)) { struct of_fixup *of_fixup = xzalloc(sizeof(*of_fixup)); @@ -296,13 +294,13 @@ int of_register_fixup(int (*fixup)(struct fdt_header *)) * Apply registered fixups for the given fdt. The fdt must have * enough free space to apply the fixups. */ -int of_fix_tree(struct fdt_header *fdt) +int of_fix_tree(struct device_node *node) { struct of_fixup *of_fixup; int ret; list_for_each_entry(of_fixup, &of_fixup_list, list) { - ret = of_fixup->fixup(fdt); + ret = of_fixup->fixup(node); if (ret) return ret; } @@ -325,8 +323,6 @@ int of_fix_tree(struct fdt_header *fdt) struct fdt_header *of_get_fixed_tree(struct device_node *node) { int ret; - void *fixfdt, *internalfdt = NULL; - int size, align; struct fdt_header *fdt; if (!node) { @@ -335,35 +331,13 @@ struct fdt_header *of_get_fixed_tree(struct device_node *node) return NULL; } - fdt = internalfdt = of_flatten_dtb(node); - if (!fdt) - return NULL; - - size = fdt_totalsize(fdt); - - /* - * ARM Linux uses a single 1MiB section (with 1MiB alignment) - * for mapping the devicetree, so we are not allowed to cross - * 1MiB boundaries. - */ - align = 1 << fls(size + OFTREE_SIZE_INCREASE - 1); - - fixfdt = xmemalign(align, size + OFTREE_SIZE_INCREASE); - ret = fdt_open_into(fdt, fixfdt, size + OFTREE_SIZE_INCREASE); - - free(internalfdt); - + ret = of_fix_tree(node); if (ret) - goto out_free; - - ret = of_fix_tree(fixfdt); - if (ret) - goto out_free; - - return fixfdt; + return NULL; -out_free: - free(fixfdt); + fdt = of_flatten_dtb(node); + if (!fdt) + return NULL; - return NULL; + return fdt; } diff --git a/include/of.h b/include/of.h index 21e5687..66b9fde 100644 --- a/include/of.h +++ b/include/of.h @@ -7,9 +7,6 @@ int fdt_print(struct fdt_header *working_fdt, const char *pathp); -int of_fix_tree(struct fdt_header *fdt); -int of_register_fixup(int (*fixup)(struct fdt_header *)); - int fdt_find_and_setprop(struct fdt_header *fdt, const char *node, const char *prop, const void *val, int len, int create); void do_fixup_by_path(struct fdt_header *fdt, const char *path, const char *prop, @@ -51,6 +48,9 @@ struct of_device_id { struct driver_d; +int of_fix_tree(struct device_node *); +int of_register_fixup(int (*fixup)(struct device_node *)); + int of_match(struct device_d *dev, struct driver_d *drv); int of_n_addr_cells(struct device_node *np); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 27/29] of: remove unused libfdt 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (25 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 26/29] of: fixup unflattened devicetree Sascha Hauer @ 2013-02-26 20:18 ` 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 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Now that we are completely independent of libfdt remove the unused code. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/boards/at91sam9m10ihd/hw_version.c | 1 - arch/arm/boards/at91sam9x5ek/hw_version.c | 1 - arch/arm/boards/sama5d3xek/hw_version.c | 1 - arch/arm/lib/bootm.c | 1 - commands/bootm.c | 1 - commands/of_node.c | 1 - commands/of_property.c | 1 - commands/oftree.c | 3 +- common/memory.c | 1 - common/oftree.c | 148 ---- drivers/of/Kconfig | 1 - drivers/of/base.c | 1 - drivers/of/dtb.c | 1 - include/fdt.h | 13 + include/libfdt.h | 1235 --------------------------- include/libfdt_env.h | 21 - include/of.h | 10 - lib/Kconfig | 3 - lib/Makefile | 1 - lib/fdt/Makefile | 2 - lib/fdt/TODO | 3 - lib/fdt/fdt.c | 222 ----- lib/fdt/fdt_ro.c | 574 ------------- lib/fdt/fdt_rw.c | 465 ---------- lib/fdt/fdt_strerror.c | 96 --- lib/fdt/fdt_sw.c | 256 ------ lib/fdt/fdt_wip.c | 118 --- lib/fdt/libfdt_internal.h | 95 --- 28 files changed, 14 insertions(+), 3262 deletions(-) delete mode 100644 include/libfdt.h delete mode 100644 include/libfdt_env.h delete mode 100644 lib/fdt/Makefile delete mode 100644 lib/fdt/TODO delete mode 100644 lib/fdt/fdt.c delete mode 100644 lib/fdt/fdt_ro.c delete mode 100644 lib/fdt/fdt_rw.c delete mode 100644 lib/fdt/fdt_strerror.c delete mode 100644 lib/fdt/fdt_sw.c delete mode 100644 lib/fdt/fdt_wip.c delete mode 100644 lib/fdt/libfdt_internal.h diff --git a/arch/arm/boards/at91sam9m10ihd/hw_version.c b/arch/arm/boards/at91sam9m10ihd/hw_version.c index cd522f7..be910df 100644 --- a/arch/arm/boards/at91sam9m10ihd/hw_version.c +++ b/arch/arm/boards/at91sam9m10ihd/hw_version.c @@ -20,7 +20,6 @@ #include <libbb.h> #include <asm/armlinux.h> #include <of.h> -#include <libfdt.h> #include "hw_version.h" diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c index 2695faa..76d4e1b 100644 --- a/arch/arm/boards/at91sam9x5ek/hw_version.c +++ b/arch/arm/boards/at91sam9x5ek/hw_version.c @@ -20,7 +20,6 @@ #include <libbb.h> #include <asm/armlinux.h> #include <of.h> -#include <libfdt.h> #include "hw_version.h" diff --git a/arch/arm/boards/sama5d3xek/hw_version.c b/arch/arm/boards/sama5d3xek/hw_version.c index a9fcf7d..79fd63a 100644 --- a/arch/arm/boards/sama5d3xek/hw_version.c +++ b/arch/arm/boards/sama5d3xek/hw_version.c @@ -20,7 +20,6 @@ #include <libbb.h> #include <asm/armlinux.h> #include <of.h> -#include <libfdt.h> #include "hw_version.h" diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 234f3e0..92f9e11 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -14,7 +14,6 @@ #include <sizes.h> #include <libbb.h> #include <magicvar.h> -#include <libfdt.h> #include <binfmt.h> #include <asm/byteorder.h> diff --git a/commands/bootm.c b/commands/bootm.c index 65a75e2..4acc57f 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -34,7 +34,6 @@ #include <errno.h> #include <boot.h> #include <of.h> -#include <libfdt.h> #include <rtc.h> #include <init.h> #include <of.h> diff --git a/commands/of_node.c b/commands/of_node.c index 2f6ecae..27f070d 100644 --- a/commands/of_node.c +++ b/commands/of_node.c @@ -24,7 +24,6 @@ #include <command.h> #include <fs.h> #include <malloc.h> -#include <libfdt.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <errno.h> diff --git a/commands/of_property.c b/commands/of_property.c index 585522c..1b968d8 100644 --- a/commands/of_property.c +++ b/commands/of_property.c @@ -24,7 +24,6 @@ #include <command.h> #include <fs.h> #include <malloc.h> -#include <libfdt.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <errno.h> diff --git a/commands/oftree.c b/commands/oftree.c index e4f52b8..468235a 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -30,7 +30,6 @@ #include <command.h> #include <fs.h> #include <malloc.h> -#include <libfdt.h> #include <linux/ctype.h> #include <linux/err.h> #include <asm/byteorder.h> @@ -114,7 +113,7 @@ static int do_oftree(int argc, char *argv[]) goto out; } - ret = write_file(file, fdt, fdt_totalsize(fdt)); + ret = write_file(file, fdt, fdt32_to_cpu(fdt->totalsize)); goto out; } diff --git a/common/memory.c b/common/memory.c index 1d2e3a3..6e59a0a 100644 --- a/common/memory.c +++ b/common/memory.c @@ -21,7 +21,6 @@ #include <memory.h> #include <of.h> #include <init.h> -#include <libfdt.h> #include <linux/ioport.h> #include <asm-generic/memory_layout.h> #include <asm/sections.h> diff --git a/common/oftree.c b/common/oftree.c index abbb7bd..776d301 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -5,7 +5,6 @@ #include <command.h> #include <fs.h> #include <malloc.h> -#include <libfdt.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <errno.h> @@ -99,153 +98,6 @@ void of_print_property(const void *data, int len) } } -static void printf_indent(int level, const char *fmt, ...) -{ - va_list args; - - printf("%*s", level * 8, ""); - - va_start (args, fmt); - vprintf(fmt, args); - va_end (args); -} - -int fdt_print(struct fdt_header *working_fdt, const char *pathp) -{ - 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 */ - int level = 0; /* keep track of nesting level */ - const struct fdt_property *fdt_prop; - - nodeoffset = fdt_path_offset(working_fdt, pathp); - if (nodeoffset < 0) { - /* - * Not found or something else bad happened. - */ - printf("libfdt fdt_path_offset() returned %s\n", - fdt_strerror(nodeoffset)); - return 1; - } - - while (level >= 0) { - tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); - switch (tag) { - case FDT_BEGIN_NODE: - pathp = fdt_get_name(working_fdt, nodeoffset, NULL); - if (pathp == NULL) - pathp = "/* NULL pointer error */"; - if (*pathp == '\0') - pathp = "/"; /* root is nameless */ - printf_indent(level, "%s {\n",pathp); - level++; - if (level >= MAX_LEVEL) { - printf("Nested too deep, aborting.\n"); - return 1; - } - break; - case FDT_END_NODE: - level--; - printf_indent(level, "};\n"); - if (level == 0) { - level = -1; /* exit the loop */ - } - break; - case FDT_PROP: - fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset, - sizeof(*fdt_prop)); - pathp = fdt_string(working_fdt, - fdt32_to_cpu(fdt_prop->nameoff)); - len = fdt32_to_cpu(fdt_prop->len); - nodep = fdt_prop->data; - if (len < 0) { - printf("libfdt fdt_getprop(): %s\n", - fdt_strerror(len)); - return 1; - } else if (len == 0) { - /* the property has no value */ - printf_indent(level, "%s;\n", pathp); - } else { - printf_indent(level, "%s = ", pathp); - of_print_property(nodep, len); - printf(";\n"); - } - break; - case FDT_NOP: - printf_indent(level, "/* NOP */\n"); - break; - case FDT_END: - return 1; - default: - printf("Unknown tag 0x%08X\n", tag); - return 1; - } - nodeoffset = nextoffset; - } - return 0; -} - -/** - * fdt_find_and_setprop: Find a node and set it's property - * - * @fdt: ptr to device tree - * @node: path of node - * @prop: property name - * @val: ptr to new value - * @len: length of new property value - * @create: flag to create the property if it doesn't exist - * - * Convenience function to directly set a property given the path to the node. - */ -int fdt_find_and_setprop(struct fdt_header *fdt, const char *node, - const char *prop, const void *val, int len, int create) -{ - int nodeoff = fdt_path_offset(fdt, node); - - if (nodeoff < 0) - return nodeoff; - - if ((!create) && (fdt_get_property(fdt, nodeoff, prop, NULL) == NULL)) - return 0; /* create flag not set; so exit quietly */ - - return fdt_setprop(fdt, nodeoff, prop, val, len); -} - -void do_fixup_by_path(struct fdt_header *fdt, const char *path, - const char *prop, const void *val, int len, int create) -{ - int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); - if (rc) - printf("Unable to update property %s:%s, err=%s\n", - path, prop, fdt_strerror(rc)); -} - -void do_fixup_by_path_u32(struct fdt_header *fdt, const char *path, - const char *prop, u32 val, int create) -{ - val = cpu_to_fdt32(val); - do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create); -} - -int fdt_get_path_or_create(struct fdt_header *fdt, const char *path) -{ - int nodeoffset; - - nodeoffset = fdt_path_offset (fdt, path); - if (nodeoffset < 0) { - nodeoffset = fdt_add_subnode(fdt, 0, path + 1); - if (nodeoffset < 0) { - printf("WARNING: could not create %s %s.\n", - path, fdt_strerror(nodeoffset)); - return -EINVAL; - } - } - - return nodeoffset; -} - static int of_fixup_bootargs(struct device_node *root) { struct device_node *node; diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index c30b1c1..031bec1 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -1,5 +1,4 @@ config OFTREE - select FDT bool config OFDEVICE diff --git a/drivers/of/base.c b/drivers/of/base.c index c47801a..faff883 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -20,7 +20,6 @@ #include <common.h> #include <of.h> #include <errno.h> -#include <libfdt.h> #include <malloc.h> #include <init.h> #include <memory.h> diff --git a/drivers/of/dtb.c b/drivers/of/dtb.c index 671ea63..ae4130e 100644 --- a/drivers/of/dtb.c +++ b/drivers/of/dtb.c @@ -20,7 +20,6 @@ #include <common.h> #include <of.h> #include <errno.h> -#include <libfdt.h> #include <malloc.h> #include <init.h> #include <memory.h> diff --git a/include/fdt.h b/include/fdt.h index 48ccfd9..35278e3 100644 --- a/include/fdt.h +++ b/include/fdt.h @@ -3,6 +3,19 @@ #ifndef __ASSEMBLY__ +#define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) + +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) + +static inline uint64_t fdt64_to_cpu(uint64_t x) +{ + return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) + | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); +} +#define cpu_to_fdt64(x) fdt64_to_cpu(x) +#undef _B + struct fdt_header { uint32_t magic; /* magic word FDT_MAGIC */ uint32_t totalsize; /* total size of DT block */ diff --git a/include/libfdt.h b/include/libfdt.h deleted file mode 100644 index 55f3eb3..0000000 --- a/include/libfdt.h +++ /dev/null @@ -1,1235 +0,0 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <libfdt_env.h> -#include <fdt.h> - -#define FDT_FIRST_SUPPORTED_VERSION 0x10 -#define FDT_LAST_SUPPORTED_VERSION 0x11 - -/* Error codes: informative error codes */ -#define FDT_ERR_NOTFOUND 1 - /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ -#define FDT_ERR_EXISTS 2 - /* FDT_ERR_EXISTS: Attemped to create a node or property which - * already exists */ -#define FDT_ERR_NOSPACE 3 - /* FDT_ERR_NOSPACE: Operation needed to expand the device - * tree, but its buffer did not have sufficient space to - * contain the expanded tree. Use fdt_open_into() to move the - * device tree to a buffer with more space. */ - -/* Error codes: codes for bad parameters */ -#define FDT_ERR_BADOFFSET 4 - /* FDT_ERR_BADOFFSET: Function was passed a structure block - * offset which is out-of-bounds, or which points to an - * unsuitable part of the structure for the operation. */ -#define FDT_ERR_BADPATH 5 - /* FDT_ERR_BADPATH: Function was passed a badly formatted path - * (e.g. missing a leading / for a function which requires an - * absolute path) */ -#define FDT_ERR_BADPHANDLE 6 - /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle - * value. phandle values of 0 and -1 are not permitted. */ -#define FDT_ERR_BADSTATE 7 - /* FDT_ERR_BADSTATE: Function was passed an incomplete device - * tree created by the sequential-write functions, which is - * not sufficiently complete for the requested operation. */ - -/* Error codes: codes for bad device tree blobs */ -#define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: Structure block of the given device tree - * ends without an FDT_END tag. */ -#define FDT_ERR_BADMAGIC 9 - /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a - * device tree at all - it is missing the flattened device - * tree magic number. */ -#define FDT_ERR_BADVERSION 10 - /* FDT_ERR_BADVERSION: Given device tree has a version which - * can't be handled by the requested operation. For - * read-write functions, this may mean that fdt_open_into() is - * required to convert the tree to the expected version. */ -#define FDT_ERR_BADSTRUCTURE 11 - /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt - * structure block or other serious error (e.g. misnested - * nodes, or subnodes preceding properties). */ -#define FDT_ERR_BADLAYOUT 12 - /* FDT_ERR_BADLAYOUT: For read-write functions, the given - * device tree has it's sub-blocks in an order that the - * function can't handle (memory reserve map, then structure, - * then strings). Use fdt_open_into() to reorganize the tree - * into a form suitable for the read-write operations. */ - -/* "Can't happen" error indicating a bug in libfdt */ -#define FDT_ERR_INTERNAL 13 - /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. - * Should never be returned, if it is, it indicates a bug in - * libfdt itself. */ - -#define FDT_ERR_MAX 13 - -/**********************************************************************/ -/* Low-level functions (you probably don't need these) */ -/**********************************************************************/ - -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); -static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) -{ - return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); -} - -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); - -/**********************************************************************/ -/* Traversal functions */ -/**********************************************************************/ - -int fdt_next_node(const void *fdt, int offset, int *depth); - -/**********************************************************************/ -/* General functions */ -/**********************************************************************/ - -#define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) -#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) -#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) -#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) -#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) -#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) -#define fdt_version(fdt) (fdt_get_header(fdt, version)) -#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) -#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) -#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) -#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) - -#define __fdt_set_hdr(name) \ - static inline void fdt_set_##name(void *fdt, uint32_t val) \ - { \ - struct fdt_header *fdth = (struct fdt_header*)fdt; \ - fdth->name = cpu_to_fdt32(val); \ - } -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr - -/** - * fdt_check_header - sanity check a device tree or possible device tree - * @fdt: pointer to data which might be a flattened device tree - * - * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree with sane information in its - * header. - * - * returns: - * 0, if the buffer appears to contain a valid device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings, as above - */ -int fdt_check_header(const void *fdt); - -/** - * fdt_move - move a device tree around in memory - * @fdt: pointer to the device tree to move - * @buf: pointer to memory where the device is to be moved - * @bufsize: size of the memory space at buf - * - * fdt_move() relocates, if possible, the device tree blob located at - * fdt to the buffer at buf of size bufsize. The buffer may overlap - * with the existing device tree blob at fdt. Therefore, - * fdt_move(fdt, fdt, fdt_totalsize(fdt)) - * should always succeed. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_move(const void *fdt, void *buf, int bufsize); - -/**********************************************************************/ -/* Read-only functions */ -/**********************************************************************/ - -/** - * fdt_string - retrieve a string from the strings block of a device tree - * @fdt: pointer to the device tree blob - * @stroffset: offset of the string within the strings block (native endian) - * - * fdt_string() retrieves a pointer to a single string from the - * strings block of the device tree blob at fdt. - * - * returns: - * a pointer to the string, on success - * NULL, if stroffset is out of bounds - */ -const char *fdt_string(const void *fdt, int stroffset); - -/** - * fdt_num_mem_rsv - retrieve the number of memory reserve map entries - * @fdt: pointer to the device tree blob - * - * Returns the number of entries in the device tree blob's memory - * reservation map. This does not include the terminating 0,0 entry - * or any other (0,0) entries reserved for expansion. - * - * returns: - * the number of entries - */ -int fdt_num_mem_rsv(const void *fdt); - -/** - * fdt_get_mem_rsv - retrieve one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: pointers to 64-bit variables - * - * On success, *address and *size will contain the address and size of - * the n-th reserve map entry from the device tree blob, in - * native-endian format. - * - * returns: - * 0, on success - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); - -/** - * fdt_subnode_offset_namelen - find a subnode based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_subnode_offset(), but only examine the first - * namelen characters of name for matching the subnode name. This is - * useful for finding subnodes based on a portion of a larger string, - * such as a full path. - */ -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, - const char *name, int namelen); -/** - * fdt_subnode_offset - find a subnode of a given node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_subnode_offset() finds a subnode of the node at structure block - * offset parentoffset with the given name. name may include a unit - * address, in which case fdt_subnode_offset() will find the subnode - * with that unit address, or the unit address may be omitted, in - * which case fdt_subnode_offset() will find an arbitrary subnode - * whose name excluding unit address matches the given name. - * - * returns: - * structure block offset of the requested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); - -/** - * fdt_path_offset - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate - * - * fdt_path_offset() finds a node of a given path in the device tree. - * Each path component may omit the unit address portion, but the - * results of this are undefined if any such path component is - * ambiguous (that is if there are multiple nodes at the relevant - * level matching the given component, differentiated only by unit - * address). - * - * returns: - * structure block offset of the node with the requested path (>=0), on success - * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid - * -FDT_ERR_NOTFOUND, if the requested node does not exist - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_path_offset(const void *fdt, const char *path); - -/** - * fdt_get_name - retrieve the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the starting node - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_name() retrieves the name (including unit address) of the - * device tree node at structure block offset nodeoffset. If lenp is - * non-NULL, the length of this name is also returned, in the integer - * pointed to by lenp. - * - * returns: - * pointer to the node's name, on success - * If lenp is non-NULL, *lenp contains the length of that name (>=0) - * NULL, on error - * if lenp is non-NULL *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); - -/** - * fdt_first_property_offset - find the offset of a node's first property - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * - * fdt_first_property_offset() finds the first property of the node at - * the given structure block offset. - * - * returns: - * structure block offset of the property (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested node has no properties - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_first_property_offset(const void *fdt, int nodeoffset); - -/** - * fdt_next_property_offset - step through a node's properties - * @fdt: pointer to the device tree blob - * @offset: structure block offset of a property - * - * fdt_next_property_offset() finds the property immediately after the - * one at the given structure block offset. This will be a property - * of the same node as the given property. - * - * returns: - * structure block offset of the next property (>=0), on success - * -FDT_ERR_NOTFOUND, if the given property is the last in its node - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_next_property_offset(const void *fdt, int offset); - -/** - * fdt_get_property_by_offset - retrieve the property at a given offset - * @fdt: pointer to the device tree blob - * @offset: offset of the property to retrieve - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property_by_offset() retrieves a pointer to the - * fdt_property structure within the device tree blob at the given - * offset. If lenp is non-NULL, the length of the property value is - * also returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp); - -/** - * fdt_get_property_namelen - find a property based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_get_property_namelen(), but only examine the first - * namelen characters of name for matching the property name. - */ -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int nodeoffset, - const char *name, - int namelen, int *lenp); - -/** - * fdt_get_property - find a given property in a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property() retrieves a pointer to the fdt_property - * structure within the device tree blob corresponding to the property - * named 'name' of the node at offset nodeoffset. If lenp is - * non-NULL, the length of the property value is also returned, in the - * integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, - const char *name, - int *lenp) -{ - return (struct fdt_property *)(uintptr_t) - fdt_get_property(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_getprop_by_offset - retrieve the value of a property at a given offset - * @fdt: pointer to the device tree blob - * @ffset: offset of the property to read - * @namep: pointer to a string variable (will be overwritten) or NULL - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop_by_offset() retrieves a pointer to the value of the - * property at structure block offset 'offset' (this will be a pointer - * to within the device blob itself, not a copy of the value). If - * lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. If namep is non-NULL, - * the property's namne will also be returned in the char * pointed to - * by namep (this will be a pointer to within the device tree's string - * block, not a new copy of the name). - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * if namep is non-NULL *namep contiains a pointer to the property - * name. - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp); - -/** - * fdt_getprop_namelen - get property value based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_getprop(), but only examine the first namelen - * characters of name for matching the property name. - */ -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp); - -/** - * fdt_getprop - retrieve the value of a given property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop() retrieves a pointer to the value of the property - * named 'name' of the node at offset nodeoffset (this will be a - * pointer to within the device blob itself, not a copy of the value). - * If lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline void *fdt_getprop_w(void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_get_phandle - retrieve the phandle of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the node - * - * fdt_get_phandle() retrieves the phandle of the device tree node at - * structure block offset nodeoffset. - * - * returns: - * the phandle of the node at nodeoffset, on success (!= 0, != -1) - * 0, if the node has no phandle, or another error occurs - */ -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); - -/** - * fdt_get_alias_namelen - get alias based on substring - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * @namelen: number of characters of name to consider - * - * Identical to fdt_get_alias(), but only examine the first namelen - * characters of name for matching the alias name. - */ -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen); - -/** - * fdt_get_alias - retreive the path referenced by a given alias - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * - * fdt_get_alias() retrieves the value of a given alias. That is, the - * value of the property named 'name' in the node /aliases. - * - * returns: - * a pointer to the expansion of the alias named 'name', of it exists - * NULL, if the given alias or the /aliases node does not exist - */ -const char *fdt_get_alias(const void *fdt, const char *name); - -/** - * fdt_get_path - determine the full path of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose path to find - * @buf: character buffer to contain the returned path (will be overwritten) - * @buflen: size of the character buffer at buf - * - * fdt_get_path() computes the full path of the node at offset - * nodeoffset, and records that path in the buffer at buf. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * 0, on success - * buf contains the absolute path of the node at - * nodeoffset, as a NUL-terminated string. - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) - * characters and will not fit in the given buffer. - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); - -/** - * fdt_supernode_atdepth_offset - find a specific ancestor of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * @supernodedepth: depth of the ancestor to find - * @nodedepth: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_supernode_atdepth_offset() finds an ancestor of the given node - * at a specific depth from the root (where the root itself has depth - * 0, its immediate subnodes depth 1 and so forth). So - * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); - * will always return 0, the offset of the root node. If the node at - * nodeoffset has depth D, then: - * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); - * will return nodeoffset itself. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - - * structure block offset of the node at node offset's ancestor - * of depth supernodedepth (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth); - -/** - * fdt_node_depth - find the depth of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_node_depth() finds the depth of a given node. The root node - * has depth 0, its immediate subnodes depth 1 and so forth. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * depth of the node at nodeoffset (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_depth(const void *fdt, int nodeoffset); - -/** - * fdt_parent_offset - find the parent of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_parent_offset() locates the parent node of a given node (that - * is, it finds the offset of the node which contains the node at - * nodeoffset as a subnode). - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset, *twice*. - * - * returns: - * structure block offset of the parent of the node at nodeoffset - * (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_parent_offset(const void *fdt, int nodeoffset); - -/** - * fdt_node_offset_by_prop_value - find nodes with a given property value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @propname: property name to check - * @propval: property value to search for - * @proplen: length of the value in propval - * - * fdt_node_offset_by_prop_value() returns the offset of the first - * node after startoffset, which has a property named propname whose - * value is of length proplen and has value equal to propval; or if - * startoffset is -1, the very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, - * propval, proplen); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, - * propval, proplen); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen); - -/** - * fdt_node_offset_by_phandle - find the node with a given phandle - * @fdt: pointer to the device tree blob - * @phandle: phandle value - * - * fdt_node_offset_by_phandle() returns the offset of the node - * which has the given phandle value. If there is more than one node - * in the tree with the given phandle (an invalid tree), results are - * undefined. - * - * returns: - * structure block offset of the located node (>= 0), on success - * -FDT_ERR_NOTFOUND, no node with that phandle exists - * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); - -/** - * fdt_node_check_compatible: check a node's compatible property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @compatible: string to match against - * - * - * fdt_node_check_compatible() returns 0 if the given node contains a - * 'compatible' property with the given string as one of its elements, - * it returns non-zero otherwise, or on error. - * - * returns: - * 0, if the node has a 'compatible' property listing the given string - * 1, if the node has a 'compatible' property, but it does not list - * the given string - * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property - * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible); - -/** - * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @compatible: 'compatible' string to match against - * - * fdt_node_offset_by_compatible() returns the offset of the first - * node after startoffset, which has a 'compatible' property which - * lists the given compatible string; or if startoffset is -1, the - * very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible); - -/**********************************************************************/ -/* Write-in-place functions */ -/**********************************************************************/ - -/** - * fdt_setprop_inplace - change a property's value, but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to replace the property value with - * @len: length of the property value - * - * fdt_setprop_inplace() replaces the value of a given property with - * the data in val, of length len. This function cannot change the - * size of a property, and so will only work if len is equal to the - * current length of the property. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if len is not equal to the property's current length - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_setprop_inplace_cell - change the value of a single-cell property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: cell (32-bit integer) value to replace the property with - * - * fdt_setprop_inplace_cell() replaces the value of a given property - * with the 32-bit integer cell value in val, converting val to - * big-endian if necessary. This function cannot change the size of a - * property, and so will only work if the property already exists and - * has length 4. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_nop_property - replace a property with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_nop_property() will replace a given property's representation - * in the blob with FDT_NOP tags, effectively removing it from the - * tree. - * - * This function will alter only the bytes in the blob which contain - * the property, and will not alter or move any other part of the - * tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_property(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_nop_node - replace a node (subtree) with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_nop_node() will replace a given node's representation in the - * blob, including all its subnodes, if any, with FDT_NOP tags, - * effectively removing it from the tree. - * - * This function will alter only the bytes in the blob which contain - * the node and its properties and subnodes, and will not alter or - * move any other part of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_node(void *fdt, int nodeoffset); - -/**********************************************************************/ -/* Sequential write functions */ -/**********************************************************************/ - -int fdt_create(void *buf, int bufsize); -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); -int fdt_finish_reservemap(void *fdt); -int fdt_begin_node(void *fdt, const char *name); -int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_property(fdt, name, &val, sizeof(val)); -} -#define fdt_property_string(fdt, name, str) \ - fdt_property(fdt, name, str, strlen(str)+1) -int fdt_end_node(void *fdt); -int fdt_finish(void *fdt); - -/**********************************************************************/ -/* Read-write functions */ -/**********************************************************************/ - -int fdt_open_into(const void *fdt, void *buf, int bufsize); -int fdt_pack(void *fdt); - -/** - * fdt_add_mem_rsv - add one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: 64-bit values (native endian) - * - * Adds a reserve map entry to the given blob reserving a region at - * address address of length size. - * - * This function will insert data into the reserve map and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new reservation entry - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); - -/** - * fdt_del_mem_rsv - remove a memory reserve map entry - * @fdt: pointer to the device tree blob - * @n: entry to remove - * - * fdt_del_mem_rsv() removes the n-th memory reserve map entry from - * the blob. - * - * This function will delete data from the reservation table and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there - * are less than n+1 reserve map entries) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_mem_rsv(void *fdt, int n); - -/** - * fdt_set_name - change the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * @name: name to give the node - * - * fdt_set_name() replaces the name (including unit address, if any) - * of the given node with the given string. NOTE: this function can't - * efficiently check if the new name is unique amongst the given - * node's siblings; results are undefined if this function is invoked - * with a name equal to one of the given node's siblings. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob - * to contain the new name - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_set_name(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_setprop - create or change a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to set the property value to - * @len: length of the property value - * - * fdt_setprop() sets the value of the named property in the given - * node to the given value and length, creating the property if it - * does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_setprop_cell - set a property to a single cell value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value for the property (native endian) - * - * fdt_setprop_cell() sets the value of the named property in the - * given node to the given cell value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_setprop_string - set a property to a string value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value for the property - * - * fdt_setprop_string() sets the value of the named property in the - * given node to the given string value (using the length of the - * string to determine the new length of the property), or creates a - * new property with that value if it does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_setprop_string(fdt, nodeoffset, name, str) \ - fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - -/** - * fdt_delprop - delete a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_del_property() will delete the given property. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_delprop(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_add_subnode_namelen - creates a new node based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_add_subnode(), but use only the first namelen - * characters of name as the name of the new node. This is useful for - * creating subnodes based on a portion of a larger string, such as a - * full path. - */ -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen); - -/** - * fdt_add_subnode - creates a new node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_add_subnode() creates a new node as a subnode of the node at - * structure block offset parentoffset, with the given name (which - * should include the unit address, if any). - * - * This function will insert data into the blob, and will therefore - * change the offsets of some existing nodes. - - * returns: - * structure block offset of the created nodeequested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of - * the given name - * -FDT_ERR_NOSPACE, if there is insufficient free space in the - * blob to contain the new node - * -FDT_ERR_NOSPACE - * -FDT_ERR_BADLAYOUT - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_add_subnode(void *fdt, int parentoffset, const char *name); - -/** - * fdt_del_node - delete a node (subtree) - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_del_node() will remove the given node, including all its - * subnodes if any, from the blob. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_node(void *fdt, int nodeoffset); - -/**********************************************************************/ -/* Debugging / informational functions */ -/**********************************************************************/ - -const char *fdt_strerror(int errval); - -#endif /* _LIBFDT_H */ diff --git a/include/libfdt_env.h b/include/libfdt_env.h deleted file mode 100644 index 6486187..0000000 --- a/include/libfdt_env.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H - -#include <linux/types.h> -#include <string.h> -#include <asm/byteorder.h> - -#define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) - -#define fdt32_to_cpu(x) be32_to_cpu(x) -#define cpu_to_fdt32(x) cpu_to_be32(x) - -static inline uint64_t fdt64_to_cpu(uint64_t x) -{ - return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) - | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); -} -#define cpu_to_fdt64(x) fdt64_to_cpu(x) -#undef _B - -#endif /* _LIBFDT_ENV_H */ diff --git a/include/of.h b/include/of.h index 66b9fde..9d50694 100644 --- a/include/of.h +++ b/include/of.h @@ -5,16 +5,6 @@ #include <errno.h> #include <asm/byteorder.h> -int fdt_print(struct fdt_header *working_fdt, const char *pathp); - -int fdt_find_and_setprop(struct fdt_header *fdt, const char *node, const char *prop, - const void *val, int len, int create); -void do_fixup_by_path(struct fdt_header *fdt, const char *path, const char *prop, - const void *val, int len, int create); -void do_fixup_by_path_u32(struct fdt_header *fdt, const char *path, const char *prop, - u32 val, int create); -int fdt_get_path_or_create(struct fdt_header *fdt, const char *path); - #define OF_BAD_ADDR ((u64)-1) typedef u32 phandle; diff --git a/lib/Kconfig b/lib/Kconfig index d58109b..646fdb7 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -22,9 +22,6 @@ config PROCESS_ESCAPE_SEQUENCE source lib/lzo/Kconfig -config FDT - bool - config BCH bool diff --git a/lib/Makefile b/lib/Makefile index 3c94542..7c42537 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -31,7 +31,6 @@ obj-y += lzo/ obj-y += show_progress.o obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o -obj-$(CONFIG_FDT) += fdt/ obj-$(CONFIG_UNCOMPRESS) += uncompress.o obj-$(CONFIG_BCH) += bch.o obj-$(CONFIG_BITREV) += bitrev.o diff --git a/lib/fdt/Makefile b/lib/fdt/Makefile deleted file mode 100644 index 853bee9..0000000 --- a/lib/fdt/Makefile +++ /dev/null @@ -1,2 +0,0 @@ - -obj-y += fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o diff --git a/lib/fdt/TODO b/lib/fdt/TODO deleted file mode 100644 index 288437e..0000000 --- a/lib/fdt/TODO +++ /dev/null @@ -1,3 +0,0 @@ -- Tree traversal functions -- Graft function -- Complete libfdt.h documenting comments diff --git a/lib/fdt/fdt.c b/lib/fdt/fdt.c deleted file mode 100644 index e56833a..0000000 --- a/lib/fdt/fdt.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -int fdt_check_header(const void *fdt) -{ - if (fdt_magic(fdt) == FDT_MAGIC) { - /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) - return -FDT_ERR_BADSTATE; - } else { - return -FDT_ERR_BADMAGIC; - } - - return 0; -} - -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) -{ - const char *p; - - if (fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) - || ((offset + len) > fdt_size_dt_struct(fdt))) - return NULL; - - p = _fdt_offset_ptr(fdt, offset); - - if (p + len < p) - return NULL; - return p; -} - -uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) -{ - const uint32_t *tagp, *lenp; - uint32_t tag; - int offset = startoffset; - const char *p; - - *nextoffset = -FDT_ERR_TRUNCATED; - tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) - return FDT_END; /* premature end */ - tag = fdt32_to_cpu(*tagp); - offset += FDT_TAGSIZE; - - *nextoffset = -FDT_ERR_BADSTRUCTURE; - switch (tag) { - case FDT_BEGIN_NODE: - /* skip name */ - do { - p = fdt_offset_ptr(fdt, offset++, 1); - } while (p && (*p != '\0')); - if (!p) - return FDT_END; /* premature end */ - break; - - case FDT_PROP: - lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) - return FDT_END; /* premature end */ - /* skip-name offset, length and value */ - offset += sizeof(struct fdt_property) - FDT_TAGSIZE - + fdt32_to_cpu(*lenp); - break; - - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return FDT_END; - } - - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) - return FDT_END; /* premature end */ - - *nextoffset = FDT_TAGALIGN(offset); - return tag; -} - -int _fdt_check_node_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int _fdt_check_prop_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int fdt_next_node(const void *fdt, int offset, int *depth) -{ - int nextoffset = 0; - uint32_t tag; - - if (offset >= 0) - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) - return nextoffset; - - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_PROP: - case FDT_NOP: - break; - - case FDT_BEGIN_NODE: - if (depth) - (*depth)++; - break; - - case FDT_END_NODE: - if (depth && ((--(*depth)) < 0)) - return nextoffset; - break; - - case FDT_END: - if ((nextoffset >= 0) - || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) - return -FDT_ERR_NOTFOUND; - else - return nextoffset; - } - } while (tag != FDT_BEGIN_NODE); - - return offset; -} - -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) -{ - int len = strlen(s) + 1; - const char *last = strtab + tabsize - len; - const char *p; - - for (p = strtab; p <= last; p++) - if (memcmp(p, s, len) == 0) - return p; - return NULL; -} - -int fdt_move(const void *fdt, void *buf, int bufsize) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_totalsize(fdt) > bufsize) - return -FDT_ERR_NOSPACE; - - memmove(buf, fdt, fdt_totalsize(fdt)); - return 0; -} diff --git a/lib/fdt/fdt_ro.c b/lib/fdt/fdt_ro.c deleted file mode 100644 index 02b6d68..0000000 --- a/lib/fdt/fdt_ro.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_nodename_eq(const void *fdt, int offset, - const char *s, int len) -{ - const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); - - if (! p) - /* short match */ - return 0; - - if (memcmp(p, s, len) != 0) - return 0; - - if (p[len] == '\0') - return 1; - else if (!memchr(s, '@', len) && (p[len] == '@')) - return 1; - else - return 0; -} - -const char *fdt_string(const void *fdt, int stroffset) -{ - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; -} - -static int _fdt_string_eq(const void *fdt, int stroffset, - const char *s, int len) -{ - const char *p = fdt_string(fdt, stroffset); - - return (strlen(p) == len) && (memcmp(p, s, len) == 0); -} - -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) -{ - FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); - return 0; -} - -int fdt_num_mem_rsv(const void *fdt) -{ - int i = 0; - - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) - i++; - return i; -} - -static int _nextprop(const void *fdt, int offset) -{ - uint32_t tag; - int nextoffset; - - do { - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - if (nextoffset >= 0) - return -FDT_ERR_BADSTRUCTURE; - else - return nextoffset; - - case FDT_PROP: - return offset; - } - offset = nextoffset; - } while (tag == FDT_NOP); - - return -FDT_ERR_NOTFOUND; -} - -int fdt_subnode_offset_namelen(const void *fdt, int offset, - const char *name, int namelen) -{ - int depth; - - FDT_CHECK_HEADER(fdt); - - for (depth = 0; - (offset >= 0) && (depth >= 0); - offset = fdt_next_node(fdt, offset, &depth)) - if ((depth == 1) - && _fdt_nodename_eq(fdt, offset, name, namelen)) - return offset; - - if (depth < 0) - return -FDT_ERR_NOTFOUND; - return offset; /* error */ -} - -int fdt_subnode_offset(const void *fdt, int parentoffset, - const char *name) -{ - return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_path_offset(const void *fdt, const char *path) -{ - const char *end = path + strlen(path); - const char *p = path; - int offset = 0; - - FDT_CHECK_HEADER(fdt); - - /* see if we have an alias */ - if (*path != '/') { - const char *q = strchr(path, '/'); - - if (!q) - q = end; - - p = fdt_get_alias_namelen(fdt, p, q - p); - if (!p) - return -FDT_ERR_BADPATH; - offset = fdt_path_offset(fdt, p); - - p = q; - } - - while (*p) { - const char *q; - - while (*p == '/') - p++; - if (! *p) - return offset; - q = strchr(p, '/'); - if (! q) - q = end; - - offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); - if (offset < 0) - return offset; - - p = q; - } - - return offset; -} - -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) -{ - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); - int err; - - if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) - goto fail; - - if (len) - *len = strlen(nh->name); - - return nh->name; - - fail: - if (len) - *len = err; - return NULL; -} - -int fdt_first_property_offset(const void *fdt, int nodeoffset) -{ - int offset; - - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -int fdt_next_property_offset(const void *fdt, int offset) -{ - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp) -{ - int err; - const struct fdt_property *prop; - - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { - if (lenp) - *lenp = err; - return NULL; - } - - prop = _fdt_offset_ptr(fdt, offset); - - if (lenp) - *lenp = fdt32_to_cpu(prop->len); - - return prop; -} - -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int offset, - const char *name, - int namelen, int *lenp) -{ - for (offset = fdt_first_property_offset(fdt, offset); - (offset >= 0); - (offset = fdt_next_property_offset(fdt, offset))) { - const struct fdt_property *prop; - - if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { - offset = -FDT_ERR_INTERNAL; - break; - } - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), - name, namelen)) - return prop; - } - - if (lenp) - *lenp = offset; - return NULL; -} - -const struct fdt_property *fdt_get_property(const void *fdt, - int nodeoffset, - const char *name, int *lenp) -{ - return fdt_get_property_namelen(fdt, nodeoffset, name, - strlen(name), lenp); -} - -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); - if (! prop) - return NULL; - - return prop->data; -} - -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_by_offset(fdt, offset, lenp); - if (!prop) - return NULL; - if (namep) - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - return prop->data; -} - -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); -} - -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) -{ - const uint32_t *php; - int len; - - /* FIXME: This is a bit sub-optimal, since we potentially scan - * over all the properties twice. */ - php = fdt_getprop(fdt, nodeoffset, "phandle", &len); - if (!php || (len != sizeof(*php))) { - php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); - if (!php || (len != sizeof(*php))) - return 0; - } - - return fdt32_to_cpu(*php); -} - -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen) -{ - int aliasoffset; - - aliasoffset = fdt_path_offset(fdt, "/aliases"); - if (aliasoffset < 0) - return NULL; - - return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); -} - -const char *fdt_get_alias(const void *fdt, const char *name) -{ - return fdt_get_alias_namelen(fdt, name, strlen(name)); -} - -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) -{ - int pdepth = 0, p = 0; - int offset, depth, namelen; - const char *name; - - FDT_CHECK_HEADER(fdt); - - if (buflen < 2) - return -FDT_ERR_NOSPACE; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - while (pdepth > depth) { - do { - p--; - } while (buf[p-1] != '/'); - pdepth--; - } - - if (pdepth >= depth) { - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if ((p + namelen + 1) <= buflen) { - memcpy(buf + p, name, namelen); - p += namelen; - buf[p++] = '/'; - pdepth++; - } - } - - if (offset == nodeoffset) { - if (pdepth < (depth + 1)) - return -FDT_ERR_NOSPACE; - - if (p > 1) /* special case so that root path is "/", not "" */ - p--; - buf[p] = '\0'; - return 0; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth) -{ - int offset, depth; - int supernodeoffset = -FDT_ERR_INTERNAL; - - FDT_CHECK_HEADER(fdt); - - if (supernodedepth < 0) - return -FDT_ERR_NOTFOUND; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - if (depth == supernodedepth) - supernodeoffset = offset; - - if (offset == nodeoffset) { - if (nodedepth) - *nodedepth = depth; - - if (supernodedepth > depth) - return -FDT_ERR_NOTFOUND; - else - return supernodeoffset; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_depth(const void *fdt, int nodeoffset) -{ - int nodedepth; - int err; - - err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); - if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; - return nodedepth; -} - -int fdt_parent_offset(const void *fdt, int nodeoffset) -{ - int nodedepth = fdt_node_depth(fdt, nodeoffset); - - if (nodedepth < 0) - return nodedepth; - return fdt_supernode_atdepth_offset(fdt, nodeoffset, - nodedepth - 1, NULL); -} - -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen) -{ - int offset; - const void *val; - int len; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we scan each - * property of a node in fdt_getprop(), then if that didn't - * find what we want, we scan over them again making our way - * to the next node. Still it's the easiest to implement - * approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - val = fdt_getprop(fdt, offset, propname, &len); - if (val && (len == proplen) - && (memcmp(val, propval, len) == 0)) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) -{ - int offset; - - if ((phandle == 0) || (phandle == -1)) - return -FDT_ERR_BADPHANDLE; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we - * potentially scan each property of a node in - * fdt_get_phandle(), then if that didn't find what - * we want, we scan over them again making our way to the next - * node. Still it's the easiest to implement approach; - * performance can come later. */ - for (offset = fdt_next_node(fdt, -1, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - if (fdt_get_phandle(fdt, offset) == phandle) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -static int _fdt_stringlist_contains(const char *strlist, int listlen, - const char *str) -{ - int len = strlen(str); - const char *p; - - while (listlen >= len) { - if (memcmp(str, strlist, len+1) == 0) - return 1; - p = memchr(strlist, '\0', listlen); - if (!p) - return 0; /* malformed strlist.. */ - listlen -= (p-strlist) + 1; - strlist = p + 1; - } - return 0; -} - -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible) -{ - const void *prop; - int len; - - prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); - if (!prop) - return len; - if (_fdt_stringlist_contains(prop, len, compatible)) - return 0; - else - return 1; -} - -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible) -{ - int offset, err; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we scan each - * property of a node in fdt_node_check_compatible(), then if - * that didn't find what we want, we scan over them again - * making our way to the next node. Still it's the easiest to - * implement approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - err = fdt_node_check_compatible(fdt, offset, compatible); - if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) - return err; - else if (err == 0) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} diff --git a/lib/fdt/fdt_rw.c b/lib/fdt/fdt_rw.c deleted file mode 100644 index 994037b..0000000 --- a/lib/fdt/fdt_rw.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_blocks_misordered(const void *fdt, - int mem_rsv_size, int struct_size) -{ - return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) - || (fdt_off_dt_struct(fdt) < - (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) - || (fdt_off_dt_strings(fdt) < - (fdt_off_dt_struct(fdt) + struct_size)) - || (fdt_totalsize(fdt) < - (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); -} - -static int _fdt_rw_check_header(void *fdt) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_version(fdt) < 17) - return -FDT_ERR_BADVERSION; - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), - fdt_size_dt_struct(fdt))) - return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) - fdt_set_version(fdt, 17); - - return 0; -} - -#define FDT_RW_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_rw_check_header(fdt)) != 0) \ - return err; \ - } - -static inline int _fdt_data_size(void *fdt) -{ - return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); -} - -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) -{ - char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); - - if (((p + oldlen) < p) || ((p + oldlen) > end)) - return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) - return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); - return 0; -} - -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, - int oldn, int newn) -{ - int delta = (newn - oldn) * sizeof(*p); - int err; - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); - if (err) - return err; - fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_struct(void *fdt, void *p, - int oldlen, int newlen) -{ - int delta = newlen - oldlen; - int err; - - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) - return err; - - fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_string(void *fdt, int newlen) -{ - void *p = (char *)fdt - + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); - int err; - - if ((err = _fdt_splice(fdt, p, 0, newlen))) - return err; - - fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); - const char *p; - char *new; - int len = strlen(s) + 1; - int err; - - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); - if (p) - /* found it */ - return (p - strtab); - - new = strtab + fdt_size_dt_strings(fdt); - err = _fdt_splice_string(fdt, len); - if (err) - return err; - - memcpy(new, s, len); - return (new - strtab); -} - -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) -{ - struct fdt_reserve_entry *re; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); - if (err) - return err; - - re->address = cpu_to_fdt64(address); - re->size = cpu_to_fdt64(size); - return 0; -} - -int fdt_del_mem_rsv(void *fdt, int n) -{ - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); - int err; - - FDT_RW_CHECK_HEADER(fdt); - - if (n >= fdt_num_mem_rsv(fdt)) - return -FDT_ERR_NOTFOUND; - - err = _fdt_splice_mem_rsv(fdt, re, 1, 0); - if (err) - return err; - return 0; -} - -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int oldlen; - int err; - - *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (! (*prop)) - return oldlen; - - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(len)))) - return err; - - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int proplen; - int nextoffset; - int namestroff; - int err; - - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return nextoffset; - - namestroff = _fdt_find_add_string(fdt, name); - if (namestroff < 0) - return namestroff; - - *prop = _fdt_offset_ptr_w(fdt, nextoffset); - proplen = sizeof(**prop) + FDT_TAGALIGN(len); - - err = _fdt_splice_struct(fdt, *prop, 0, proplen); - if (err) - return err; - - (*prop)->tag = cpu_to_fdt32(FDT_PROP); - (*prop)->nameoff = cpu_to_fdt32(namestroff); - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -int fdt_set_name(void *fdt, int nodeoffset, const char *name) -{ - char *namep; - int oldlen, newlen; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); - if (!namep) - return oldlen; - - newlen = strlen(name); - - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), - FDT_TAGALIGN(newlen+1)); - if (err) - return err; - - memcpy(namep, name, newlen+1); - return 0; -} - -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - struct fdt_property *prop; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); - if (err == -FDT_ERR_NOTFOUND) - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - - memcpy(prop->data, val, len); - return 0; -} - -int fdt_delprop(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len, proplen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) - return len; - - proplen = sizeof(*prop) + FDT_TAGALIGN(len); - return _fdt_splice_struct(fdt, prop, proplen, 0); -} - -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen) -{ - struct fdt_node_header *nh; - int offset, nextoffset; - int nodelen; - int err; - uint32_t tag; - uint32_t *endtag; - - FDT_RW_CHECK_HEADER(fdt); - - offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); - if (offset >= 0) - return -FDT_ERR_EXISTS; - else if (offset != -FDT_ERR_NOTFOUND) - return offset; - - /* Try to place the new node after the parent's properties */ - fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - } while ((tag == FDT_PROP) || (tag == FDT_NOP)); - - nh = _fdt_offset_ptr_w(fdt, offset); - nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - - err = _fdt_splice_struct(fdt, nh, 0, nodelen); - if (err) - return err; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); - memcpy(nh->name, name, namelen); - endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); - *endtag = cpu_to_fdt32(FDT_END_NODE); - - return offset; -} - -int fdt_add_subnode(void *fdt, int parentoffset, const char *name) -{ - return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_del_node(void *fdt, int nodeoffset) -{ - int endoffset; - - FDT_RW_CHECK_HEADER(fdt); - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), - endoffset - nodeoffset, 0); -} - -static void _fdt_packblocks(const char *old, char *new, - int mem_rsv_size, int struct_size) -{ - int mem_rsv_off, struct_off, strings_off; - - mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); - struct_off = mem_rsv_off + mem_rsv_size; - strings_off = struct_off + struct_size; - - memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); - fdt_set_off_mem_rsvmap(new, mem_rsv_off); - - memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); - fdt_set_off_dt_struct(new, struct_off); - fdt_set_size_dt_struct(new, struct_size); - - memmove(new + strings_off, old + fdt_off_dt_strings(old), - fdt_size_dt_strings(old)); - fdt_set_off_dt_strings(new, strings_off); - fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); -} - -int fdt_open_into(const void *fdt, void *buf, int bufsize) -{ - int err; - int mem_rsv_size, struct_size; - int newsize; - const char *fdtstart = fdt; - const char *fdtend = fdtstart + fdt_totalsize(fdt); - char *tmp; - - FDT_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - - if (fdt_version(fdt) >= 17) { - struct_size = fdt_size_dt_struct(fdt); - } else { - struct_size = 0; - while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) - ; - if (struct_size < 0) - return struct_size; - } - - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { - /* no further work necessary */ - err = fdt_move(fdt, buf, bufsize); - if (err) - return err; - fdt_set_version(buf, 17); - fdt_set_size_dt_struct(buf, struct_size); - fdt_set_totalsize(buf, bufsize); - return 0; - } - - /* Need to reorder */ - newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size - + struct_size + fdt_size_dt_strings(fdt); - - if (bufsize < newsize) - return -FDT_ERR_NOSPACE; - - /* First attempt to build converted tree at beginning of buffer */ - tmp = buf; - /* But if that overlaps with the old tree... */ - if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { - /* Try right after the old tree instead */ - tmp = (char *)(uintptr_t)fdtend; - if ((tmp + newsize) > ((char *)buf + bufsize)) - return -FDT_ERR_NOSPACE; - } - - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); - memmove(buf, tmp, newsize); - - fdt_set_magic(buf, FDT_MAGIC); - fdt_set_totalsize(buf, bufsize); - fdt_set_version(buf, 17); - fdt_set_last_comp_version(buf, 16); - fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); - - return 0; -} - -int fdt_pack(void *fdt) -{ - int mem_rsv_size; - - FDT_RW_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); - - return 0; -} diff --git a/lib/fdt/fdt_strerror.c b/lib/fdt/fdt_strerror.c deleted file mode 100644 index e6c3cee..0000000 --- a/lib/fdt/fdt_strerror.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -struct fdt_errtabent { - const char *str; -}; - -#define FDT_ERRTABENT(val) \ - [(val)] = { .str = #val, } - -static struct fdt_errtabent fdt_errtable[] = { - FDT_ERRTABENT(FDT_ERR_NOTFOUND), - FDT_ERRTABENT(FDT_ERR_EXISTS), - FDT_ERRTABENT(FDT_ERR_NOSPACE), - - FDT_ERRTABENT(FDT_ERR_BADOFFSET), - FDT_ERRTABENT(FDT_ERR_BADPATH), - FDT_ERRTABENT(FDT_ERR_BADSTATE), - - FDT_ERRTABENT(FDT_ERR_TRUNCATED), - FDT_ERRTABENT(FDT_ERR_BADMAGIC), - FDT_ERRTABENT(FDT_ERR_BADVERSION), - FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), - FDT_ERRTABENT(FDT_ERR_BADLAYOUT), -}; -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) - -const char *fdt_strerror(int errval) -{ - if (errval > 0) - return "<valid offset/length>"; - else if (errval == 0) - return "<no error>"; - else if (errval > -FDT_ERRTABSIZE) { - const char *s = fdt_errtable[-errval].str; - - if (s) - return s; - } - - return "<unknown error>"; -} diff --git a/lib/fdt/fdt_sw.c b/lib/fdt/fdt_sw.c deleted file mode 100644 index 55ebebf..0000000 --- a/lib/fdt/fdt_sw.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_sw_check_header(void *fdt) -{ - if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; - /* FIXME: should check more details about the header state */ - return 0; -} - -#define FDT_SW_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_sw_check_header(fdt)) != 0) \ - return err; \ - } - -static void *_fdt_grab_space(void *fdt, size_t len) -{ - int offset = fdt_size_dt_struct(fdt); - int spaceleft; - - spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - - fdt_size_dt_strings(fdt); - - if ((offset + len < offset) || (offset + len > spaceleft)) - return NULL; - - fdt_set_size_dt_struct(fdt, offset + len); - return _fdt_offset_ptr_w(fdt, offset); -} - -int fdt_create(void *buf, int bufsize) -{ - void *fdt = buf; - - if (bufsize < sizeof(struct fdt_header)) - return -FDT_ERR_NOSPACE; - - memset(buf, 0, bufsize); - - fdt_set_magic(fdt, FDT_SW_MAGIC); - fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); - fdt_set_totalsize(fdt, bufsize); - - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); - fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, bufsize); - - return 0; -} - -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) -{ - struct fdt_reserve_entry *re; - int offset; - - FDT_SW_CHECK_HEADER(fdt); - - if (fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTATE; - - offset = fdt_off_dt_struct(fdt); - if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) - return -FDT_ERR_NOSPACE; - - re = (struct fdt_reserve_entry *)((char *)fdt + offset); - re->address = cpu_to_fdt64(addr); - re->size = cpu_to_fdt64(size); - - fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); - - return 0; -} - -int fdt_finish_reservemap(void *fdt) -{ - return fdt_add_reservemap_entry(fdt, 0, 0); -} - -int fdt_begin_node(void *fdt, const char *name) -{ - struct fdt_node_header *nh; - int namelen = strlen(name) + 1; - - FDT_SW_CHECK_HEADER(fdt); - - nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); - if (! nh) - return -FDT_ERR_NOSPACE; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memcpy(nh->name, name, namelen); - return 0; -} - -int fdt_end_node(void *fdt) -{ - uint32_t *en; - - FDT_SW_CHECK_HEADER(fdt); - - en = _fdt_grab_space(fdt, FDT_TAGSIZE); - if (! en) - return -FDT_ERR_NOSPACE; - - *en = cpu_to_fdt32(FDT_END_NODE); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_totalsize(fdt); - const char *p; - int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; - - p = _fdt_find_string(strtab - strtabsize, strtabsize, s); - if (p) - return p - strtab; - - /* Add it */ - offset = -strtabsize - len; - struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) - return 0; /* no more room :( */ - - memcpy(strtab + offset, s, len); - fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; -} - -int fdt_property(void *fdt, const char *name, const void *val, int len) -{ - struct fdt_property *prop; - int nameoff; - - FDT_SW_CHECK_HEADER(fdt); - - nameoff = _fdt_find_add_string(fdt, name); - if (nameoff == 0) - return -FDT_ERR_NOSPACE; - - prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) - return -FDT_ERR_NOSPACE; - - prop->tag = cpu_to_fdt32(FDT_PROP); - prop->nameoff = cpu_to_fdt32(nameoff); - prop->len = cpu_to_fdt32(len); - memcpy(prop->data, val, len); - return 0; -} - -int fdt_finish(void *fdt) -{ - char *p = (char *)fdt; - uint32_t *end; - int oldstroffset, newstroffset; - uint32_t tag; - int offset, nextoffset; - - FDT_SW_CHECK_HEADER(fdt); - - /* Add terminator */ - end = _fdt_grab_space(fdt, sizeof(*end)); - if (! end) - return -FDT_ERR_NOSPACE; - *end = cpu_to_fdt32(FDT_END); - - /* Relocate the string table */ - oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); - newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); - fdt_set_off_dt_strings(fdt, newstroffset); - - /* Walk the structure, correcting string offsets */ - offset = 0; - while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { - if (tag == FDT_PROP) { - struct fdt_property *prop = - _fdt_offset_ptr_w(fdt, offset); - int nameoff; - - nameoff = fdt32_to_cpu(prop->nameoff); - nameoff += fdt_size_dt_strings(fdt); - prop->nameoff = cpu_to_fdt32(nameoff); - } - offset = nextoffset; - } - if (nextoffset < 0) - return nextoffset; - - /* Finally, adjust the header */ - fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); - fdt_set_magic(fdt, FDT_MAGIC); - return 0; -} diff --git a/lib/fdt/fdt_wip.c b/lib/fdt/fdt_wip.c deleted file mode 100644 index 6025fa1..0000000 --- a/lib/fdt/fdt_wip.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - void *propval; - int proplen; - - propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); - if (! propval) - return proplen; - - if (proplen != len) - return -FDT_ERR_NOSPACE; - - memcpy(propval, val, len); - return 0; -} - -static void _fdt_nop_region(void *start, int len) -{ - uint32_t *p; - - for (p = start; (char *)p < ((char *)start + len); p++) - *p = cpu_to_fdt32(FDT_NOP); -} - -int fdt_nop_property(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len; - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) - return len; - - _fdt_nop_region(prop, len + sizeof(*prop)); - - return 0; -} - -int _fdt_node_end_offset(void *fdt, int offset) -{ - int depth = 0; - - while ((offset >= 0) && (depth >= 0)) - offset = fdt_next_node(fdt, offset, &depth); - - return offset; -} - -int fdt_nop_node(void *fdt, int nodeoffset) -{ - int endoffset; - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), - endoffset - nodeoffset); - return 0; -} diff --git a/lib/fdt/libfdt_internal.h b/lib/fdt/libfdt_internal.h deleted file mode 100644 index 381133b..0000000 --- a/lib/fdt/libfdt_internal.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _LIBFDT_INTERNAL_H -#define _LIBFDT_INTERNAL_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include <fdt.h> - -#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) - -#define FDT_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = fdt_check_header(fdt)) != 0) \ - return err; \ - } - -int _fdt_check_node_offset(const void *fdt, int offset); -int _fdt_check_prop_offset(const void *fdt, int offset); -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(void *fdt, int nodeoffset); - -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) -{ - return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; -} - -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) -{ - return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); -} - -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) -{ - const struct fdt_reserve_entry *rsv_table = - (const struct fdt_reserve_entry *) - ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); - - return rsv_table + n; -} -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) -{ - return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); -} - -#define FDT_SW_MAGIC (~FDT_MAGIC) - -#endif /* _LIBFDT_INTERNAL_H */ -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 28/29] of_* commands: print usage when insufficient arguments are given 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (26 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 27/29] of: remove unused libfdt Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 2013-02-26 20:18 ` [PATCH 29/29] of_property command: Fix crash with empty property value Sascha Hauer 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/of_node.c | 3 +++ commands/of_property.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/commands/of_node.c b/commands/of_node.c index 27f070d..0249d97 100644 --- a/commands/of_node.c +++ b/commands/of_node.c @@ -53,6 +53,9 @@ static int do_of_node(int argc, char *argv[]) } } + if (optind == argc) + return COMMAND_ERROR_USAGE; + if (optind < argc) { path = argv[optind]; } diff --git a/commands/of_property.c b/commands/of_property.c index 1b968d8..5d35bb4 100644 --- a/commands/of_property.c +++ b/commands/of_property.c @@ -191,6 +191,9 @@ static int do_of_property(int argc, char *argv[]) } } + if (optind == argc) + return COMMAND_ERROR_USAGE; + root = of_get_root_node(); if (!root) { printf("root node not set\n"); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 29/29] of_property command: Fix crash with empty property value 2013-02-26 20:18 [PATCH] remove libfdt Sascha Hauer ` (27 preceding siblings ...) 2013-02-26 20:18 ` [PATCH 28/29] of_* commands: print usage when insufficient arguments are given Sascha Hauer @ 2013-02-26 20:18 ` Sascha Hauer 28 siblings, 0 replies; 33+ messages in thread From: Sascha Hauer @ 2013-02-26 20:18 UTC (permalink / raw) To: barebox the of_property command crashes when an empty property value was given. This is because xrealloc is called with a length argument of 0. Fix this. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- commands/of_property.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/commands/of_property.c b/commands/of_property.c index 5d35bb4..6311b70 100644 --- a/commands/of_property.c +++ b/commands/of_property.c @@ -254,9 +254,15 @@ static int do_of_property(int argc, char *argv[]) if (pp) { free(pp->value); + /* limit property data to the actual size */ - data = xrealloc(data, len); - pp->value = data; + if (len) { + pp->value = xrealloc(data, len); + } else { + pp->value = NULL; + free(data); + } + pp->length = len; } else { pp = of_new_property(node, propname, data, len); -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2013-02-27 19:51 UTC | newest] Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 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 ` [PATCH 12/29] of: make unflatten independent of libfdt Sascha Hauer 2013-02-26 20:18 ` [PATCH 13/29] of: make flatten " 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox