From 5aae23c378ed64132176cb999d7784e84f97e9c2 Mon Sep 17 00:00:00 2001
From: Peter Seiderer <ps.report@gmx.net>
Date: Sun, 11 Jan 2015 18:11:06 +0100
Subject: [PATCH v3 6/7] dtc: add patches for raspberry pi overlay support

See [1] for documentation of raspberry pi kernel dt overlay support.

The following patches (see original download urls) where adjusted to dtc-1.4.1:

- 0003-dtc-Dynamic-symbols-fixup-support.patch
https://github.com/RobertCNelson/dtc/commit/dd6a0533e846e8d5e690a618fa35cc15a6103efb.patch

- 0004-dtc-v-takes-no-argument-drop-extra.patch
https://github.com/RobertCNelson/dtc/commit/f345d9e48c9e1169edf047de742da142cc5687bc.patch

[1] https://github.com/raspberrypi/documentation/blob/master/configuration/device-tree.md

Signed-off-by: Peter Seiderer <ps.report@gmx.net>
---
 .../0003-dtc-Dynamic-symbols-fixup-support.patch   | 581 +++++++++++++++++++++
 .../0004-dtc-v-takes-no-argument-drop-extra.patch  |  44 ++
 2 files changed, 625 insertions(+)
 create mode 100644 package/dtc/0003-dtc-Dynamic-symbols-fixup-support.patch
 create mode 100644 package/dtc/0004-dtc-v-takes-no-argument-drop-extra.patch

diff --git a/package/dtc/0003-dtc-Dynamic-symbols-fixup-support.patch b/package/dtc/0003-dtc-Dynamic-symbols-fixup-support.patch
new file mode 100644
index 0000000..125cd96
--- /dev/null
+++ b/package/dtc/0003-dtc-Dynamic-symbols-fixup-support.patch
@@ -0,0 +1,581 @@
+From 144952b04835af4ee235ea0735e6ba999eab559c Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 4 Jan 2013 21:16:21 +0200
+Subject: [PATCH 3/4] dtc: Dynamic symbols & fixup support
+
+Enable the generation of symbol & fixup information for
+usage with dynamic DT loading.
+
+Passing the -@ option generates a __symbols__ node at the
+root node of the resulting blob for any node labels used.
+
+When using the /plugin/ tag all unresolved label references
+be tracked in the __fixups__ node, while all local phandle
+references will the tracked in the __local_fixups__ node.
+
+This is sufficient to implement a dynamic DT object loader.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+Signed-off-by: Stefan Agner <stefan@agner.ch>
+
+Adjusted to dtc-1.4.1:
+Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+---
+ Documentation/dts-format.txt |   7 +++
+ Documentation/manual.txt     |   8 +++
+ checks.c                     | 120 +++++++++++++++++++++++++++++++++++--
+ dtc-lexer.l                  |   5 ++
+ dtc-parser.y                 |  23 ++++++-
+ dtc.c                        |   9 ++-
+ dtc.h                        |  38 ++++++++++++
+ flattree.c                   | 139 +++++++++++++++++++++++++++++++++++++++++++
+ 8 files changed, 340 insertions(+), 9 deletions(-)
+
+diff --git a/Documentation/dts-format.txt b/Documentation/dts-format.txt
+index 41741df..4da515c 100644
+--- a/Documentation/dts-format.txt
++++ b/Documentation/dts-format.txt
+@@ -115,7 +115,14 @@ Version 1 DTS files have the overall layout:
+ 
+ * C style (/* ... */) and C++ style (// ...) comments are supported.
+ 
++Device Tree Objects
++-------------------
+ 
++Using the plugin tag enables dynamic tree objects.
++
++	/plugin/;
++
++For the full details please see Documentation/dt-object-internal.txt
+ 
+ 	-- David Gibson <david@gibson.dropbear.id.au>
+ 	-- Yoder Stuart <stuart.yoder@freescale.com>
+diff --git a/Documentation/manual.txt b/Documentation/manual.txt
+index 398de32..07321ff 100644
+--- a/Documentation/manual.txt
++++ b/Documentation/manual.txt
+@@ -131,6 +131,14 @@ Options:
+ 	By default the most recent version is generated.
+ 	Relevant for dtb and asm output only.
+ 
++    -@
++        Dynamic resolution mode. For non /plugin/ compilations generate
++	a __symbols__ node containing a list of all nodes with a label.
++	When /plugin/ is used, unresolved references are recorded in
++	a __fixups__ node, while local phandle references are recorded
++	in a __local_fixups__ node.
++	See Documentation/dt-object-internal.txt
++
+ 
+ The <output_version> defines what version of the "blob" format will be
+ generated.  Supported versions are 1, 2, 3, 16 and 17.  The default is
+diff --git a/checks.c b/checks.c
+index 3bf0fa4..078a50e 100644
+--- a/checks.c
++++ b/checks.c
+@@ -457,22 +457,93 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
+ 				     struct node *node, struct property *prop)
+ {
+ 	struct marker *m = prop->val.markers;
++	struct fixup *f, **fp;
++	struct fixup_entry *fe, **fep;
+ 	struct node *refnode;
+ 	cell_t phandle;
++	int has_phandle_refs;
++
++	has_phandle_refs = 0;
++	for_each_marker_of_type(m, REF_PHANDLE) {
++		has_phandle_refs = 1;
++		break;
++	}
++
++	if (!has_phandle_refs)
++		return;
+ 
+ 	for_each_marker_of_type(m, REF_PHANDLE) {
+ 		assert(m->offset + sizeof(cell_t) <= prop->val.len);
+ 
+ 		refnode = get_node_by_ref(dt, m->ref);
+-		if (! refnode) {
++		if (!refnode && !symbol_fixup_support) {
+ 			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+-			     m->ref);
++				m->ref);
+ 			continue;
+ 		}
+ 
+-		phandle = get_node_phandle(dt, refnode);
+-		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
++		if (!refnode) {
++			/* allocate fixup entry */
++			fe = xmalloc(sizeof(*fe));
++
++			fe->node = node;
++			fe->prop = prop;
++			fe->offset = m->offset;
++			fe->next = NULL;
++
++			/* search for an already existing fixup */
++			for_each_fixup(dt, f)
++				if (strcmp(f->ref, m->ref) == 0)
++					break;
++
++			/* no fixup found, add new */
++			if (f == NULL) {
++				f = xmalloc(sizeof(*f));
++				f->ref = m->ref;
++				f->entries = NULL;
++				f->next = NULL;
++
++				/* add it to the tree */
++				fp = &dt->fixups;
++				while (*fp)
++					fp = &(*fp)->next;
++				*fp = f;
++			}
++
++			/* and now append fixup entry */
++			fep = &f->entries;
++			while (*fep)
++				fep = &(*fep)->next;
++			*fep = fe;
++
++			/* mark the entry as unresolved */
++			phandle = 0xdeadbeef;
++		} else {
++			phandle = get_node_phandle(dt, refnode);
++
++			/* if it's a plugin, we need to record it */
++			if (symbol_fixup_support && dt->is_plugin) {
++
++				/* allocate a new local fixup entry */
++				fe = xmalloc(sizeof(*fe));
++
++				fe->node = node;
++				fe->prop = prop;
++				fe->offset = m->offset;
++				fe->next = NULL;
++
++				/* append it to the local fixups */
++				fep = &dt->local_fixups;
++				while (*fep)
++					fep = &(*fep)->next;
++				*fep = fe;
++			}
++		}
++
++		*((cell_t *)(prop->val.val + m->offset)) =
++			cpu_to_fdt32(phandle);
+ 	}
++
+ }
+ ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
+       &duplicate_node_names, &explicit_phandles);
+@@ -651,6 +722,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
+ }
+ TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
+ 
++static void check_auto_label_phandles(struct check *c, struct node *dt,
++				       struct node *node)
++{
++	struct label *l;
++	struct symbol *s, **sp;
++	int has_label;
++
++	if (!symbol_fixup_support)
++		return;
++
++	has_label = 0;
++	for_each_label(node->labels, l) {
++		has_label = 1;
++		break;
++	}
++
++	if (!has_label)
++		return;
++
++	/* force allocation of a phandle for this node */
++	(void)get_node_phandle(dt, node);
++
++	/* add the symbol */
++	for_each_label(node->labels, l) {
++
++		s = xmalloc(sizeof(*s));
++		s->label = l;
++		s->node = node;
++		s->next = NULL;
++
++		/* add it to the symbols list */
++		sp = &dt->symbols;
++		while (*sp)
++			sp = &((*sp)->next);
++		*sp = s;
++	}
++}
++NODE_WARNING(auto_label_phandles, NULL);
++
+ static struct check *check_table[] = {
+ 	&duplicate_node_names, &duplicate_property_names,
+ 	&node_name_chars, &node_name_format, &property_name_chars,
+@@ -669,6 +779,8 @@ static struct check *check_table[] = {
+ 	&avoid_default_addr_size,
+ 	&obsolete_chosen_interrupt_controller,
+ 
++	&auto_label_phandles,
++
+ 	&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..687ccad 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;
++	int 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,23 @@ extern bool treesource_error;
+ %%
+ 
+ sourcefile:
+-	  DT_V1 ';' memreserves devicetree
++	  DT_V1 ';' plugindecl memreserves devicetree
+ 		{
+-			the_boot_info = build_boot_info($3, $4,
+-							guess_boot_cpuid($4));
++			$5->is_plugin = $3;
++			$5->is_root = 1;
++			the_boot_info = build_boot_info($4, $5,
++							guess_boot_cpuid($5));
++		}
++	;
++
++plugindecl:
++	/* empty */
++		{
++			$$ = 0;
++		}
++	| DT_PLUGIN ';'
++		{
++			$$ = 1;
+ 		}
+ 	;
+ 
+diff --git a/dtc.c b/dtc.c
+index 8c4add6..f4d56e5 100644
+--- a/dtc.c
++++ b/dtc.c
+@@ -29,6 +29,7 @@ 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 = 0;
+ 
+ static void fill_fullpaths(struct node *tree, const char *prefix)
+ {
+@@ -51,7 +52,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:hv:@";
+ static struct option const usage_long_opts[] = {
+ 	{"quiet",            no_argument, NULL, 'q'},
+ 	{"in-format",         a_argument, NULL, 'I'},
+@@ -69,6 +70,7 @@ static struct option const usage_long_opts[] = {
+ 	{"phandle",           a_argument, NULL, 'H'},
+ 	{"warning",           a_argument, NULL, 'W'},
+ 	{"error",             a_argument, NULL, 'E'},
++	{"symbols",           a_argument, NULL, '@'},
+ 	{"help",             no_argument, NULL, 'h'},
+ 	{"version",          no_argument, NULL, 'v'},
+ 	{NULL,               no_argument, NULL, 0x0},
+@@ -99,6 +101,7 @@ 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\tSymbols and Fixups support",
+ 	"\n\tPrint this help and exit",
+ 	"\n\tPrint version and exit",
+ 	NULL,
+@@ -186,7 +189,9 @@ int main(int argc, char *argv[])
+ 		case 'E':
+ 			parse_checks_option(false, true, optarg);
+ 			break;
+-
++		case '@':
++			symbol_fixup_support = 1;
++			break;
+ 		case 'h':
+ 			usage(NULL);
+ 		default:
+diff --git a/dtc.h b/dtc.h
+index 56212c8..fe45748 100644
+--- a/dtc.h
++++ b/dtc.h
+@@ -54,6 +54,7 @@ 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 */
+ 
+ #define PHANDLE_LEGACY	0x1
+ #define PHANDLE_EPAPR	0x2
+@@ -132,6 +133,25 @@ struct label {
+ 	struct label *next;
+ };
+ 
++struct fixup_entry {
++	int offset;
++	struct node *node;
++	struct property *prop;
++	struct fixup_entry *next;
++};
++
++struct fixup {
++	char *ref;
++	struct fixup_entry *entries;
++	struct fixup *next;
++};
++
++struct symbol {
++	struct label *label;
++	struct node *node;
++	struct symbol *next;
++};
++
+ struct property {
+ 	bool deleted;
+ 	char *name;
+@@ -158,6 +178,12 @@ struct node {
+ 	int addr_cells, size_cells;
+ 
+ 	struct label *labels;
++
++	int is_root;
++	int is_plugin;
++	struct fixup *fixups;
++	struct symbol *symbols;
++	struct fixup_entry *local_fixups;
+ };
+ 
+ #define for_each_label_withdel(l0, l) \
+@@ -181,6 +207,18 @@ struct node {
+ 	for_each_child_withdel(n, c) \
+ 		if (!(c)->deleted)
+ 
++#define for_each_fixup(n, f) \
++	for ((f) = (n)->fixups; (f); (f) = (f)->next)
++
++#define for_each_fixup_entry(f, fe) \
++	for ((fe) = (f)->entries; (fe); (fe) = (fe)->next)
++
++#define for_each_symbol(n, s) \
++	for ((s) = (n)->symbols; (s); (s) = (s)->next)
++
++#define for_each_local_fixup_entry(n, fe) \
++	for ((fe) = (n)->local_fixups; (fe); (fe) = (fe)->next)
++
+ void add_label(struct label **labels, char *label);
+ void delete_labels(struct label **labels);
+ 
+diff --git a/flattree.c b/flattree.c
+index bd99fa2..7f3df74 100644
+--- a/flattree.c
++++ b/flattree.c
+@@ -262,6 +262,12 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
+ 	struct property *prop;
+ 	struct node *child;
+ 	bool seen_name_prop = false;
++	struct symbol *sym;
++	struct fixup *f;
++	struct fixup_entry *fe;
++	char *name, *s;
++	const char *fullpath;
++	int namesz, nameoff, vallen;
+ 
+ 	if (tree->deleted)
+ 		return;
+@@ -310,6 +316,139 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
+ 		flatten_tree(child, emit, etarget, strbuf, vi);
+ 	}
+ 
++	if (!symbol_fixup_support)
++		goto no_symbols;
++
++	/* add the symbol nodes (if any) */
++	if (tree->symbols) {
++
++		emit->beginnode(etarget, NULL);
++		emit->string(etarget, "__symbols__", 0);
++		emit->align(etarget, sizeof(cell_t));
++
++		for_each_symbol(tree, sym) {
++
++			vallen = strlen(sym->node->fullpath);
++
++			nameoff = stringtable_insert(strbuf, sym->label->label);
++
++			emit->property(etarget, NULL);
++			emit->cell(etarget, vallen + 1);
++			emit->cell(etarget, nameoff);
++
++			if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
++				emit->align(etarget, 8);
++
++			emit->string(etarget, sym->node->fullpath,
++					strlen(sym->node->fullpath));
++			emit->align(etarget, sizeof(cell_t));
++		}
++
++		emit->endnode(etarget, NULL);
++	}
++
++	/* add the fixup nodes */
++	if (tree->fixups) {
++
++		/* emit the external fixups */
++		emit->beginnode(etarget, NULL);
++		emit->string(etarget, "__fixups__", 0);
++		emit->align(etarget, sizeof(cell_t));
++
++		for_each_fixup(tree, f) {
++
++			namesz = 0;
++			for_each_fixup_entry(f, fe) {
++				fullpath = fe->node->fullpath;
++				if (fullpath[0] == '\0')
++					fullpath = "/";
++				namesz += strlen(fullpath) + 1;
++			      	namesz += strlen(fe->prop->name) + 1;
++				namesz += 32;	/* space for :<number> + '\0' */
++			}
++
++			name = xmalloc(namesz);
++
++			s = name;
++			for_each_fixup_entry(f, fe) {
++				fullpath = fe->node->fullpath;
++				if (fullpath[0] == '\0')
++					fullpath = "/";
++				snprintf(s, name + namesz - s, "%s:%s:%d",
++						fullpath,
++						fe->prop->name, fe->offset);
++				s += strlen(s) + 1;
++			}
++
++			nameoff = stringtable_insert(strbuf, f->ref);
++			vallen = s - name - 1;
++
++			emit->property(etarget, NULL);
++			emit->cell(etarget, vallen + 1);
++			emit->cell(etarget, nameoff);
++
++			if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
++				emit->align(etarget, 8);
++
++			emit->string(etarget, name, vallen);
++			emit->align(etarget, sizeof(cell_t));
++
++			free(name);
++		}
++
++		emit->endnode(etarget, tree->labels);
++	}
++
++	/* add the local fixup property */
++	if (tree->local_fixups) {
++
++		/* emit the external fixups */
++		emit->beginnode(etarget, NULL);
++		emit->string(etarget, "__local_fixups__", 0);
++		emit->align(etarget, sizeof(cell_t));
++
++		namesz = 0;
++		for_each_local_fixup_entry(tree, fe) {
++			fullpath = fe->node->fullpath;
++			if (fullpath[0] == '\0')
++				fullpath = "/";
++			namesz += strlen(fullpath) + 1;
++			namesz += strlen(fe->prop->name) + 1;
++			namesz += 32;	/* space for :<number> + '\0' */
++		}
++
++		name = xmalloc(namesz);
++
++		s = name;
++		for_each_local_fixup_entry(tree, fe) {
++			fullpath = fe->node->fullpath;
++			if (fullpath[0] == '\0')
++				fullpath = "/";
++			snprintf(s, name + namesz - s, "%s:%s:%d",
++					fullpath, fe->prop->name,
++					fe->offset);
++			s += strlen(s) + 1;
++		}
++
++		nameoff = stringtable_insert(strbuf, "fixup");
++		vallen = s - name - 1;
++
++		emit->property(etarget, NULL);
++		emit->cell(etarget, vallen + 1);
++		emit->cell(etarget, nameoff);
++
++		if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
++			emit->align(etarget, 8);
++
++		emit->string(etarget, name, vallen);
++		emit->align(etarget, sizeof(cell_t));
++
++		free(name);
++
++		emit->endnode(etarget, tree->labels);
++	}
++
++no_symbols:
+ 	emit->endnode(etarget, tree->labels);
+ }
+ 
+-- 
+2.1.2
+
diff --git a/package/dtc/0004-dtc-v-takes-no-argument-drop-extra.patch b/package/dtc/0004-dtc-v-takes-no-argument-drop-extra.patch
new file mode 100644
index 0000000..9bb3f48
--- /dev/null
+++ b/package/dtc/0004-dtc-v-takes-no-argument-drop-extra.patch
@@ -0,0 +1,44 @@
+From c01c20c475d1547ddb197f52ae1c725acc7b4e3e Mon Sep 17 00:00:00 2001
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Mon, 23 Sep 2013 11:05:12 -0500
+Subject: [PATCH 4/4] dtc: v takes no argument drop extra :
+
+$ git show dd6a0533
+... snip ...
+@@ -49,7 +50,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
+
+ /* Usage related data. */
+ 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:hv:@";
+ static struct option const usage_long_opts[] = {
+        {"quiet",            no_argument, NULL, 'q'},
+        {"in-format",         a_argument, NULL, 'I'},
+
+  that patch is wrong, there should be no ":" after "v"
+
+Reported-by: Robert P. J. Day <rpjday@crashcourse.ca>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+
+Adjusted to dtc-1.4.1:
+Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+---
+ dtc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dtc.c b/dtc.c
+index f4d56e5..0cbb14c 100644
+--- a/dtc.c
++++ b/dtc.c
+@@ -52,7 +52,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:hv@";
+ static struct option const usage_long_opts[] = {
+ 	{"quiet",            no_argument, NULL, 'q'},
+ 	{"in-format",         a_argument, NULL, 'I'},
+-- 
+2.1.2
+
-- 
2.1.2

