summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/core/ofnode.c26
-rw-r--r--include/dm/ofnode.h10
-rw-r--r--include/of_live.h10
-rw-r--r--lib/of_live.c6
-rw-r--r--test/dm/ofnode.c19
5 files changed, 66 insertions, 5 deletions
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index dee890b552..8df16e56af 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -12,6 +12,7 @@
#include <fdt_support.h>
#include <log.h>
#include <malloc.h>
+#include <of_live.h>
#include <linux/libfdt.h>
#include <dm/of_access.h>
#include <dm/of_addr.h>
@@ -51,6 +52,20 @@ static oftree oftree_ensure(void *fdt)
oftree tree;
int i;
+ if (of_live_active()) {
+ struct device_node *root;
+ int ret;
+
+ ret = unflatten_device_tree(fdt, &root);
+ if (ret) {
+ log_err("Failed to create live tree: err=%d\n", ret);
+ return oftree_null();
+ }
+ tree = oftree_from_np(root);
+
+ return tree;
+ }
+
if (gd->flags & GD_FLG_RELOC) {
i = oftree_find(fdt);
if (i == -1) {
@@ -60,11 +75,6 @@ static oftree oftree_ensure(void *fdt)
return oftree_null();
}
- if (of_live_active()) {
- log_err("Cannot register a flattree when OF_LIVE is active\n");
- return oftree_null();
- }
-
/* register the new tree */
i = oftree_count++;
oftree_list[i] = fdt;
@@ -82,6 +92,12 @@ static oftree oftree_ensure(void *fdt)
return tree;
}
+void oftree_dispose(oftree tree)
+{
+ if (of_live_active())
+ of_live_free(tree.np);
+}
+
void *ofnode_lookup_fdt(ofnode node)
{
if (gd->flags & GD_FLG_RELOC) {
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 443db6252d..0f38b3e736 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -353,6 +353,16 @@ static inline oftree oftree_from_np(struct device_node *root)
}
/**
+ * oftree_dispose() - Dispose of an oftree
+ *
+ * This can be used to dispose of a tree that has been created (other than
+ * the control FDT which must not be disposed)
+ *
+ * @tree: Tree to dispose
+ */
+void oftree_dispose(oftree tree);
+
+/**
* ofnode_name_eq() - Check if the node name is equivalent to a given name
* ignoring the unit address
*
diff --git a/include/of_live.h b/include/of_live.h
index f59d6af335..05e86ac06b 100644
--- a/include/of_live.h
+++ b/include/of_live.h
@@ -36,4 +36,14 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp);
*/
int unflatten_device_tree(const void *blob, struct device_node **mynodes);
+/**
+ * of_live_free() - Dispose of a livetree
+ *
+ * This frees memory used by the tree, after which @root becomes invalid and
+ * cannot be used
+ *
+ * @root: Tree to dispose
+ */
+void of_live_free(struct device_node *root);
+
#endif
diff --git a/lib/of_live.c b/lib/of_live.c
index 05588d5ed2..25f7af6106 100644
--- a/lib/of_live.c
+++ b/lib/of_live.c
@@ -330,3 +330,9 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp)
return ret;
}
+
+void of_live_free(struct device_node *root)
+{
+ /* the tree is stored as a contiguous block of memory */
+ free(root);
+}
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 64baaf68db..6fbebc7da0 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -1266,3 +1266,22 @@ static int dm_test_livetree_align(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_livetree_align, UT_TESTF_LIVE_TREE);
+
+/* check that it is possible to load an arbitrary livetree */
+static int dm_test_livetree_ensure(struct unit_test_state *uts)
+{
+ oftree tree;
+ ofnode node;
+
+ /* read from other.dtb */
+ ut_assertok(test_load_other_fdt(uts));
+ tree = oftree_from_fdt(uts->other_fdt);
+ ut_assert(oftree_valid(tree));
+ node = oftree_path(tree, "/node/subnode");
+ ut_assert(ofnode_valid(node));
+ ut_asserteq_str("sandbox-other2",
+ ofnode_read_string(node, "compatible"));
+
+ return 0;
+}
+DM_TEST(dm_test_livetree_ensure, 0);