summaryrefslogtreecommitdiff
path: root/ufdt_convert.c
diff options
context:
space:
mode:
authorJeff Hao <jeffhao@google.com>2016-12-14 02:36:07 +0000
committerJeff Hao <jeffhao@google.com>2016-12-14 02:36:07 +0000
commiteeaff8f66f44518a0e776957c6e0921f7799ace2 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /ufdt_convert.c
parent3084ce7cbdff84093286459758f99c15082e6556 (diff)
downloadlibufdt-eeaff8f66f44518a0e776957c6e0921f7799ace2.tar.gz
Revert "libufdt: device tree overlay via unflattening FDT"
This reverts commit 3084ce7cbdff84093286459758f99c15082e6556. Change-Id: I36f8252ea77c75301711009180c1908bb18e231c
Diffstat (limited to 'ufdt_convert.c')
-rw-r--r--ufdt_convert.c294
1 files changed, 0 insertions, 294 deletions
diff --git a/ufdt_convert.c b/ufdt_convert.c
deleted file mode 100644
index caa3ce3..0000000
--- a/ufdt_convert.c
+++ /dev/null
@@ -1,294 +0,0 @@
-#include "libufdt.h"
-
-#include "fdt_internal.h"
-#include "ufdt_util.h"
-
-
-struct ufdt *ufdt_construct(void *fdtp) {
- struct ufdt *res_ufdt = dto_malloc(sizeof(struct ufdt));
- res_ufdt->fdtp = fdtp;
- res_ufdt->root = NULL;
-
- return res_ufdt;
-}
-
-void ufdt_destruct(struct ufdt *tree) {
- ufdt_node_destruct(tree->root);
- dto_free(tree->phandle_table.data);
-}
-
-static struct ufdt_node *ufdt_new_node(void *fdtp, int node_offset) {
- if (fdtp == NULL) {
- dto_error("Failed to get new_node because tree is NULL\n");
- return NULL;
- }
-
- fdt32_t *fdt_tag_ptr =
- (fdt32_t *)fdt_offset_ptr(fdtp, node_offset, sizeof(fdt32_t));
- struct ufdt_node *res = ufdt_node_construct(fdtp, fdt_tag_ptr);
- return res;
-}
-
-static struct ufdt_node *fdt_to_ufdt_tree(void *fdtp, int cur_fdt_tag_offset,
- int *next_fdt_tag_offset,
- int cur_tag) {
- if (fdtp == NULL) {
- return NULL;
- }
- uint32_t tag;
- struct ufdt_node *res, *child_node;
-
- res = NULL;
- child_node = NULL;
- tag = cur_tag;
-
- switch (tag) {
- case FDT_END_NODE:
- case FDT_NOP:
- case FDT_END:
- break;
-
- case FDT_PROP:
- res = ufdt_new_node(fdtp, cur_fdt_tag_offset);
- break;
-
- case FDT_BEGIN_NODE:
- res = ufdt_new_node(fdtp, cur_fdt_tag_offset);
-
- do {
- cur_fdt_tag_offset = *next_fdt_tag_offset;
- tag = fdt_next_tag(fdtp, cur_fdt_tag_offset, next_fdt_tag_offset);
- child_node = fdt_to_ufdt_tree(fdtp, cur_fdt_tag_offset,
- next_fdt_tag_offset, tag);
- ufdt_node_add_child(res, child_node);
- } while (tag != FDT_END_NODE);
- break;
-
- default:
- break;
- }
-
- return res;
-}
-
-void ufdt_print(struct ufdt *tree) { ufdt_node_print(tree->root, 0); }
-
-struct ufdt_node *ufdt_get_node_by_path_len(struct ufdt *tree, const char *path,
- int len) {
- /*
- * RARE: aliases
- * In device tree, we can assign some alias to specific nodes by defining
- * these relation in "/aliases" node.
- * The node has the form:
- * {
- * a = "/a_for_apple";
- * b = "/b_for_banana";
- * };
- * So the path "a/subnode_1" should be expanded to "/a_for_apple/subnode_1".
- */
- if (*path != '/') {
- const char *end = path + len;
-
- const char *next_slash;
- next_slash = dto_memchr(path, '/', end - path);
- if (!next_slash) next_slash = end;
-
- struct ufdt_node *aliases_node =
- ufdt_node_get_node_by_path(tree->root, "/aliases");
- aliases_node = ufdt_node_get_property_by_name_len(aliases_node, path,
- next_slash - path);
-
- int path_len = 0;
- const char *alias_path =
- ufdt_node_get_fdt_prop_data(aliases_node, &path_len);
-
- if (alias_path == NULL) {
- dto_error("Failed to find alias %s\n", path);
- return NULL;
- }
-
- struct ufdt_node *target_node =
- ufdt_node_get_node_by_path_len(tree->root, alias_path, path_len);
-
- return ufdt_node_get_node_by_path_len(target_node, next_slash,
- end - next_slash);
- }
- return ufdt_node_get_node_by_path_len(tree->root, path, len);
-}
-
-struct ufdt_node *ufdt_get_node_by_path(struct ufdt *tree, const char *path) {
- return ufdt_get_node_by_path_len(tree, path, dto_strlen(path));
-}
-
-struct ufdt_node *ufdt_get_node_by_phandle(struct ufdt *tree,
- uint32_t phandle) {
- struct ufdt_node *res = NULL;
- /*
- * Do binary search in phandle_table.data.
- * [s, e) means the possible range which contains target node.
- */
- int s = 0, e = tree->phandle_table.len;
- while (e - s > 1) {
- int mid = s + ((e - s) >> 1);
- uint32_t mid_phandle = tree->phandle_table.data[mid].phandle;
- if (phandle < mid_phandle)
- e = mid;
- else
- s = mid;
- }
- if (e - s > 0) {
- res = tree->phandle_table.data[s].node;
- }
- return res;
-}
-
-int merge_children(struct ufdt_node *node_a, struct ufdt_node *node_b) {
- int err = 0;
- struct ufdt_node *it;
- for (it = ((struct fdt_node_ufdt_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 (tag_of(cur_node) == FDT_BEGIN_NODE) {
- target_node = ufdt_node_get_subnode_by_name(node_a, name_of(cur_node));
- } else {
- target_node = ufdt_node_get_property_by_name(node_a, name_of(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 fdt_node_ufdt_node *)node_b)->child = NULL;
-
- return 0;
-}
-
-int merge_ufdt_into(struct ufdt_node *node_a, struct ufdt_node *node_b) {
- if (tag_of(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;
-}
-
-void ufdt_map(struct ufdt *tree, struct ufdt_node_closure closure) {
- ufdt_node_map(tree->root, closure);
-}
-
-static int count_phandle_node(struct ufdt_node *node) {
- if (node == NULL) return 0;
- if (tag_of(node) != FDT_BEGIN_NODE) return 0;
- int res = 0;
- if (ufdt_node_get_phandle(node) > 0) res++;
- struct ufdt_node **it;
- for_each_child(it, node) { res += count_phandle_node(*it); }
- return res;
-}
-
-static void set_phandle_table_entry(struct ufdt_node *node,
- struct phandle_table_entry *data,
- int *cur) {
- if (node == NULL || tag_of(node) != FDT_BEGIN_NODE) return;
- int ph = ufdt_node_get_phandle(node);
- if (ph > 0) {
- data[*cur].phandle = ph;
- data[*cur].node = node;
- (*cur)++;
- }
- struct ufdt_node **it;
- for_each_node(it, node) set_phandle_table_entry(*it, data, cur);
- return;
-}
-
-int phandle_table_entry_cmp(const void *pa, const void *pb) {
- uint32_t ph_a = ((const struct phandle_table_entry *)pa)->phandle;
- uint32_t ph_b = ((const struct phandle_table_entry *)pb)->phandle;
- if (ph_a < ph_b)
- return -1;
- else if (ph_a == ph_b)
- return 0;
- else
- return 1;
-}
-
-struct static_phandle_table build_phandle_table(struct ufdt *tree) {
- struct static_phandle_table res;
- res.len = count_phandle_node(tree->root);
- res.data = dto_malloc(sizeof(struct phandle_table_entry) * res.len);
- int cur = 0;
- set_phandle_table_entry(tree->root, res.data, &cur);
- dto_qsort(res.data, res.len, sizeof(struct phandle_table_entry),
- phandle_table_entry_cmp);
- return res;
-}
-
-struct ufdt *fdt_to_ufdt(void *fdtp, size_t fdt_size) {
- (void)(fdt_size); // unused parameter
-
- struct ufdt *res_tree = ufdt_construct(fdtp);
-
- int start_offset = fdt_path_offset(fdtp, "/");
- if (start_offset < 0) {
- res_tree->fdtp = NULL;
- return res_tree;
- }
-
- int end_offset;
- int start_tag = fdt_next_tag(fdtp, start_offset, &end_offset);
- res_tree->root = fdt_to_ufdt_tree(fdtp, start_offset, &end_offset, start_tag);
-
- res_tree->phandle_table = build_phandle_table(res_tree);
-
- return res_tree;
-}
-
-int ufdt_to_fdt(struct ufdt *tree, void *buf, int buf_size) {
- int err;
- err = fdt_create(buf, buf_size);
- if (err < 0) return -1;
-
- int n_mem_rsv = fdt_num_mem_rsv(tree->fdtp);
- for (int i = 0; i < n_mem_rsv; i++) {
- uint64_t addr, size;
- fdt_get_mem_rsv(tree->fdtp, i, &addr, &size);
- fdt_add_reservemap_entry(buf, addr, size);
- }
-
- err = fdt_finish_reservemap(buf);
- if (err < 0) return -1;
-
- /*
- * Obtains all props for later use because getting them from
- * FDT requires complicated manipulation.
- */
- struct ufdt_node_dict all_props = ufdt_node_dict_construct();
- err = output_ufdt_node_to_fdt(tree->root, buf, &all_props);
- if (err < 0) return -1;
-
- ufdt_node_dict_destruct(&all_props);
-
- err = fdt_finish(buf);
- if (err < 0) return -1;
-
- /*
- * IMPORTANT: fdt_totalsize(buf) might be less than buf_size
- * so this is needed to make use of remain spaces.
- */
- return fdt_open_into(buf, buf, buf_size);
-}