From: Simon Glass Date: Tue, 26 Sep 2023 14:14:40 +0000 (-0600) Subject: dm: core: Add a function to create an empty tree X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=e0c3c21d8ba1a0abbb7effee6c5a952f3e65a03d;p=u-boot.git dm: core: Add a function to create an empty tree Provide a function to create a new, empty tree. Signed-off-by: Simon Glass --- diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 515396c62f..d2bdb8b9af 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 32917f6615..0b96ab34ed 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -127,6 +127,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 * diff --git a/include/of_live.h b/include/of_live.h index 05e86ac06b..81cb9bd13e 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 25f7af6106..e4eee38554 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 = ""; + root->full_name = ""; + *rootp = root; + + return 0; +} diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 3bf97761d1..594116e3c0 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);