mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/3] of: Fix memory hole in of_find_node_by_reproducible_name()
@ 2019-09-12  8:35 Sascha Hauer
  2019-09-12  8:35 ` [PATCH 2/3] of: add of_diff() Sascha Hauer
  2019-09-12  8:35 ` [PATCH 3/3] add of_diff command Sascha Hauer
  0 siblings, 2 replies; 3+ messages in thread
From: Sascha Hauer @ 2019-09-12  8:35 UTC (permalink / raw)
  To: Barebox List

of_get_reproducible_name() returns an allocated string, so we must free
it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/of/base.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 838f530f85..22077fa397 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2306,9 +2306,17 @@ struct device_node *of_find_node_by_reproducible_name(struct device_node *from,
 {
 	struct device_node *np;
 
-	of_tree_for_each_node_from(np, from)
-		if (!of_node_cmp(of_get_reproducible_name(np), name))
+	of_tree_for_each_node_from(np, from) {
+		char *rep = of_get_reproducible_name(np);
+		int res;
+
+		res = of_node_cmp(rep, name);
+
+		free(rep);
+
+		if (!res)
 			return np;
+	}
 	return NULL;
 }
 
-- 
2.23.0


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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/3] of: add of_diff()
  2019-09-12  8:35 [PATCH 1/3] of: Fix memory hole in of_find_node_by_reproducible_name() Sascha Hauer
@ 2019-09-12  8:35 ` Sascha Hauer
  2019-09-12  8:35 ` [PATCH 3/3] add of_diff command Sascha Hauer
  1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2019-09-12  8:35 UTC (permalink / raw)
  To: Barebox List

of_diff compares two device trees against each other and prints a
diff-like result.

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

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 22077fa397..63e0879f06 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1776,24 +1776,21 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
 }
 EXPORT_SYMBOL(of_get_child_by_name);
 
-void of_print_nodes(struct device_node *node, int indent)
+static void __of_print_nodes(struct device_node *node, int indent, const char *prefix)
 {
 	struct device_node *n;
 	struct property *p;
-	int i;
 
 	if (!node)
 		return;
 
-	for (i = 0; i < indent; i++)
-		printf("\t");
+	if (!prefix)
+		prefix = "";
 
-	printf("%s%s\n", node->name, node->name ? " {" : "{");
+	printf("%s%*s%s%s\n", prefix, indent * 8, "", node->name, node->name ? " {" : "{");
 
 	list_for_each_entry(p, &node->properties, list) {
-		for (i = 0; i < indent + 1; i++)
-			printf("\t");
-		printf("%s", p->name);
+		printf("%s%*s%s", prefix, (indent + 1) * 8, "", p->name);
 		if (p->length) {
 			printf(" = ");
 			of_print_property(of_property_get_value(p), p->length);
@@ -1802,12 +1799,136 @@ void of_print_nodes(struct device_node *node, int indent)
 	}
 
 	list_for_each_entry(n, &node->children, parent_list) {
-		of_print_nodes(n, indent + 1);
+		__of_print_nodes(n, indent + 1, prefix);
+	}
+
+	printf("%s%*s};\n", prefix, indent * 8, "");
+}
+
+void of_print_nodes(struct device_node *node, int indent)
+{
+	__of_print_nodes(node, indent, NULL);
+}
+
+static void __of_print_property(struct property *p, int indent)
+{
+	int i;
+
+	for (i = 0; i < indent; i++)
+		printf("\t");
+
+	printf("%s", p->name);
+	if (p->length) {
+		printf(" = ");
+		of_print_property(of_property_get_value(p), p->length);
 	}
+	printf(";\n");
+}
+
+static int __of_print_parents(struct device_node *node)
+{
+	int indent, i;
+
+	if (!node->parent)
+		return 0;
+
+	indent = __of_print_parents(node->parent);
 
 	for (i = 0; i < indent; i++)
 		printf("\t");
-	printf("};\n");
+
+	printf("%s {\n", node->name);
+
+	return indent + 1;
+}
+
+static void of_print_parents(struct device_node *node, int *printed)
+{
+	if (*printed)
+		return;
+
+	__of_print_parents(node);
+
+	*printed = 1;
+}
+
+static void of_print_close(struct device_node *node, int *printed)
+{
+	int depth = 0, i, j;
+
+	if (!*printed)
+		return;
+
+	while ((node = node->parent))
+		depth++;
+
+	for (i = depth; i > 0; i--) {
+		for (j = 0; j + 1 < i; j++)
+			printf("\t");
+		printf("};\n");
+	}
+}
+
+/**
+ * of_diff - compare two device trees against each other
+ * @a: The first device tree
+ * @b: The second device tree
+ * @indent: The initial indentation level when printing
+ *
+ * This function compares two device trees against each other and prints
+ * a diff-like result.
+ */
+void of_diff(struct device_node *a, struct device_node *b, int indent)
+{
+	struct property *ap, *bp;
+	struct device_node *ca, *cb;
+	int printed = 0;
+
+	list_for_each_entry(ap, &a->properties, list) {
+		bp = of_find_property(b, ap->name, NULL);
+		if (!bp) {
+			of_print_parents(a, &printed);
+			printf("- ");
+			__of_print_property(ap, indent);
+			continue;
+		}
+
+		if (ap->length != bp->length || memcmp(of_property_get_value(ap), of_property_get_value(bp), bp->length)) {
+			of_print_parents(a, &printed);
+			printf("- ");
+			__of_print_property(ap, indent);
+			printf("+ ");
+			__of_print_property(bp, indent);
+		}
+	}
+
+	list_for_each_entry(bp, &b->properties, list) {
+		ap = of_find_property(a, bp->name, NULL);
+		if (!ap) {
+			of_print_parents(a, &printed);
+			printf("+ ");
+			__of_print_property(bp, indent);
+		}
+	}
+
+	for_each_child_of_node(a, ca) {
+		cb = of_get_child_by_name(b, ca->name);
+		if (cb) {
+			of_diff(ca, cb, indent + 1);
+		} else {
+			of_print_parents(a, &printed);
+			__of_print_nodes(ca, indent, "-");
+		}
+	}
+
+	for_each_child_of_node(b, cb) {
+		if (!of_get_child_by_name(a, cb->name)) {
+			of_print_parents(a, &printed);
+			__of_print_nodes(cb, indent, "+");
+		}
+	}
+
+	of_print_close(a, &printed);
 }
 
 struct device_node *of_new_node(struct device_node *parent, const char *name)
diff --git a/include/of.h b/include/of.h
index b5f54dd4e5..c8275e169b 100644
--- a/include/of.h
+++ b/include/of.h
@@ -104,6 +104,7 @@ void of_print_property(const void *data, int len);
 void of_print_cmdline(struct device_node *root);
 
 void of_print_nodes(struct device_node *node, int indent);
+void of_diff(struct device_node *a, struct device_node *b, int indent);
 int of_probe(void);
 int of_parse_dtb(struct fdt_header *fdt);
 struct device_node *of_unflatten_dtb(const void *fdt);
-- 
2.23.0


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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 3/3] add of_diff command
  2019-09-12  8:35 [PATCH 1/3] of: Fix memory hole in of_find_node_by_reproducible_name() Sascha Hauer
  2019-09-12  8:35 ` [PATCH 2/3] of: add of_diff() Sascha Hauer
@ 2019-09-12  8:35 ` Sascha Hauer
  1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2019-09-12  8:35 UTC (permalink / raw)
  To: Barebox List

The of_diff command compares two device trees against each other
and prints a diff-like result. This can be handy to find out the
differences between the barebox live tree and the one we start the
kernel with. Another usecase would be to examine the changes our
of_fixup process introduces (of_diff - +)

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/Kconfig   |   7 +++
 commands/Makefile  |   1 +
 commands/of_diff.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)
 create mode 100644 commands/of_diff.c

diff --git a/commands/Kconfig b/commands/Kconfig
index e03110fd46..24fd47b5cd 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -2012,6 +2012,13 @@ config CMD_LSMOD
 	help
 	  List loaded barebox modules.
 
+config CMD_OF_DIFF
+	tristate
+	select OFTREE
+	prompt "of_diff"
+	help
+	  Compare two device tree files against each other.
+
 config CMD_OF_DUMP
 	tristate
 	select OFTREE
diff --git a/commands/Makefile b/commands/Makefile
index 5cd35b78a7..a619ee5765 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_CMD_LED_TRIGGER)	+= trigger.o
 obj-$(CONFIG_CMD_USB)		+= usb.o
 obj-$(CONFIG_CMD_TIME)		+= time.o
 obj-$(CONFIG_CMD_OFTREE)	+= oftree.o
+obj-$(CONFIG_CMD_OF_DIFF)	+= of_diff.o
 obj-$(CONFIG_CMD_OF_PROPERTY)	+= of_property.o
 obj-$(CONFIG_CMD_OF_NODE)	+= of_node.o
 obj-$(CONFIG_CMD_OF_DUMP)	+= of_dump.o
diff --git a/commands/of_diff.c b/commands/of_diff.c
new file mode 100644
index 0000000000..4ea801729f
--- /dev/null
+++ b/commands/of_diff.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * of_diff.c - compare device tree files
+ *
+ * Copyright (c) 2019 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ */
+
+#include <common.h>
+#include <fs.h>
+#include <libfile.h>
+#include <of.h>
+#include <command.h>
+#include <malloc.h>
+#include <complete.h>
+#include <errno.h>
+#include <linux/err.h>
+
+static struct device_node *get_tree(const char *filename, struct device_node *root)
+{
+	struct device_node *node;
+	void *fdt;
+	size_t size;
+	int ret;
+
+	if (!strcmp(filename, "-")) {
+		node = of_get_root_node();
+		if (!node)
+			return ERR_PTR(-ENOENT);
+
+		return of_copy_node(NULL, node);
+	}
+
+	if (!strcmp(filename, "+")) {
+		node = of_get_root_node();
+		if (!node)
+			return ERR_PTR(-ENOENT);
+
+		node = of_copy_node(NULL, root);
+
+		of_fix_tree(node);
+
+		return node;
+	}
+
+	ret = read_file_2(filename, &size, &fdt, FILESIZE_MAX);
+	if (ret)
+		return ERR_PTR(ret);
+
+	node = of_unflatten_dtb(fdt);
+
+	free(fdt);
+
+	return node;
+}
+
+// of_diff - /mnt/tftp/sha-oftree-phyCORE-i.MX6
+
+static int do_of_diff(int argc, char *argv[])
+{
+	int ret = 0;
+	struct device_node *a, *b, *root;
+
+	if (argc < 3)
+		return COMMAND_ERROR_USAGE;
+
+	root = of_get_root_node();
+	a = get_tree(argv[1], root);
+	b = get_tree(argv[2], root);
+
+	if (IS_ERR(a)) {
+		printf("Cannot read %s: %s\n", argv[1], strerrorp(a));
+		ret = COMMAND_ERROR;
+		a = NULL;
+		goto out;
+	}
+
+	if (IS_ERR(b)) {
+		printf("Cannot read %s: %s\n", argv[2], strerrorp(b));
+		ret = COMMAND_ERROR;
+		b = NULL;
+		goto out;
+	}
+
+	of_diff(a, b, 0);
+
+	ret = 0;
+out:
+	if (a && a != root)
+		of_delete_node(a);
+	if (b && b != root)
+		of_delete_node(b);
+
+	return ret;
+}
+
+BAREBOX_CMD_HELP_START(of_diff)
+BAREBOX_CMD_HELP_TEXT("This command prints a diff between two given device trees.")
+BAREBOX_CMD_HELP_TEXT("The device trees are given as dtb files or:")
+BAREBOX_CMD_HELP_TEXT("'-' to compare against the barebox live tree, or")
+BAREBOX_CMD_HELP_TEXT("'+' to compare against the fixed barebox live tree")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(of_diff)
+	.cmd		= do_of_diff,
+	BAREBOX_CMD_DESC("diff device trees")
+	BAREBOX_CMD_OPTS("<a> <b>")
+	BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+	BAREBOX_CMD_HELP(cmd_of_diff_help)
+BAREBOX_CMD_END
-- 
2.23.0


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

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-09-12  8:35 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-12  8:35 [PATCH 1/3] of: Fix memory hole in of_find_node_by_reproducible_name() Sascha Hauer
2019-09-12  8:35 ` [PATCH 2/3] of: add of_diff() Sascha Hauer
2019-09-12  8:35 ` [PATCH 3/3] add of_diff command Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox