mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	Add patch with the DT overlay support into the DTC package. Signed-off-by: Marek Vasut <marex@denx.de>
		
			
				
	
	
		
			643 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			643 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 5f84cb93eef9f8a8ff7f49d593893f252744d0fe Mon Sep 17 00:00:00 2001
 | |
| From: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
 | |
| 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 <pantelis.antoniou@konsulko.com>
 | |
| ---
 | |
|  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
 | |
| 
 |