summaryrefslogtreecommitdiff
path: root/ufdt_overlay.c
diff options
context:
space:
mode:
authorSzuWei Lin <szuweilin@google.com>2017-04-14 15:38:15 +0800
committerSzuWei Lin <szuweilin@google.com>2017-04-15 11:09:17 +0800
commit8a7039c218527bfc25a2831f480a9558e64f84e5 (patch)
tree0c730d0a3e83db73cb55bd2536be90029955062e /ufdt_overlay.c
parent6ad4caae73191bdc2403185b6482969c17604c95 (diff)
downloadlibufdt-8a7039c218527bfc25a2831f480a9558e64f84e5.tar.gz
Code revise
- Remove unused code - Remove internel functions from header file - Fix typos - Revise all function names with prefix ufdt_* Test: ./tests/run_tests.sh Change-Id: I4f89e90eb983540e78aadb092c07de62d219e454
Diffstat (limited to 'ufdt_overlay.c')
-rw-r--r--ufdt_overlay.c131
1 files changed, 114 insertions, 17 deletions
diff --git a/ufdt_overlay.c b/ufdt_overlay.c
index d6e250e..08c8ac8 100644
--- a/ufdt_overlay.c
+++ b/ufdt_overlay.c
@@ -68,7 +68,7 @@ static void fdt_increase_u32(void *pos, uint32_t offset) {
* Gets the max phandle of a given ufdt.
*/
static uint32_t ufdt_get_max_phandle(struct ufdt *tree) {
- struct static_phandle_table sorted_table = tree->phandle_table;
+ struct ufdt_static_phandle_table sorted_table = tree->phandle_table;
if (sorted_table.len > 0)
return sorted_table.data[sorted_table.len - 1].phandle;
else
@@ -97,7 +97,7 @@ static void ufdt_node_try_increase_phandle(struct ufdt_node *node,
* in O(n) time.
*/
static void ufdt_try_increase_phandle(struct ufdt *tree, uint32_t offset) {
- struct static_phandle_table sorted_table = tree->phandle_table;
+ struct ufdt_static_phandle_table sorted_table = tree->phandle_table;
int i;
for (i = 0; i < sorted_table.len; i++) {
@@ -259,10 +259,11 @@ static int ufdt_overlay_do_fixups(struct ufdt *main_tree,
struct ufdt_node *fixups = *it;
char *symbol_path = ufdt_node_get_fdt_prop_data_by_name(
- main_symbols_node, name_of(fixups), &len);
+ main_symbols_node, ufdt_node_name(fixups), &len);
if (!symbol_path) {
- dto_error("Couldn't find '%s' symbol in main dtb\n", name_of(fixups));
+ dto_error("Couldn't find '%s' symbol in main dtb\n",
+ ufdt_node_name(fixups));
return -1;
}
@@ -294,7 +295,7 @@ static int ufdt_overlay_do_fixups(struct ufdt *main_tree,
* What is "overlay fragment"? The main purpose is to add some subtrees to the
* main_tree in order to complete the entire device tree.
*
- * A frgament consists of two parts: 1. the subtree to be added 2. where it
+ * A fragment consists of two parts: 1. the subtree to be added 2. where it
* should be added.
*
* Overlaying a fragment requires: 1. find the node in the main_tree 2. merge
@@ -303,6 +304,106 @@ static int ufdt_overlay_do_fixups(struct ufdt *main_tree,
/* BEGIN of applying fragments. */
+/* Proptyping predefined */
+static int merge_ufdt_into(struct ufdt_node *node_a, struct ufdt_node *node_b);
+
+/*
+ * Merges tree_b into tree_a with tree_b has all nodes except root disappeared.
+ * Overwrite property in tree_a if there's one with same name in tree_b.
+ * Otherwise add the property to tree_a.
+ * For subnodes with the same name, recursively run this function.
+ *
+ * Ex:
+ * tree_a : ta {
+ * b = "b";
+ * c = "c";
+ * d {
+ * e = "g";
+ * };
+ * };
+ *
+ * tree_b : tb {
+ * c = "C";
+ * g = "G";
+ * d {
+ * da = "dad";
+ * };
+ * h {
+ * hh = "HH";
+ * };
+ * };
+ *
+ * The resulting trees will be:
+ *
+ * tree_a : ta {
+ * b = "b";
+ * c = "C";
+ * g = "G";
+ * d {
+ * da = "dad";
+ * e = "g";
+ * };
+ * h {
+ * hh = "HH";
+ * };
+ * };
+ *
+ * tree_b : tb {
+ * };
+ *
+ *
+ * @return: 0 if merge success
+ * < 0 otherwise
+ *
+ * @Time: O(# of nodes in tree_b + total length of all names in tree_b) w.h.p.
+ */
+static int merge_children(struct ufdt_node *node_a, struct ufdt_node *node_b) {
+ int err = 0;
+ struct ufdt_node *it;
+ for (it = ((struct ufdt_node_fdt_node *)node_b)->child; it;) {
+ struct ufdt_node *cur_node = it;
+ it = it->sibling;
+ cur_node->sibling = NULL;
+ struct ufdt_node *target_node = NULL;
+ if (ufdt_node_tag(cur_node) == FDT_BEGIN_NODE) {
+ target_node =
+ ufdt_node_get_subnode_by_name(node_a, ufdt_node_name(cur_node));
+ } else {
+ target_node =
+ ufdt_node_get_property_by_name(node_a, ufdt_node_name(cur_node));
+ }
+ if (target_node == NULL) {
+ err = ufdt_node_add_child(node_a, cur_node);
+ } else {
+ err = merge_ufdt_into(target_node, cur_node);
+ }
+ if (err < 0) return -1;
+ }
+ /*
+ * The ufdt_node* in node_b will be copied to node_a.
+ * To prevent the ufdt_node from being freed twice
+ * (main_tree and overlay_tree) at the end of function
+ * ufdt_apply_overlay(), set this node in node_b
+ * (overlay_tree) to NULL.
+ */
+ ((struct ufdt_node_fdt_node *)node_b)->child = NULL;
+
+ return 0;
+}
+
+static int merge_ufdt_into(struct ufdt_node *node_a, struct ufdt_node *node_b) {
+ if (ufdt_node_tag(node_a) == FDT_PROP) {
+ node_a->fdt_tag_ptr = node_b->fdt_tag_ptr;
+ return 0;
+ }
+
+ int err = 0;
+ err = merge_children(node_a, node_b);
+ if (err < 0) return -1;
+
+ return 0;
+}
+
/*
* Overlay the overlay_node over target_node.
*/
@@ -369,8 +470,8 @@ static enum overlay_result ufdt_apply_fragment(struct ufdt *tree,
int err = ufdt_overlay_node(target_node, overlay_node);
if (err < 0) {
- dto_error("failed to overlay node %s to target %s\n", name_of(overlay_node),
- name_of(target_node));
+ dto_error("failed to overlay node %s to target %s\n",
+ ufdt_node_name(overlay_node), ufdt_node_name(target_node));
return OVERLAY_RESULT_MERGE_FAIL;
}
@@ -461,8 +562,8 @@ static int ufdt_local_fixup_node(struct ufdt_node *target_node,
struct ufdt_node *sub_target_node;
for_each_prop(it_local_fixups, local_fixups_node) {
- sub_target_node =
- ufdt_node_get_property_by_name(target_node, name_of(*it_local_fixups));
+ sub_target_node = ufdt_node_get_property_by_name(
+ target_node, ufdt_node_name(*it_local_fixups));
if (sub_target_node != NULL) {
int err = ufdt_local_fixup_prop(sub_target_node, *it_local_fixups,
@@ -474,8 +575,8 @@ static int ufdt_local_fixup_node(struct ufdt_node *target_node,
}
for_each_node(it_local_fixups, local_fixups_node) {
- sub_target_node =
- ufdt_node_get_node_by_path(target_node, name_of(*it_local_fixups));
+ sub_target_node = ufdt_node_get_node_by_path(
+ target_node, ufdt_node_name(*it_local_fixups));
if (sub_target_node != NULL) {
int err = ufdt_local_fixup_node(sub_target_node, *it_local_fixups,
phandle_offset);
@@ -641,12 +742,8 @@ struct fdt_header *ufdt_apply_overlay(struct fdt_header *main_fdt_header,
return NULL;
}
- struct ufdt *main_tree = NULL;
- struct ufdt *overlay_tree = NULL;
-
- main_tree = fdt_to_ufdt(main_fdt_header, main_fdt_size);
- overlay_tree = fdt_to_ufdt(overlay_fdtp, overlay_size);
-
+ struct ufdt *main_tree = ufdt_from_fdt(main_fdt_header, main_fdt_size);
+ struct ufdt *overlay_tree = ufdt_from_fdt(overlay_fdtp, overlay_size);
int err = ufdt_overlay_apply(main_tree, overlay_tree, overlay_size);
if (err < 0) {
goto fail;