From 6f05afcbb031722ec1eff77dde188ff2edf8940e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 4 Jan 2017 10:45:20 -0600 Subject: scripts/dtc: Update to upstream version 0931cea3ba20 Sync to upstream dtc commit 0931cea3ba20 ("dtc: fdtdump: check fdt if not in scanning mode"). In particular, this pulls in dtc overlay support. This adds the following commits from upstream: f88865469b65 dtc: Fix memory leak in character literal parsing 00fbb8696b66 Rename boot_info 1ef86ad2c24f dtc: Clean up /dts-v1/ and /plugin/ handling in grammar e3c769aa9c16 dtc: Don't always generate __symbols__ for plugins c96cb3c0169e tests: Don't use -@ on plugin de/recompile tests 66381538ce24 tests: Remove "suppression of fixups" tests ba765b273f0f tests: Clarify dtc overlay tests 6ea8cd944fcd tests: More thorough tests of libfdt overlay application without dtc 7d8ef6e1db97 tests: Correct fdt handling of overlays without fixups and base trees without symbols b4dc0ed8b127 tests: Fix double expansion bugs in test code 3ea879dc0c8f tests: Split overlay tests into those with do/don't exercise dtc plugin generation 47b4d66a2f11 tests: Test auto-alias generation on base tree, not overlay 72e1ad811523 tests: Make overlay/plugin tests unconditional e7b3c3b5951b tests: Add overlay tests 9637e3f772a9 tests: Add check_path test 20f29d8d41f6 dtc: Plugin and fixup support a2c92cac53f8 dtc: Document the dynamic plugin internals 8f70ac39801d checks: Pass boot_info instead of root node ea10f953878f libfdt: add missing errors to fdt_strerror() daa75e8fa594 libfdt: fix fdt_stringlist_search() e28eff5b787a libfdt: fix fdt_stringlist_count() ae97c7722840 tests: overlay: Rename the device tree blobs to be more explicit 96162d2bd9cb tests: overlay: Add test suffix to the compiled blobs 5ce8634733b7 libfdt: Add fdt_overlay_apply to the exported symbols 804a9db90ad2 fdt: strerr: Remove spurious BADOVERLAY e8c3a1a493fa tests: overlay: Move back the bad fixup tests 7a72d89d3f81 libfdt: overlay: Fix symbols and fixups nodes condition cabbaa972cdd libfdt: overlay: Report a bad overlay for mismatching local fixups deb0a5c1aeaa libfdt: Add BADPHANDLE error string 7b7a6be9ba15 libfdt: Don't use 'index' as a local variable name aea8860d831e tests: Add tests cases for the overlay code 0cdd06c5135b libfdt: Add overlay application function 39240cc865cf libfdt: Extend the reach of FDT_ERR_BADPHANDLE 4aa3a6f5e6d9 libfdt: Add new errors for the overlay code 6d1832c9e64b dtc: Remove "home page" link 45fd440a9561 Fix some typing errors in libfdt.h and livetree.c a59be4939c13 Merge tag 'v1.4.2' a34bb721caca dtc: Fix assorted problems in the testcases for the -a option 874f40588d3e Implement the -a option to pad dtb aligned ec02b34c05be dtc: Makefile improvements for release uploading 1ed45d40a137 dtc: Bump version to 1.4.2 36fd7331fb11 libfdt: simplify fdt_del_mem_rsv() d877364e4a0f libfdt: Add fdt_setprop_inplace_namelen_partial 3e9037aaad44 libfdt: Add fdt_getprop_namelen_w 84e0e1346c68 libfdt: Add max phandle retrieval function d29126c90acb libfdt: Add iterator over properties 902d0f0953d0 libfdt: Add a subnodes iterator macro c539075ba8ba fdtput.c: Fix memory leak. f79ddb83e185 fdtget.c: Fix memory leak 1074ee54b63f convert-dtsv0-lexer.l: fix memory leak e24d39a024e6 fdtdump.c: make sure size_t argument to memchr is always unsigned. 44a59713cf05 Remove unused srcpos_dump() function cb9241ae3453 DTC: Fix memory leak on flatname. 1ee0ae24ea09 Simplify check field and macro names 9d97527a8621 Remove property check functions 2e709d158e11 Remove tree check functions c4cb12e193e3 Alter grammar to allow multiple /dts-v1/ tags d71d25d76012 Use xasprintf() in srcpos 9dc404958e9c util: Add xasprintf portable asprintf variant beef80b8b55f Correct a missing space in a fdt_header cast 68d43cec1253 Correct line lengths in libfdt.h b0dbceafd49a Correct space-after-tab in libfdt.h Signed-off-by: Rob Herring --- scripts/dtc/livetree.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 283 insertions(+), 16 deletions(-) (limited to 'scripts/dtc/livetree.c') diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index e229b84432f9..afa2f67b142a 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -204,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) } } - /* if no collision occured, add child to the old node. */ + /* if no collision occurred, add child to the old node. */ if (new_child) add_child(old_node, new_child); } @@ -296,6 +296,23 @@ void delete_node(struct node *node) delete_labels(&node->labels); } +void append_to_property(struct node *node, + char *name, const void *data, int len) +{ + struct data d; + struct property *p; + + p = get_property(node, name); + if (p) { + d = data_append_data(p->val, data, len); + p->val = d; + } else { + d = data_append_data(empty_data, data, len); + p = build_property(name, d); + add_property(node, p); + } +} + struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) { struct reserve_info *new = xmalloc(sizeof(*new)); @@ -335,17 +352,19 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, return list; } -struct boot_info *build_boot_info(struct reserve_info *reservelist, - struct node *tree, uint32_t boot_cpuid_phys) +struct dt_info *build_dt_info(unsigned int dtsflags, + struct reserve_info *reservelist, + struct node *tree, uint32_t boot_cpuid_phys) { - struct boot_info *bi; + struct dt_info *dti; - bi = xmalloc(sizeof(*bi)); - bi->reservelist = reservelist; - bi->dt = tree; - bi->boot_cpuid_phys = boot_cpuid_phys; + dti = xmalloc(sizeof(*dti)); + dti->dtsflags = dtsflags; + dti->reservelist = reservelist; + dti->dt = tree; + dti->boot_cpuid_phys = boot_cpuid_phys; - return bi; + return dti; } /* @@ -592,12 +611,12 @@ static int cmp_reserve_info(const void *ax, const void *bx) return 0; } -static void sort_reserve_entries(struct boot_info *bi) +static void sort_reserve_entries(struct dt_info *dti) { struct reserve_info *ri, **tbl; int n = 0, i = 0; - for (ri = bi->reservelist; + for (ri = dti->reservelist; ri; ri = ri->next) n++; @@ -607,14 +626,14 @@ static void sort_reserve_entries(struct boot_info *bi) tbl = xmalloc(n * sizeof(*tbl)); - for (ri = bi->reservelist; + for (ri = dti->reservelist; ri; ri = ri->next) tbl[i++] = ri; qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); - bi->reservelist = tbl[0]; + dti->reservelist = tbl[0]; for (i = 0; i < (n-1); i++) tbl[i]->next = tbl[i+1]; tbl[n-1]->next = NULL; @@ -704,8 +723,256 @@ static void sort_node(struct node *node) sort_node(c); } -void sort_tree(struct boot_info *bi) +void sort_tree(struct dt_info *dti) +{ + sort_reserve_entries(dti); + sort_node(dti->dt); +} + +/* utility helper to avoid code duplication */ +static struct node *build_and_name_child_node(struct node *parent, char *name) +{ + struct node *node; + + node = build_node(NULL, NULL); + name_node(node, xstrdup(name)); + add_child(parent, node); + + return node; +} + +static struct node *build_root_node(struct node *dt, char *name) +{ + struct node *an; + + an = get_subnode(dt, name); + if (!an) + an = build_and_name_child_node(dt, name); + + if (!an) + die("Could not build root node /%s\n", name); + + return an; +} + +static bool any_label_tree(struct dt_info *dti, struct node *node) +{ + struct node *c; + + if (node->labels) + return true; + + for_each_child(node, c) + if (any_label_tree(dti, c)) + return true; + + return false; +} + +static void generate_label_tree_internal(struct dt_info *dti, + struct node *an, struct node *node, + bool allocph) +{ + struct node *dt = dti->dt; + struct node *c; + struct property *p; + struct label *l; + + /* if there are labels */ + if (node->labels) { + + /* now add the label in the node */ + for_each_label(node->labels, l) { + + /* check whether the label already exists */ + p = get_property(an, l->label); + if (p) { + fprintf(stderr, "WARNING: label %s already" + " exists in /%s", l->label, + an->name); + continue; + } + + /* insert it */ + p = build_property(l->label, + data_copy_mem(node->fullpath, + strlen(node->fullpath) + 1)); + add_property(an, p); + } + + /* force allocation of a phandle for this node */ + if (allocph) + (void)get_node_phandle(dt, node); + } + + for_each_child(node, c) + generate_label_tree_internal(dti, an, c, allocph); +} + +static bool any_fixup_tree(struct dt_info *dti, struct node *node) +{ + struct node *c; + struct property *prop; + struct marker *m; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + if (!get_node_by_ref(dti->dt, m->ref)) + return true; + } + } + + for_each_child(node, c) { + if (any_fixup_tree(dti, c)) + return true; + } + + return false; +} + +static void add_fixup_entry(struct dt_info *dti, struct node *fn, + struct node *node, struct property *prop, + struct marker *m) { - sort_reserve_entries(bi); - sort_node(bi->dt); + char *entry; + + /* m->ref can only be a REF_PHANDLE, but check anyway */ + assert(m->type == REF_PHANDLE); + + /* there shouldn't be any ':' in the arguments */ + if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) + die("arguments should not contain ':'\n"); + + xasprintf(&entry, "%s:%s:%u", + node->fullpath, prop->name, m->offset); + append_to_property(fn, m->ref, entry, strlen(entry) + 1); +} + +static void generate_fixups_tree_internal(struct dt_info *dti, + struct node *fn, + struct node *node) +{ + struct node *dt = dti->dt; + struct node *c; + struct property *prop; + struct marker *m; + struct node *refnode; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + refnode = get_node_by_ref(dt, m->ref); + if (!refnode) + add_fixup_entry(dti, fn, node, prop, m); + } + } + + for_each_child(node, c) + generate_fixups_tree_internal(dti, fn, c); +} + +static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) +{ + struct node *c; + struct property *prop; + struct marker *m; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + if (get_node_by_ref(dti->dt, m->ref)) + return true; + } + } + + for_each_child(node, c) { + if (any_local_fixup_tree(dti, c)) + return true; + } + + return false; +} + +static void add_local_fixup_entry(struct dt_info *dti, + struct node *lfn, struct node *node, + struct property *prop, struct marker *m, + struct node *refnode) +{ + struct node *wn, *nwn; /* local fixup node, walk node, new */ + uint32_t value_32; + char **compp; + int i, depth; + + /* walk back retreiving depth */ + depth = 0; + for (wn = node; wn; wn = wn->parent) + depth++; + + /* allocate name array */ + compp = xmalloc(sizeof(*compp) * depth); + + /* store names in the array */ + for (wn = node, i = depth - 1; wn; wn = wn->parent, i--) + compp[i] = wn->name; + + /* walk the path components creating nodes if they don't exist */ + for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { + /* if no node exists, create it */ + nwn = get_subnode(wn, compp[i]); + if (!nwn) + nwn = build_and_name_child_node(wn, compp[i]); + } + + free(compp); + + value_32 = cpu_to_fdt32(m->offset); + append_to_property(wn, prop->name, &value_32, sizeof(value_32)); +} + +static void generate_local_fixups_tree_internal(struct dt_info *dti, + struct node *lfn, + struct node *node) +{ + struct node *dt = dti->dt; + struct node *c; + struct property *prop; + struct marker *m; + struct node *refnode; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + refnode = get_node_by_ref(dt, m->ref); + if (refnode) + add_local_fixup_entry(dti, lfn, node, prop, m, refnode); + } + } + + for_each_child(node, c) + generate_local_fixups_tree_internal(dti, lfn, c); +} + +void generate_label_tree(struct dt_info *dti, char *name, bool allocph) +{ + if (!any_label_tree(dti, dti->dt)) + return; + generate_label_tree_internal(dti, build_root_node(dti->dt, name), + dti->dt, allocph); +} + +void generate_fixups_tree(struct dt_info *dti, char *name) +{ + if (!any_fixup_tree(dti, dti->dt)) + return; + generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), + dti->dt); +} + +void generate_local_fixups_tree(struct dt_info *dti, char *name) +{ + if (!any_local_fixup_tree(dti, dti->dt)) + return; + generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), + dti->dt); } -- cgit v1.2.3