Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 658f29a5 authored by John Bonesio's avatar John Bonesio Committed by Grant Likely
Browse files

of/flattree: Update dtc to current mainline.

Pull in recent changes from the main dtc repository. These changes
primarily allow multiple device trees to be declared which are merged
by dtc. This feature allows us to include a basic dts file and then
provide more information for the specific system through the merging
functionality.

Changes pulled from git://git.jdl.com/software/dtc.git


commit id: 37c0b6a0, "dtc: Add code to make diffing trees easier"

Signed-off-by: default avatarJohn Bonesio <bones@secretlab.ca>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent cd1e6504
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ hostprogs-y := dtc
always		:= $(hostprogs-y)

dtc-objs	:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
		   srcpos.o checks.o
		   srcpos.o checks.o util.o
dtc-objs	+= dtc-lexer.lex.o dtc-parser.tab.o

# Source files need to get at the userspace version of libfdt_env.h to compile
@@ -19,6 +19,7 @@ HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)

HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
+94 −11
Original line number Diff line number Diff line
@@ -278,32 +278,112 @@ static void check_property_name_chars(struct check *c, struct node *dt,
}
PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);

static void check_explicit_phandles(struct check *c, struct node *root,
#define DESCLABEL_FMT	"%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark)		\
	((mark) ? "value of " : ""),		\
	((prop) ? "'" : ""), \
	((prop) ? (prop)->name : ""), \
	((prop) ? "' in " : ""), (node)->fullpath

static void check_duplicate_label(struct check *c, struct node *dt,
				  const char *label, struct node *node,
				  struct property *prop, struct marker *mark)
{
	struct node *othernode = NULL;
	struct property *otherprop = NULL;
	struct marker *othermark = NULL;

	othernode = get_node_by_label(dt, label);

	if (!othernode)
		otherprop = get_property_by_label(dt, label, &othernode);
	if (!othernode)
		othermark = get_marker_label(dt, label, &othernode,
					       &otherprop);

	if (!othernode)
		return;

	if ((othernode != node) || (otherprop != prop) || (othermark != mark))
		FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
		     " and " DESCLABEL_FMT,
		     label, DESCLABEL_ARGS(node, prop, mark),
		     DESCLABEL_ARGS(othernode, otherprop, othermark));
}

static void check_duplicate_label_node(struct check *c, struct node *dt,
				       struct node *node)
{
	struct property *prop;
	struct label *l;

	for_each_label(node->labels, l)
		check_duplicate_label(c, dt, l->label, node, NULL, NULL);
}
static void check_duplicate_label_prop(struct check *c, struct node *dt,
				       struct node *node, struct property *prop)
{
	struct marker *m = prop->val.markers;
	struct label *l;

	for_each_label(prop->labels, l)
		check_duplicate_label(c, dt, l->label, node, prop, NULL);

	for_each_marker_of_type(m, LABEL)
		check_duplicate_label(c, dt, m->ref, node, prop, m);
}
CHECK(duplicate_label, NULL, check_duplicate_label_node,
      check_duplicate_label_prop, NULL, ERROR);

static void check_explicit_phandles(struct check *c, struct node *root,
				    struct node *node, struct property *prop)
{
	struct marker *m;
	struct node *other;
	cell_t phandle;

	prop = get_property(node, "linux,phandle");
	if (! prop)
		return; /* No phandle, that's fine */
	if (!streq(prop->name, "phandle")
	    && !streq(prop->name, "linux,phandle"))
		return;

	if (prop->val.len != sizeof(cell_t)) {
		FAIL(c, "%s has bad length (%d) linux,phandle property",
		     node->fullpath, prop->val.len);
		FAIL(c, "%s has bad length (%d) %s property",
		     node->fullpath, prop->val.len, prop->name);
		return;
	}

	m = prop->val.markers;
	for_each_marker_of_type(m, REF_PHANDLE) {
		assert(m->offset == 0);
		if (node != get_node_by_ref(root, m->ref))
			/* "Set this node's phandle equal to some
			 * other node's phandle".  That's nonsensical
			 * by construction. */ {
			FAIL(c, "%s in %s is a reference to another node",
			     prop->name, node->fullpath);
			return;
		}
		/* But setting this node's phandle equal to its own
		 * phandle is allowed - that means allocate a unique
		 * phandle for this node, even if it's not otherwise
		 * referenced.  The value will be filled in later, so
		 * no further checking for now. */
		return;
	}

	phandle = propval_cell(prop);

	if ((phandle == 0) || (phandle == -1)) {
		FAIL(c, "%s has invalid linux,phandle value 0x%x",
		     node->fullpath, phandle);
		FAIL(c, "%s has bad value (0x%x) in %s property",
		     node->fullpath, phandle, prop->name);
		return;
	}

	if (node->phandle && (node->phandle != phandle))
		FAIL(c, "%s has %s property which replaces existing phandle information",
		     node->fullpath, prop->name);

	other = get_node_by_phandle(root, phandle);
	if (other) {
	if (other && (other != node)) {
		FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
		     node->fullpath, phandle, other->fullpath);
		return;
@@ -311,7 +391,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,

	node->phandle = phandle;
}
NODE_CHECK(explicit_phandles, NULL, ERROR);
PROP_CHECK(explicit_phandles, NULL, ERROR);

static void check_name_properties(struct check *c, struct node *root,
				  struct node *node)
@@ -549,6 +629,9 @@ static struct check *check_table[] = {
	&duplicate_node_names, &duplicate_property_names,
	&node_name_chars, &node_name_format, &property_name_chars,
	&name_is_string, &name_properties,

	&duplicate_label,

	&explicit_phandles,
	&phandle_references, &path_references,

+23 −152
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
 *                                                                   USA
 */

%option noyywrap noinput nounput yylineno
%option noyywrap nounput noinput never-interactive

%x INCLUDE
%x BYTESTRING
@@ -38,6 +38,13 @@ LINECOMMENT "//".*\n
#include "srcpos.h"
#include "dtc-parser.tab.h"

YYLTYPE yylloc;

/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
#define	YY_USER_ACTION \
	{ \
		srcpos_update(&yylloc, yytext, yyleng); \
	}

/*#define LEXDEBUG	1*/

@@ -47,15 +54,10 @@ LINECOMMENT "//".*\n
#define DPRINT(fmt, ...)	do { } while (0)
#endif

static int dts_version; /* = 0 */
static int dts_version = 1;

#define BEGIN_DEFAULT()	if (dts_version == 0) { \
				DPRINT("<INITIAL>\n"); \
				BEGIN(INITIAL); \
			} else { \
				DPRINT("<V1>\n"); \
#define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
				BEGIN(V1); \
			}

static void push_input_file(const char *filename);
static int pop_input_file(void);
@@ -75,18 +77,13 @@ static int pop_input_file(void);
		}

<*>{STRING}	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("String: %s\n", yytext);
			yylval.data = data_copy_escape_string(yytext+1,
					yyleng-2);
			yylloc.first_line = yylineno;
			return DT_STRING;
		}

<*>"/dts-v1/"	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("Keyword: /dts-v1/\n");
			dts_version = 1;
			BEGIN_DEFAULT();
@@ -94,106 +91,57 @@ static int pop_input_file(void);
		}

<*>"/memreserve/"	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("Keyword: /memreserve/\n");
			BEGIN_DEFAULT();
			return DT_MEMRESERVE;
		}

<*>{LABEL}:	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("Label: %s\n", yytext);
			yylval.labelref = strdup(yytext);
			yylval.labelref = xstrdup(yytext);
			yylval.labelref[yyleng-1] = '\0';
			return DT_LABEL;
		}

<INITIAL>[bodh]# {
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			if (*yytext == 'b')
				yylval.cbase = 2;
			else if (*yytext == 'o')
				yylval.cbase = 8;
			else if (*yytext == 'd')
				yylval.cbase = 10;
			else
				yylval.cbase = 16;
			DPRINT("Base: %d\n", yylval.cbase);
			return DT_BASE;
		}

<INITIAL>[0-9a-fA-F]+	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			yylval.literal = strdup(yytext);
			DPRINT("Literal: '%s'\n", yylval.literal);
			return DT_LEGACYLITERAL;
		}

<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			yylval.literal = strdup(yytext);
			yylval.literal = xstrdup(yytext);
			DPRINT("Literal: '%s'\n", yylval.literal);
			return DT_LITERAL;
		}

\&{LABEL}	{	/* label reference */
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
<*>\&{LABEL}	{	/* label reference */
			DPRINT("Ref: %s\n", yytext+1);
			yylval.labelref = strdup(yytext+1);
			yylval.labelref = xstrdup(yytext+1);
			return DT_REF;
		}

"&{/"{PATHCHAR}+\}	{	/* new-style path reference */
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
<*>"&{/"{PATHCHAR}+\}	{	/* new-style path reference */
			yytext[yyleng-1] = '\0';
			DPRINT("Ref: %s\n", yytext+2);
			yylval.labelref = strdup(yytext+2);
			return DT_REF;
		}

<INITIAL>"&/"{PATHCHAR}+ {	/* old-style path reference */
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("Ref: %s\n", yytext+1);
			yylval.labelref = strdup(yytext+1);
			yylval.labelref = xstrdup(yytext+2);
			return DT_REF;
		}

<BYTESTRING>[0-9a-fA-F]{2} {
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			yylval.byte = strtol(yytext, NULL, 16);
			DPRINT("Byte: %02x\n", (int)yylval.byte);
			return DT_BYTE;
		}

<BYTESTRING>"]"	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("/BYTESTRING\n");
			BEGIN_DEFAULT();
			return ']';
		}

<PROPNODENAME>{PROPNODECHAR}+ {
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("PropNodeName: %s\n", yytext);
			yylval.propnodename = strdup(yytext);
			yylval.propnodename = xstrdup(yytext);
			BEGIN_DEFAULT();
			return DT_PROPNODENAME;
		}

"/incbin/"	{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("Binary Include\n");
			return DT_INCBIN;
		}
@@ -203,8 +151,6 @@ static int pop_input_file(void);
<*>{LINECOMMENT}+ /* eat C++-style comments */

<*>.		{
			yylloc.file = srcpos_file;
			yylloc.first_line = yylineno;
			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
				(unsigned)yytext[0]);
			if (yytext[0] == '[') {
@@ -221,100 +167,25 @@ static int pop_input_file(void);

%%


/*
 * Stack of nested include file contexts.
 */

struct incl_file {
	struct dtc_file *file;
	YY_BUFFER_STATE yy_prev_buf;
	int yy_prev_lineno;
	struct incl_file *prev;
};

static struct incl_file *incl_file_stack;


/*
 * Detect infinite include recursion.
 */
#define MAX_INCLUDE_DEPTH	(100)

static int incl_depth = 0;


static void push_input_file(const char *filename)
{
	struct incl_file *incl_file;
	struct dtc_file *newfile;
	struct search_path search, *searchptr = NULL;

	assert(filename);

	if (incl_depth++ >= MAX_INCLUDE_DEPTH)
		die("Includes nested too deeply");

	if (srcpos_file) {
		search.dir = srcpos_file->dir;
		search.next = NULL;
		search.prev = NULL;
		searchptr = &search;
	}

	newfile = dtc_open_file(filename, searchptr);
	srcfile_push(filename);

	incl_file = xmalloc(sizeof(struct incl_file));
	yyin = current_srcfile->f;

	/*
	 * Save current context.
	 */
	incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
	incl_file->yy_prev_lineno = yylineno;
	incl_file->file = srcpos_file;
	incl_file->prev = incl_file_stack;

	incl_file_stack = incl_file;

	/*
	 * Establish new context.
	 */
	srcpos_file = newfile;
	yylineno = 1;
	yyin = newfile->file;
	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
}


static int pop_input_file(void)
{
	struct incl_file *incl_file;

	if (incl_file_stack == 0)
	if (srcfile_pop() == 0)
		return 0;

	dtc_close_file(srcpos_file);

	/*
	 * Pop.
	 */
	--incl_depth;
	incl_file = incl_file_stack;
	incl_file_stack = incl_file->prev;

	/*
	 * Recover old context.
	 */
	yy_delete_buffer(YY_CURRENT_BUFFER);
	yy_switch_to_buffer(incl_file->yy_prev_buf);
	yylineno = incl_file->yy_prev_lineno;
	srcpos_file = incl_file->file;
	yyin = incl_file->file ? incl_file->file->file : NULL;

	/*
	 * Free old state.
	 */
	free(incl_file);
	yypop_buffer_state();
	yyin = current_srcfile->f;

	return 1;
}
+176 −375

File changed.

Preview size limit exceeded, changes collapsed.

+440 −452

File changed.

Preview size limit exceeded, changes collapsed.

Loading