diff options
-rw-r--r-- | drivers/core/ofnode.c | 26 | ||||
-rw-r--r-- | include/dm/ofnode.h | 10 | ||||
-rw-r--r-- | include/of_live.h | 10 | ||||
-rw-r--r-- | lib/of_live.c | 6 | ||||
-rw-r--r-- | test/dm/ofnode.c | 19 |
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); |