diff options
author | SzuWei Lin <szuweilin@google.com> | 2017-04-14 15:38:15 +0800 |
---|---|---|
committer | SzuWei Lin <szuweilin@google.com> | 2017-04-15 11:09:17 +0800 |
commit | 8a7039c218527bfc25a2831f480a9558e64f84e5 (patch) | |
tree | 0c730d0a3e83db73cb55bd2536be90029955062e /ufdt_overlay.c | |
parent | 6ad4caae73191bdc2403185b6482969c17604c95 (diff) | |
download | libufdt-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.c | 131 |
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; |