|
@@ -0,0 +1,642 @@
|
|
|
|
+From 5f84cb93eef9f8a8ff7f49d593893f252744d0fe Mon Sep 17 00:00:00 2001
|
|
|
|
+From: Pantelis Antoniou <[email protected]>
|
|
|
|
+Date: Wed, 26 Aug 2015 18:28:08 +0300
|
|
|
|
+Subject: [PATCH] scripts/dtc: Update to version with overlays
|
|
|
|
+
|
|
|
|
+Update to mainline dtc with overlay support
|
|
|
|
+
|
|
|
|
+Signed-off-by: Pantelis Antoniou <[email protected]>
|
|
|
|
+---
|
|
|
|
+ checks.c | 20 +++++-
|
|
|
|
+ dtc-lexer.l | 5 ++
|
|
|
|
+ dtc-parser.y | 54 ++++++++++++++--
|
|
|
|
+ dtc.c | 83 ++++++++++++++++++++++--
|
|
|
|
+ dtc.h | 13 +++-
|
|
|
|
+ livetree.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
+ treesource.c | 3 +
|
|
|
|
+ util.c | 2 +-
|
|
|
|
+ 8 files changed, 367 insertions(+), 15 deletions(-)
|
|
|
|
+
|
|
|
|
+diff --git a/checks.c b/checks.c
|
|
|
|
+index 3bf0fa4..af25c2b 100644
|
|
|
|
+--- a/checks.c
|
|
|
|
++++ b/checks.c
|
|
|
|
+@@ -465,8 +465,12 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
|
|
|
|
+
|
|
|
|
+ refnode = get_node_by_ref(dt, m->ref);
|
|
|
|
+ if (! refnode) {
|
|
|
|
+- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
|
|
|
|
+- m->ref);
|
|
|
|
++ if (!source_is_plugin)
|
|
|
|
++ FAIL(c, "Reference to non-existent node or "
|
|
|
|
++ "label \"%s\"\n", m->ref);
|
|
|
|
++ else /* mark the entry as unresolved */
|
|
|
|
++ *((cell_t *)(prop->val.val + m->offset)) =
|
|
|
|
++ cpu_to_fdt32(0xffffffff);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+@@ -559,7 +563,7 @@ static void check_reg_format(struct check *c, struct node *dt,
|
|
|
|
+ size_cells = node_size_cells(node->parent);
|
|
|
|
+ entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
|
|
|
+
|
|
|
|
+- if ((prop->val.len % entrylen) != 0)
|
|
|
|
++ if (!entrylen || (prop->val.len % entrylen) != 0)
|
|
|
|
+ FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
|
|
|
|
+ "(#address-cells == %d, #size-cells == %d)",
|
|
|
|
+ node->fullpath, prop->val.len, addr_cells, size_cells);
|
|
|
|
+@@ -651,6 +655,15 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
|
|
|
|
+ }
|
|
|
|
+ TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
|
|
|
|
+
|
|
|
|
++static void check_deprecated_plugin_syntax(struct check *c,
|
|
|
|
++ struct node *dt)
|
|
|
|
++{
|
|
|
|
++ if (deprecated_plugin_syntax_warning)
|
|
|
|
++ FAIL(c, "Use '/dts-v1/ /plugin/'; syntax. /dts-v1/; /plugin/; "
|
|
|
|
++ "is going to be removed in next versions");
|
|
|
|
++}
|
|
|
|
++TREE_WARNING(deprecated_plugin_syntax, NULL);
|
|
|
|
++
|
|
|
|
+ static struct check *check_table[] = {
|
|
|
|
+ &duplicate_node_names, &duplicate_property_names,
|
|
|
|
+ &node_name_chars, &node_name_format, &property_name_chars,
|
|
|
|
+@@ -668,6 +681,7 @@ static struct check *check_table[] = {
|
|
|
|
+
|
|
|
|
+ &avoid_default_addr_size,
|
|
|
|
+ &obsolete_chosen_interrupt_controller,
|
|
|
|
++ &deprecated_plugin_syntax,
|
|
|
|
+
|
|
|
|
+ &always_fail,
|
|
|
|
+ };
|
|
|
|
+diff --git a/dtc-lexer.l b/dtc-lexer.l
|
|
|
|
+index 0ee1caf..dd44ba2 100644
|
|
|
|
+--- a/dtc-lexer.l
|
|
|
|
++++ b/dtc-lexer.l
|
|
|
|
+@@ -113,6 +113,11 @@ static void lexical_error(const char *fmt, ...);
|
|
|
|
+ return DT_V1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
++<*>"/plugin/" {
|
|
|
|
++ DPRINT("Keyword: /plugin/\n");
|
|
|
|
++ return DT_PLUGIN;
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
+ <*>"/memreserve/" {
|
|
|
|
+ DPRINT("Keyword: /memreserve/\n");
|
|
|
|
+ BEGIN_DEFAULT();
|
|
|
|
+diff --git a/dtc-parser.y b/dtc-parser.y
|
|
|
|
+index ea57e0a..7d9652d 100644
|
|
|
|
+--- a/dtc-parser.y
|
|
|
|
++++ b/dtc-parser.y
|
|
|
|
+@@ -19,6 +19,7 @@
|
|
|
|
+ */
|
|
|
|
+ %{
|
|
|
|
+ #include <stdio.h>
|
|
|
|
++#include <inttypes.h>
|
|
|
|
+
|
|
|
|
+ #include "dtc.h"
|
|
|
|
+ #include "srcpos.h"
|
|
|
|
+@@ -52,9 +53,11 @@ extern bool treesource_error;
|
|
|
|
+ struct node *nodelist;
|
|
|
|
+ struct reserve_info *re;
|
|
|
|
+ uint64_t integer;
|
|
|
|
++ bool is_plugin;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ %token DT_V1
|
|
|
|
++%token DT_PLUGIN
|
|
|
|
+ %token DT_MEMRESERVE
|
|
|
|
+ %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
|
|
|
|
+ %token DT_BITS
|
|
|
|
+@@ -71,6 +74,7 @@ extern bool treesource_error;
|
|
|
|
+
|
|
|
|
+ %type <data> propdata
|
|
|
|
+ %type <data> propdataprefix
|
|
|
|
++%type <is_plugin> plugindecl
|
|
|
|
+ %type <re> memreserve
|
|
|
|
+ %type <re> memreserves
|
|
|
|
+ %type <array> arrayprefix
|
|
|
|
+@@ -101,10 +105,39 @@ extern bool treesource_error;
|
|
|
|
+ %%
|
|
|
|
+
|
|
|
|
+ sourcefile:
|
|
|
|
+- DT_V1 ';' memreserves devicetree
|
|
|
|
++ basesource
|
|
|
|
++ | pluginsource
|
|
|
|
++ ;
|
|
|
|
++
|
|
|
|
++basesource:
|
|
|
|
++ DT_V1 ';' plugindecl memreserves devicetree
|
|
|
|
++ {
|
|
|
|
++ source_is_plugin = $3;
|
|
|
|
++ if (source_is_plugin)
|
|
|
|
++ deprecated_plugin_syntax_warning = true;
|
|
|
|
++ the_boot_info = build_boot_info($4, $5,
|
|
|
|
++ guess_boot_cpuid($5));
|
|
|
|
++ }
|
|
|
|
++ ;
|
|
|
|
++
|
|
|
|
++plugindecl:
|
|
|
|
++ /* empty */
|
|
|
|
++ {
|
|
|
|
++ $$ = false;
|
|
|
|
++ }
|
|
|
|
++ | DT_PLUGIN ';'
|
|
|
|
++ {
|
|
|
|
++ $$ = true;
|
|
|
|
++ }
|
|
|
|
++ ;
|
|
|
|
++
|
|
|
|
++pluginsource:
|
|
|
|
++ DT_V1 DT_PLUGIN ';' memreserves devicetree
|
|
|
|
+ {
|
|
|
|
+- the_boot_info = build_boot_info($3, $4,
|
|
|
|
+- guess_boot_cpuid($4));
|
|
|
|
++ source_is_plugin = true;
|
|
|
|
++ deprecated_plugin_syntax_warning = false;
|
|
|
|
++ the_boot_info = build_boot_info($4, $5,
|
|
|
|
++ guess_boot_cpuid($5));
|
|
|
|
+ }
|
|
|
|
+ ;
|
|
|
|
+
|
|
|
|
+@@ -144,10 +177,14 @@ devicetree:
|
|
|
|
+ {
|
|
|
|
+ struct node *target = get_node_by_ref($1, $2);
|
|
|
|
+
|
|
|
|
+- if (target)
|
|
|
|
++ if (target) {
|
|
|
|
+ merge_nodes(target, $3);
|
|
|
|
+- else
|
|
|
|
+- ERROR(&@2, "Label or path %s not found", $2);
|
|
|
|
++ } else {
|
|
|
|
++ if (symbol_fixup_support)
|
|
|
|
++ add_orphan_node($1, $3, $2);
|
|
|
|
++ else
|
|
|
|
++ ERROR(&@2, "Label or path %s not found", $2);
|
|
|
|
++ }
|
|
|
|
+ $$ = $1;
|
|
|
|
+ }
|
|
|
|
+ | devicetree DT_DEL_NODE DT_REF ';'
|
|
|
|
+@@ -162,6 +199,11 @@ devicetree:
|
|
|
|
+
|
|
|
|
+ $$ = $1;
|
|
|
|
+ }
|
|
|
|
++ | /* empty */
|
|
|
|
++ {
|
|
|
|
++ /* build empty node */
|
|
|
|
++ $$ = name_node(build_node(NULL, NULL), "");
|
|
|
|
++ }
|
|
|
|
+ ;
|
|
|
|
+
|
|
|
|
+ nodedef:
|
|
|
|
+diff --git a/dtc.c b/dtc.c
|
|
|
|
+index 8c4add6..ee37be9 100644
|
|
|
|
+--- a/dtc.c
|
|
|
|
++++ b/dtc.c
|
|
|
|
+@@ -18,6 +18,8 @@
|
|
|
|
+ * USA
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
++#include <sys/stat.h>
|
|
|
|
++
|
|
|
|
+ #include "dtc.h"
|
|
|
|
+ #include "srcpos.h"
|
|
|
|
+
|
|
|
|
+@@ -29,6 +31,8 @@ int reservenum; /* Number of memory reservation slots */
|
|
|
|
+ int minsize; /* Minimum blob size */
|
|
|
|
+ int padsize; /* Additional padding to blob */
|
|
|
|
+ int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
|
|
|
|
++int symbol_fixup_support;
|
|
|
|
++int auto_label_aliases;
|
|
|
|
+
|
|
|
|
+ static void fill_fullpaths(struct node *tree, const char *prefix)
|
|
|
|
+ {
|
|
|
|
+@@ -51,7 +55,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
|
|
|
|
+ #define FDT_VERSION(version) _FDT_VERSION(version)
|
|
|
|
+ #define _FDT_VERSION(version) #version
|
|
|
|
+ static const char usage_synopsis[] = "dtc [options] <input file>";
|
|
|
|
+-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
|
|
|
|
++static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:@Ahv";
|
|
|
|
+ static struct option const usage_long_opts[] = {
|
|
|
|
+ {"quiet", no_argument, NULL, 'q'},
|
|
|
|
+ {"in-format", a_argument, NULL, 'I'},
|
|
|
|
+@@ -69,6 +73,8 @@ static struct option const usage_long_opts[] = {
|
|
|
|
+ {"phandle", a_argument, NULL, 'H'},
|
|
|
|
+ {"warning", a_argument, NULL, 'W'},
|
|
|
|
+ {"error", a_argument, NULL, 'E'},
|
|
|
|
++ {"symbols", no_argument, NULL, '@'},
|
|
|
|
++ {"auto-alias", no_argument, NULL, 'A'},
|
|
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
|
|
+ {"version", no_argument, NULL, 'v'},
|
|
|
|
+ {NULL, no_argument, NULL, 0x0},
|
|
|
|
+@@ -99,16 +105,63 @@ static const char * const usage_opts_help[] = {
|
|
|
|
+ "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
|
|
|
|
+ "\n\tEnable/disable warnings (prefix with \"no-\")",
|
|
|
|
+ "\n\tEnable/disable errors (prefix with \"no-\")",
|
|
|
|
++ "\n\tEnable symbols/fixup support",
|
|
|
|
++ "\n\tEnable auto-alias of labels",
|
|
|
|
+ "\n\tPrint this help and exit",
|
|
|
|
+ "\n\tPrint version and exit",
|
|
|
|
+ NULL,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
++static const char *guess_type_by_name(const char *fname, const char *fallback)
|
|
|
|
++{
|
|
|
|
++ const char *s;
|
|
|
|
++
|
|
|
|
++ s = strrchr(fname, '.');
|
|
|
|
++ if (s == NULL)
|
|
|
|
++ return fallback;
|
|
|
|
++ if (!strcasecmp(s, ".dts"))
|
|
|
|
++ return "dts";
|
|
|
|
++ if (!strcasecmp(s, ".dtb"))
|
|
|
|
++ return "dtb";
|
|
|
|
++ return fallback;
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
++static const char *guess_input_format(const char *fname, const char *fallback)
|
|
|
|
++{
|
|
|
|
++ struct stat statbuf;
|
|
|
|
++ uint32_t magic;
|
|
|
|
++ FILE *f;
|
|
|
|
++
|
|
|
|
++ if (stat(fname, &statbuf) != 0)
|
|
|
|
++ return fallback;
|
|
|
|
++
|
|
|
|
++ if (S_ISDIR(statbuf.st_mode))
|
|
|
|
++ return "fs";
|
|
|
|
++
|
|
|
|
++ if (!S_ISREG(statbuf.st_mode))
|
|
|
|
++ return fallback;
|
|
|
|
++
|
|
|
|
++ f = fopen(fname, "r");
|
|
|
|
++ if (f == NULL)
|
|
|
|
++ return fallback;
|
|
|
|
++ if (fread(&magic, 4, 1, f) != 1) {
|
|
|
|
++ fclose(f);
|
|
|
|
++ return fallback;
|
|
|
|
++ }
|
|
|
|
++ fclose(f);
|
|
|
|
++
|
|
|
|
++ magic = fdt32_to_cpu(magic);
|
|
|
|
++ if (magic == FDT_MAGIC)
|
|
|
|
++ return "dtb";
|
|
|
|
++
|
|
|
|
++ return guess_type_by_name(fname, fallback);
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
+ int main(int argc, char *argv[])
|
|
|
|
+ {
|
|
|
|
+ struct boot_info *bi;
|
|
|
|
+- const char *inform = "dts";
|
|
|
|
+- const char *outform = "dts";
|
|
|
|
++ const char *inform = NULL;
|
|
|
|
++ const char *outform = NULL;
|
|
|
|
+ const char *outname = "-";
|
|
|
|
+ const char *depname = NULL;
|
|
|
|
+ bool force = false, sort = false;
|
|
|
|
+@@ -186,7 +239,12 @@ int main(int argc, char *argv[])
|
|
|
|
+ case 'E':
|
|
|
|
+ parse_checks_option(false, true, optarg);
|
|
|
|
+ break;
|
|
|
|
+-
|
|
|
|
++ case '@':
|
|
|
|
++ symbol_fixup_support = 1;
|
|
|
|
++ break;
|
|
|
|
++ case 'A':
|
|
|
|
++ auto_label_aliases = 1;
|
|
|
|
++ break;
|
|
|
|
+ case 'h':
|
|
|
|
+ usage(NULL);
|
|
|
|
+ default:
|
|
|
|
+@@ -213,6 +271,17 @@ int main(int argc, char *argv[])
|
|
|
|
+ fprintf(depfile, "%s:", outname);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
++ if (inform == NULL)
|
|
|
|
++ inform = guess_input_format(arg, "dts");
|
|
|
|
++ if (outform == NULL) {
|
|
|
|
++ outform = guess_type_by_name(outname, NULL);
|
|
|
|
++ if (outform == NULL) {
|
|
|
|
++ if (streq(inform, "dts"))
|
|
|
|
++ outform = "dtb";
|
|
|
|
++ else
|
|
|
|
++ outform = "dts";
|
|
|
|
++ }
|
|
|
|
++ }
|
|
|
|
+ if (streq(inform, "dts"))
|
|
|
|
+ bi = dt_from_source(arg);
|
|
|
|
+ else if (streq(inform, "fs"))
|
|
|
|
+@@ -236,6 +305,12 @@ int main(int argc, char *argv[])
|
|
|
|
+ if (sort)
|
|
|
|
+ sort_tree(bi);
|
|
|
|
+
|
|
|
|
++ if (symbol_fixup_support || auto_label_aliases)
|
|
|
|
++ generate_label_node(bi->dt, bi->dt);
|
|
|
|
++
|
|
|
|
++ if (symbol_fixup_support)
|
|
|
|
++ generate_fixups_node(bi->dt, bi->dt);
|
|
|
|
++
|
|
|
|
+ if (streq(outname, "-")) {
|
|
|
|
+ outf = stdout;
|
|
|
|
+ } else {
|
|
|
|
+diff --git a/dtc.h b/dtc.h
|
|
|
|
+index 56212c8..d025111 100644
|
|
|
|
+--- a/dtc.h
|
|
|
|
++++ b/dtc.h
|
|
|
|
+@@ -20,7 +20,7 @@
|
|
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
+ * USA
|
|
|
|
+ */
|
|
|
|
+-
|
|
|
|
++#define _GNU_SOURCE
|
|
|
|
+ #include <stdio.h>
|
|
|
|
+ #include <string.h>
|
|
|
|
+ #include <stdlib.h>
|
|
|
|
+@@ -54,6 +54,14 @@ extern int reservenum; /* Number of memory reservation slots */
|
|
|
|
+ extern int minsize; /* Minimum blob size */
|
|
|
|
+ extern int padsize; /* Additional padding to blob */
|
|
|
|
+ extern int phandle_format; /* Use linux,phandle or phandle properties */
|
|
|
|
++extern int symbol_fixup_support;/* enable symbols & fixup support */
|
|
|
|
++extern int auto_label_aliases; /* auto generate labels -> aliases */
|
|
|
|
++
|
|
|
|
++/*
|
|
|
|
++ * Tree source globals
|
|
|
|
++ */
|
|
|
|
++extern bool source_is_plugin;
|
|
|
|
++extern bool deprecated_plugin_syntax_warning;
|
|
|
|
+
|
|
|
|
+ #define PHANDLE_LEGACY 0x1
|
|
|
|
+ #define PHANDLE_EPAPR 0x2
|
|
|
|
+@@ -194,6 +202,7 @@ struct node *build_node_delete(void);
|
|
|
|
+ struct node *name_node(struct node *node, char *name);
|
|
|
|
+ struct node *chain_node(struct node *first, struct node *list);
|
|
|
|
+ struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
|
|
|
++void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
|
|
|
|
+
|
|
|
|
+ void add_property(struct node *node, struct property *prop);
|
|
|
|
+ void delete_property_by_name(struct node *node, char *name);
|
|
|
|
+@@ -244,6 +253,8 @@ struct boot_info {
|
|
|
|
+ struct boot_info *build_boot_info(struct reserve_info *reservelist,
|
|
|
|
+ struct node *tree, uint32_t boot_cpuid_phys);
|
|
|
|
+ void sort_tree(struct boot_info *bi);
|
|
|
|
++void generate_label_node(struct node *node, struct node *dt);
|
|
|
|
++void generate_fixups_node(struct node *node, struct node *dt);
|
|
|
|
+
|
|
|
|
+ /* Checks */
|
|
|
|
+
|
|
|
|
+diff --git a/livetree.c b/livetree.c
|
|
|
|
+index e229b84..1ef9fc4 100644
|
|
|
|
+--- a/livetree.c
|
|
|
|
++++ b/livetree.c
|
|
|
|
+@@ -216,6 +216,34 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
|
|
|
+ return old_node;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
++void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
|
|
|
++{
|
|
|
|
++ static unsigned int next_orphan_fragment = 0;
|
|
|
|
++ struct node *ovl = xmalloc(sizeof(*ovl));
|
|
|
|
++ struct property *p;
|
|
|
|
++ struct data d = empty_data;
|
|
|
|
++ char *name;
|
|
|
|
++ int ret;
|
|
|
|
++
|
|
|
|
++ memset(ovl, 0, sizeof(*ovl));
|
|
|
|
++
|
|
|
|
++ d = data_add_marker(d, REF_PHANDLE, ref);
|
|
|
|
++ d = data_append_integer(d, 0xffffffff, 32);
|
|
|
|
++
|
|
|
|
++ p = build_property("target", d);
|
|
|
|
++ add_property(ovl, p);
|
|
|
|
++
|
|
|
|
++ ret = asprintf(&name, "fragment@%u",
|
|
|
|
++ next_orphan_fragment++);
|
|
|
|
++ if (ret == -1)
|
|
|
|
++ die("asprintf() failed\n");
|
|
|
|
++ name_node(ovl, name);
|
|
|
|
++ name_node(new_node, "__overlay__");
|
|
|
|
++
|
|
|
|
++ add_child(dt, ovl);
|
|
|
|
++ add_child(ovl, new_node);
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
+ struct node *chain_node(struct node *first, struct node *list)
|
|
|
|
+ {
|
|
|
|
+ assert(first->next_sibling == NULL);
|
|
|
|
+@@ -709,3 +737,177 @@ void sort_tree(struct boot_info *bi)
|
|
|
|
+ sort_reserve_entries(bi);
|
|
|
|
+ sort_node(bi->dt);
|
|
|
|
+ }
|
|
|
|
++
|
|
|
|
++void generate_label_node(struct node *node, struct node *dt)
|
|
|
|
++{
|
|
|
|
++ struct node *c, *an;
|
|
|
|
++ struct property *p;
|
|
|
|
++ struct label *l;
|
|
|
|
++ int has_label;
|
|
|
|
++ char *gen_node_name;
|
|
|
|
++
|
|
|
|
++ if (auto_label_aliases)
|
|
|
|
++ gen_node_name = "aliases";
|
|
|
|
++ else
|
|
|
|
++ gen_node_name = "__symbols__";
|
|
|
|
++
|
|
|
|
++ /* Make sure the label isn't already there */
|
|
|
|
++ has_label = 0;
|
|
|
|
++ for_each_label(node->labels, l) {
|
|
|
|
++ has_label = 1;
|
|
|
|
++ break;
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ if (has_label) {
|
|
|
|
++
|
|
|
|
++ /* an is the aliases/__symbols__ node */
|
|
|
|
++ an = get_subnode(dt, gen_node_name);
|
|
|
|
++ /* if no node exists, create it */
|
|
|
|
++ if (!an) {
|
|
|
|
++ an = build_node(NULL, NULL);
|
|
|
|
++ name_node(an, gen_node_name);
|
|
|
|
++ add_child(dt, an);
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ /* 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,
|
|
|
|
++ gen_node_name);
|
|
|
|
++ continue;
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ /* insert it */
|
|
|
|
++ p = build_property(l->label,
|
|
|
|
++ data_copy_escape_string(node->fullpath,
|
|
|
|
++ strlen(node->fullpath)));
|
|
|
|
++ add_property(an, p);
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ /* force allocation of a phandle for this node */
|
|
|
|
++ if (symbol_fixup_support)
|
|
|
|
++ (void)get_node_phandle(dt, node);
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ for_each_child(node, c)
|
|
|
|
++ generate_label_node(c, dt);
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
++static void add_fixup_entry(struct node *dt, struct node *node,
|
|
|
|
++ struct property *prop, struct marker *m)
|
|
|
|
++{
|
|
|
|
++ struct node *fn; /* local fixup node */
|
|
|
|
++ struct property *p;
|
|
|
|
++ char *fixups_name = "__fixups__";
|
|
|
|
++ struct data d;
|
|
|
|
++ char *entry;
|
|
|
|
++ int ret;
|
|
|
|
++
|
|
|
|
++ /* fn is the node we're putting entries in */
|
|
|
|
++ fn = get_subnode(dt, fixups_name);
|
|
|
|
++ /* if no node exists, create it */
|
|
|
|
++ if (!fn) {
|
|
|
|
++ fn = build_node(NULL, NULL);
|
|
|
|
++ name_node(fn, fixups_name);
|
|
|
|
++ add_child(dt, fn);
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ ret = asprintf(&entry, "%s:%s:%u",
|
|
|
|
++ node->fullpath, prop->name, m->offset);
|
|
|
|
++ if (ret == -1)
|
|
|
|
++ die("asprintf() failed\n");
|
|
|
|
++
|
|
|
|
++ p = get_property(fn, m->ref);
|
|
|
|
++ d = data_append_data(p ? p->val : empty_data, entry, strlen(entry) + 1);
|
|
|
|
++ if (!p)
|
|
|
|
++ add_property(fn, build_property(m->ref, d));
|
|
|
|
++ else
|
|
|
|
++ p->val = d;
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
++static void add_local_fixup_entry(struct node *dt, struct node *node,
|
|
|
|
++ struct property *prop, struct marker *m,
|
|
|
|
++ struct node *refnode)
|
|
|
|
++{
|
|
|
|
++ struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
|
|
|
|
++ struct property *p;
|
|
|
|
++ struct data d;
|
|
|
|
++ char *local_fixups_name = "__local_fixups__";
|
|
|
|
++ char *s, *e, *comp;
|
|
|
|
++ int len;
|
|
|
|
++
|
|
|
|
++ /* fn is the node we're putting entries in */
|
|
|
|
++ lfn = get_subnode(dt, local_fixups_name);
|
|
|
|
++ /* if no node exists, create it */
|
|
|
|
++ if (!lfn) {
|
|
|
|
++ lfn = build_node(NULL, NULL);
|
|
|
|
++ name_node(lfn, local_fixups_name);
|
|
|
|
++ add_child(dt, lfn);
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ /* walk the path components creating nodes if they don't exist */
|
|
|
|
++ comp = NULL;
|
|
|
|
++ /* start skipping the first / */
|
|
|
|
++ s = node->fullpath + 1;
|
|
|
|
++ wn = lfn;
|
|
|
|
++ while (*s) {
|
|
|
|
++ /* retrieve path component */
|
|
|
|
++ e = strchr(s, '/');
|
|
|
|
++ if (e == NULL)
|
|
|
|
++ e = s + strlen(s);
|
|
|
|
++ len = e - s;
|
|
|
|
++ comp = xrealloc(comp, len + 1);
|
|
|
|
++ memcpy(comp, s, len);
|
|
|
|
++ comp[len] = '\0';
|
|
|
|
++
|
|
|
|
++ /* if no node exists, create it */
|
|
|
|
++ nwn = get_subnode(wn, comp);
|
|
|
|
++ if (!nwn) {
|
|
|
|
++ nwn = build_node(NULL, NULL);
|
|
|
|
++ name_node(nwn, strdup(comp));
|
|
|
|
++ add_child(wn, nwn);
|
|
|
|
++ }
|
|
|
|
++ wn = nwn;
|
|
|
|
++
|
|
|
|
++ /* last path component */
|
|
|
|
++ if (!*e)
|
|
|
|
++ break;
|
|
|
|
++
|
|
|
|
++ /* next path component */
|
|
|
|
++ s = e + 1;
|
|
|
|
++ }
|
|
|
|
++ free(comp);
|
|
|
|
++
|
|
|
|
++ p = get_property(wn, prop->name);
|
|
|
|
++ d = data_append_cell(p ? p->val : empty_data, (cell_t)m->offset);
|
|
|
|
++ if (!p)
|
|
|
|
++ add_property(wn, build_property(prop->name, d));
|
|
|
|
++ else
|
|
|
|
++ p->val = d;
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
++void generate_fixups_node(struct node *node, struct node *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(dt, node, prop, m);
|
|
|
|
++ else
|
|
|
|
++ add_local_fixup_entry(dt, node, prop, m,
|
|
|
|
++ refnode);
|
|
|
|
++ }
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
++ for_each_child(node, c)
|
|
|
|
++ generate_fixups_node(c, dt);
|
|
|
|
++}
|
|
|
|
+diff --git a/treesource.c b/treesource.c
|
|
|
|
+index a55d1d1..e1d6657 100644
|
|
|
|
+--- a/treesource.c
|
|
|
|
++++ b/treesource.c
|
|
|
|
+@@ -28,6 +28,9 @@ extern YYLTYPE yylloc;
|
|
|
|
+ struct boot_info *the_boot_info;
|
|
|
|
+ bool treesource_error;
|
|
|
|
+
|
|
|
|
++bool source_is_plugin;
|
|
|
|
++bool deprecated_plugin_syntax_warning;
|
|
|
|
++
|
|
|
|
+ struct boot_info *dt_from_source(const char *fname)
|
|
|
|
+ {
|
|
|
|
+ the_boot_info = NULL;
|
|
|
|
+diff --git a/util.c b/util.c
|
|
|
|
+index 9d65226..cbb945b 100644
|
|
|
|
+--- a/util.c
|
|
|
|
++++ b/util.c
|
|
|
|
+@@ -349,7 +349,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
|
|
|
|
+ void utilfdt_print_data(const char *data, int len)
|
|
|
|
+ {
|
|
|
|
+ int i;
|
|
|
|
+- const char *p = data;
|
|
|
|
+ const char *s;
|
|
|
|
+
|
|
|
|
+ /* no data, don't print */
|
|
|
|
+@@ -376,6 +375,7 @@ void utilfdt_print_data(const char *data, int len)
|
|
|
|
+ i < (len - 1) ? " " : "");
|
|
|
|
+ printf(">");
|
|
|
|
+ } else {
|
|
|
|
++ const unsigned char *p = (const unsigned char *)data;
|
|
|
|
+ printf(" = [");
|
|
|
|
+ for (i = 0; i < len; i++)
|
|
|
|
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
|
|
|
|
+--
|
|
|
|
+2.7.0
|
|
|
|
+
|