aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass2023-09-26 08:14:40 -0600
committerTom Rini2023-10-06 14:38:12 -0400
commite0c3c21d8ba1a0abbb7effee6c5a952f3e65a03d (patch)
tree305d7d79cd9b6776bcccfd3e4911784bff9fa60f
parent9bf78a5add522dfc3f192eb97fb38d829174d6c7 (diff)
dm: core: Add a function to create an empty tree
Provide a function to create a new, empty tree. Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--drivers/core/ofnode.c56
-rw-r--r--include/dm/ofnode.h9
-rw-r--r--include/of_live.h8
-rw-r--r--lib/of_live.c19
-rw-r--r--test/dm/ofnode.c16
5 files changed, 104 insertions, 4 deletions
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 515396c62f4..d2bdb8b9af1 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -47,6 +47,17 @@ static int oftree_find(const void *fdt)
return -1;
}
+static int check_tree_count(void)
+{
+ if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
+ log_warning("Too many registered device trees (max %d)\n",
+ CONFIG_OFNODE_MULTI_TREE_MAX);
+ return -E2BIG;
+ }
+
+ return 0;
+}
+
static oftree oftree_ensure(void *fdt)
{
oftree tree;
@@ -69,11 +80,8 @@ static oftree oftree_ensure(void *fdt)
if (gd->flags & GD_FLG_RELOC) {
i = oftree_find(fdt);
if (i == -1) {
- if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
- log_warning("Too many registered device trees (max %d)\n",
- CONFIG_OFNODE_MULTI_TREE_MAX);
+ if (check_tree_count())
return oftree_null();
- }
/* register the new tree */
i = oftree_count++;
@@ -92,6 +100,41 @@ static oftree oftree_ensure(void *fdt)
return tree;
}
+int oftree_new(oftree *treep)
+{
+ oftree tree = oftree_null();
+ int ret;
+
+ if (of_live_active()) {
+ struct device_node *root;
+
+ ret = of_live_create_empty(&root);
+ if (ret)
+ return log_msg_ret("liv", ret);
+ tree = oftree_from_np(root);
+ } else {
+ const int size = 1024;
+ void *fdt;
+
+ ret = check_tree_count();
+ if (ret)
+ return log_msg_ret("fla", ret);
+
+ /* register the new tree with a small size */
+ fdt = malloc(size);
+ if (!fdt)
+ return log_msg_ret("fla", -ENOMEM);
+ ret = fdt_create_empty_tree(fdt, size);
+ if (ret)
+ return log_msg_ret("fla", -EINVAL);
+ oftree_list[oftree_count++] = fdt;
+ tree.fdt = fdt;
+ }
+ *treep = tree;
+
+ return 0;
+}
+
void oftree_dispose(oftree tree)
{
if (of_live_active())
@@ -193,6 +236,11 @@ static inline int oftree_find(const void *fdt)
return 0;
}
+int oftree_new(oftree *treep)
+{
+ return -ENOSYS;
+}
+
#endif /* OFNODE_MULTI_TREE */
/**
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 32917f66155..0b96ab34ede 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -128,6 +128,15 @@ static inline ofnode noffset_to_ofnode(ofnode other_node, int of_offset)
#endif /* OFNODE_MULTI_TREE */
/**
+ * oftree_new() - Create a new, empty tree
+ *
+ * @treep: Returns a pointer to the tree, on success
+ * Returns: 0 on success, -ENOMEM if out of memory, -E2BIG if !OF_LIVE and
+ * there are too many (flattrees) already
+ */
+int oftree_new(oftree *treep);
+
+/**
* ofnode_to_np() - convert an ofnode to a live DT node pointer
*
* This cannot be called if the reference contains an offset.
diff --git a/include/of_live.h b/include/of_live.h
index 05e86ac06b1..81cb9bd13e2 100644
--- a/include/of_live.h
+++ b/include/of_live.h
@@ -46,4 +46,12 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes);
*/
void of_live_free(struct device_node *root);
+/**
+ * of_live_create_empty() - Create a new, empty tree
+ *
+ * @rootp: Returns the root node of the created tree
+ * Return: 0 if OK, -ENOMEM if out of memory
+ */
+int of_live_create_empty(struct device_node **rootp);
+
#endif
diff --git a/lib/of_live.c b/lib/of_live.c
index 25f7af61061..e4eee385547 100644
--- a/lib/of_live.c
+++ b/lib/of_live.c
@@ -336,3 +336,22 @@ void of_live_free(struct device_node *root)
/* the tree is stored as a contiguous block of memory */
free(root);
}
+
+int of_live_create_empty(struct device_node **rootp)
+{
+ struct device_node *root;
+
+ root = calloc(1, sizeof(struct device_node));
+ if (!root)
+ return -ENOMEM;
+ root->name = strdup("");
+ if (!root->name) {
+ free(root);
+ return -ENOMEM;
+ }
+ root->type = "<NULL>";
+ root->full_name = "";
+ *rootp = root;
+
+ return 0;
+}
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 3bf97761d1e..594116e3c04 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -1346,3 +1346,19 @@ static int dm_test_livetree_ensure(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_livetree_ensure, UT_TESTF_SCAN_FDT);
+
+static int dm_test_oftree_new(struct unit_test_state *uts)
+{
+ ofnode node, subnode, check;
+ oftree tree;
+
+ ut_assertok(oftree_new(&tree));
+ node = oftree_root(tree);
+ ut_assert(ofnode_valid(node));
+ ut_assertok(ofnode_add_subnode(node, "edmund", &subnode));
+ check = ofnode_find_subnode(node, "edmund");
+ ut_asserteq(check.of_offset, subnode.of_offset);
+
+ return 0;
+}
+DM_TEST(dm_test_oftree_new, UT_TESTF_SCAN_FDT);