Commit cd296721 authored by Stephen Warren's avatar Stephen Warren Committed by Rob Herring

dtc: import latest upstream dtc

This updates scripts/dtc to commit 317a5d9 "dtc: zero out new label
objects" from git://git.jdl.com/software/dtc.git.

This adds features such as:
* /bits/ syntax for cell data.
* Math expressions within cell data.
* The ability to delete properties or nodes.
* Support for #line directives in the input file, which allows the use of
  cpp on *.dts.
* -i command-line option (/include/ path)
* -W/-E command-line options for error/warning control.
* Removal of spew to STDOUT containing the filename being compiled.
* Many additions to the libfdt API.
Signed-off-by: default avatarStephen Warren <swarren@nvidia.com>
Acked-by: default avatarJon Loeliger <jdl@jdl.com>
Signed-off-by: default avatarRob Herring <rob.herring@calxeda.com>
parent acc20979
......@@ -3,7 +3,16 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
checks.c
DTC_SRCS = \
checks.c \
data.c \
dtc.c \
flattree.c \
fstree.c \
livetree.c \
srcpos.c \
treesource.c \
util.c
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
This diff is collapsed.
......@@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len)
return d;
}
static char get_oct_char(const char *s, int *i)
{
char x[4];
char *endx;
long val;
x[3] = '\0';
strncpy(x, s + *i, 3);
val = strtol(x, &endx, 8);
assert(endx > x);
(*i) += endx - x;
return val;
}
static char get_hex_char(const char *s, int *i)
{
char x[3];
char *endx;
long val;
x[2] = '\0';
strncpy(x, s + *i, 2);
val = strtol(x, &endx, 16);
if (!(endx > x))
die("\\x used with no following hex digits\n");
(*i) += endx - x;
return val;
}
struct data data_copy_escape_string(const char *s, int len)
{
int i = 0;
......@@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len)
while (i < len) {
char c = s[i++];
if (c != '\\') {
q[d.len++] = c;
continue;
}
c = s[i++];
assert(c);
switch (c) {
case 'a':
q[d.len++] = '\a';
break;
case 'b':
q[d.len++] = '\b';
break;
case 't':
q[d.len++] = '\t';
break;
case 'n':
q[d.len++] = '\n';
break;
case 'v':
q[d.len++] = '\v';
break;
case 'f':
q[d.len++] = '\f';
break;
case 'r':
q[d.len++] = '\r';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
i--; /* need to re-read the first digit as
* part of the octal value */
q[d.len++] = get_oct_char(s, &i);
break;
case 'x':
q[d.len++] = get_hex_char(s, &i);
break;
default:
q[d.len++] = c;
}
if (c == '\\')
c = get_escape_char(s, &i);
q[d.len++] = c;
}
q[d.len++] = '\0';
......@@ -245,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2)
return d;
}
struct data data_append_cell(struct data d, cell_t word)
struct data data_append_integer(struct data d, uint64_t value, int bits)
{
cell_t beword = cpu_to_fdt32(word);
return data_append_data(d, &beword, sizeof(beword));
uint8_t value_8;
uint16_t value_16;
uint32_t value_32;
uint64_t value_64;
switch (bits) {
case 8:
value_8 = value;
return data_append_data(d, &value_8, 1);
case 16:
value_16 = cpu_to_fdt16(value);
return data_append_data(d, &value_16, 2);
case 32:
value_32 = cpu_to_fdt32(value);
return data_append_data(d, &value_32, 4);
case 64:
value_64 = cpu_to_fdt64(value);
return data_append_data(d, &value_64, 8);
default:
die("Invalid literal size (%d)\n", bits);
}
}
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
......@@ -262,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
return data_append_data(d, &bere, sizeof(bere));
}
struct data data_append_addr(struct data d, uint64_t addr)
struct data data_append_cell(struct data d, cell_t word)
{
uint64_t beaddr = cpu_to_fdt64(addr);
return data_append_integer(d, word, sizeof(word) * 8);
}
return data_append_data(d, &beaddr, sizeof(beaddr));
struct data data_append_addr(struct data d, uint64_t addr)
{
return data_append_integer(d, addr, sizeof(addr) * 8);
}
struct data data_append_byte(struct data d, uint8_t byte)
......
......@@ -29,6 +29,7 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
CHAR_LITERAL '([^']|\\')*'
WS [[:space:]]
COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
LINECOMMENT "//".*\n
......@@ -70,6 +71,27 @@ static int pop_input_file(void);
push_input_file(name);
}
<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? {
char *line, *tmp, *fn;
/* skip text before line # */
line = yytext;
while (!isdigit(*line))
line++;
/* skip digits in line # */
tmp = line;
while (!isspace(*tmp))
tmp++;
/* "NULL"-terminate line # */
*tmp = '\0';
/* start of filename */
fn = strchr(tmp + 1, '"') + 1;
/* strip trailing " from filename */
tmp = strchr(fn, '"');
*tmp = 0;
/* -1 since #line is the number of the next line */
srcpos_set_line(xstrdup(fn), atoi(line) - 1);
}
<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
......@@ -96,6 +118,26 @@ static int pop_input_file(void);
return DT_MEMRESERVE;
}
<*>"/bits/" {
DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT();
return DT_BITS;
}
<*>"/delete-property/" {
DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
return DT_DEL_PROP;
}
<*>"/delete-node/" {
DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
return DT_DEL_NODE;
}
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
......@@ -103,12 +145,19 @@ static int pop_input_file(void);
return DT_LABEL;
}
<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
yylval.literal = xstrdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
<*>{CHAR_LITERAL} {
yytext[yyleng-1] = '\0';
yylval.literal = xstrdup(yytext+1);
DPRINT("Character literal: %s\n", yylval.literal);
return DT_CHAR_LITERAL;
}
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
......@@ -134,9 +183,10 @@ static int pop_input_file(void);
return ']';
}
<PROPNODENAME>{PROPNODECHAR}+ {
<PROPNODENAME>\\?{PROPNODECHAR}+ {
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup(yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
......@@ -150,6 +200,15 @@ static int pop_input_file(void);
<*>{COMMENT}+ /* eat C-style comments */
<*>{LINECOMMENT}+ /* eat C++-style comments */
<*>"<<" { return DT_LSHIFT; };
<*>">>" { return DT_RSHIFT; };
<*>"<=" { return DT_LE; };
<*>">=" { return DT_GE; };
<*>"==" { return DT_EQ; };
<*>"!=" { return DT_NE; };
<*>"&&" { return DT_AND; };
<*>"||" { return DT_OR; };
<*>. {
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
......
This diff is collapsed.
This diff is collapsed.
/* A Bison parser, made by GNU Bison 2.4.3. */
/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2009, 2010 Free Software Foundation, Inc.
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -40,14 +41,26 @@
enum yytokentype {
DT_V1 = 258,
DT_MEMRESERVE = 259,
DT_PROPNODENAME = 260,
DT_LITERAL = 261,
DT_BASE = 262,
DT_BYTE = 263,
DT_STRING = 264,
DT_LABEL = 265,
DT_REF = 266,
DT_INCBIN = 267
DT_LSHIFT = 260,
DT_RSHIFT = 261,
DT_LE = 262,
DT_GE = 263,
DT_EQ = 264,
DT_NE = 265,
DT_AND = 266,
DT_OR = 267,
DT_BITS = 268,
DT_DEL_PROP = 269,
DT_DEL_NODE = 270,
DT_PROPNODENAME = 271,
DT_LITERAL = 272,
DT_CHAR_LITERAL = 273,
DT_BASE = 274,
DT_BYTE = 275,
DT_STRING = 276,
DT_LABEL = 277,
DT_REF = 278,
DT_INCBIN = 279
};
#endif
......@@ -57,6 +70,8 @@
typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 40 "dtc-parser.y"
char *propnodename;
char *literal;
......@@ -65,16 +80,22 @@ typedef union YYSTYPE
uint8_t byte;
struct data data;
uint64_t addr;
cell_t cell;
struct {
struct data data;
int bits;
} array;
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
/* Line 1676 of yacc.c */
#line 99 "dtc-parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
......
......@@ -34,6 +34,7 @@ extern struct boot_info *the_boot_info;
extern int treesource_error;
static unsigned long long eval_literal(const char *s, int base, int bits);
static unsigned char eval_char_literal(const char *s);
%}
%union {
......@@ -44,19 +45,28 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
uint8_t byte;
struct data data;
uint64_t addr;
cell_t cell;
struct {
struct data data;
int bits;
} array;
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
}
%token DT_V1
%token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS
%token DT_DEL_PROP
%token DT_DEL_NODE
%token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL
%token <literal> DT_CHAR_LITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
......@@ -68,9 +78,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
%type <addr> addr
%type <data> celllist
%type <cell> cellval
%type <array> arrayprefix
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
......@@ -80,6 +88,21 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <node> subnode
%type <nodelist> subnodes
%type <integer> integer_prim
%type <integer> integer_unary
%type <integer> integer_mul
%type <integer> integer_add
%type <integer> integer_shift
%type <integer> integer_rela
%type <integer> integer_eq
%type <integer> integer_bitand
%type <integer> integer_bitxor
%type <integer> integer_bitor
%type <integer> integer_and
%type <integer> integer_or
%type <integer> integer_trinary
%type <integer> integer_expr
%%
sourcefile:
......@@ -102,7 +125,7 @@ memreserves:
;
memreserve:
DT_MEMRESERVE addr addr ';'
DT_MEMRESERVE integer_prim integer_prim ';'
{
$$ = build_reserve_entry($2, $3);
}
......@@ -113,13 +136,6 @@ memreserve:
}
;
addr:
DT_LITERAL
{
$$ = eval_literal($1, 0, 64);
}
;
devicetree:
'/' nodedef
{
......@@ -139,6 +155,17 @@ devicetree:
print_error("label or path, '%s', not found", $2);
$$ = $1;
}
| devicetree DT_DEL_NODE DT_REF ';'
{
struct node *target = get_node_by_ref($1, $3);
if (!target)
print_error("label or path, '%s', not found", $3);
else
delete_node(target);
$$ = $1;
}
;
nodedef:
......@@ -168,6 +195,10 @@ propdef:
{
$$ = build_property($1, empty_data);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
$$ = build_property_delete($2);
}
| DT_LABEL propdef
{
add_label(&$2->labels, $1);
......@@ -180,9 +211,9 @@ propdata:
{
$$ = data_merge($1, $2);
}
| propdataprefix '<' celllist '>'
| propdataprefix arrayprefix '>'
{
$$ = data_merge($1, $3);
$$ = data_merge($1, $2.data);
}
| propdataprefix '[' bytestring ']'
{
......@@ -192,7 +223,7 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
{
FILE *f = srcfile_relative_open($4.val, NULL);
struct data d;
......@@ -240,31 +271,154 @@ propdataprefix:
}
;
celllist:
/* empty */
arrayprefix:
DT_BITS DT_LITERAL '<'
{
$$.data = empty_data;
$$.bits = eval_literal($2, 0, 7);
if (($$.bits != 8) &&
($$.bits != 16) &&
($$.bits != 32) &&
($$.bits != 64))
{
print_error("Only 8, 16, 32 and 64-bit elements"
" are currently supported");
$$.bits = 32;
}
}
| '<'
{
$$.data = empty_data;
$$.bits = 32;
}
| arrayprefix integer_prim
{
if ($1.bits < 64) {
uint64_t mask = (1ULL << $1.bits) - 1;
/*
* Bits above mask must either be all zero
* (positive within range of mask) or all one
* (negative and sign-extended). The second
* condition is true if when we set all bits
* within the mask to one (i.e. | in the
* mask), all bits are one.
*/
if (($2 > mask) && (($2 | mask) != -1ULL))
print_error(
"integer value out of range "
"%016lx (%d bits)", $1.bits);
}
$$.data = data_append_integer($1.data, $2, $1.bits);
}
| arrayprefix DT_REF
{
uint64_t val = ~0ULL >> (64 - $1.bits);
if ($1.bits == 32)
$1.data = data_add_marker($1.data,
REF_PHANDLE,
$2);
else
print_error("References are only allowed in "
"arrays with 32-bit elements.");
$$.data = data_append_integer($1.data, val, $1.bits);
}
| arrayprefix DT_LABEL
{
$$ = empty_data;
$$.data = data_add_marker($1.data, LABEL, $2);
}
| celllist cellval
;
integer_prim:
DT_LITERAL
{
$$ = data_append_cell($1, $2);
$$ = eval_literal($1, 0, 64);
}
| celllist DT_REF
| DT_CHAR_LITERAL
{
$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
$2), -1);
$$ = eval_char_literal($1);
}
| celllist DT_LABEL
| '(' integer_expr ')'
{
$$ = data_add_marker($1, LABEL, $2);
$$ = $2;
}
;
cellval:
DT_LITERAL
{
$$ = eval_literal($1, 0, 32);
}
integer_expr:
integer_trinary
;
integer_trinary:
integer_or
| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
;
integer_or:
integer_and
| integer_or DT_OR integer_and { $$ = $1 || $3; }
;
integer_and:
integer_bitor
| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
;
integer_bitor:
integer_bitxor
| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
;
integer_bitxor:
integer_bitand
| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
;
integer_bitand:
integer_eq
| integer_bitand '&' integer_eq { $$ = $1 & $3; }
;
integer_eq:
integer_rela
| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
;
integer_rela:
integer_shift
| integer_rela '<' integer_shift { $$ = $1 < $3; }
| integer_rela '>' integer_shift { $$ = $1 > $3; }
| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
;
integer_shift:
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
| integer_add
;
integer_add:
integer_add '+' integer_mul { $$ = $1 + $3; }
| integer_add '-' integer_mul { $$ = $1 - $3; }
| integer_mul
;
integer_mul:
integer_mul '*' integer_unary { $$ = $1 * $3; }
| integer_mul '/' integer_unary { $$ = $1 / $3; }
| integer_mul '%' integer_unary { $$ = $1 % $3; }
| integer_unary
;
integer_unary:
integer_prim
| '-' integer_unary { $$ = -$2; }
| '~' integer_unary { $$ = ~$2; }
| '!' integer_unary { $$ = !$2; }
;
bytestring:
......@@ -303,6 +457,10 @@ subnode:
{
$$ = name_node($2, $1);
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
$$ = name_node(build_node_delete(), $2);
}
| DT_LABEL subnode
{
add_label(&$2->labels, $1);
......@@ -334,12 +492,41 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
errno = 0;
val = strtoull(s, &e, base);
if (*e)
print_error("bad characters in literal");
else if ((errno == ERANGE)
if (*e) {
size_t uls = strspn(e, "UL");
if (e[uls])
print_error("bad characters in literal");
}
if ((errno == ERANGE)
|| ((bits < 64) && (val >= (1ULL << bits))))
print_error("literal out of range");
else if (errno != 0)
print_error("bad literal");
return val;
}
static unsigned char eval_char_literal(const char *s)
{
int i = 1;
char c = s[0];
if (c == '\0')
{
print_error("empty character literal");
return 0;
}
/*
* If the first character in the character literal is a \ then process
* the remaining characters as an escape encoding. If the first
* character is neither an escape or a terminator it should be the only
* character in the literal and will be returned.
*/
if (c == '\\')
c = get_escape_char(s, &i);
if (s[i] != '\0')
print_error("malformed character literal");
return c;
}
......@@ -82,6 +82,8 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\tSet the physical boot cpu\n");
fprintf(stderr, "\t-f\n");
fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
fprintf(stderr, "\t-i\n");
fprintf(stderr, "\t\tAdd a path to search for include files\n");
fprintf(stderr, "\t-s\n");
fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
fprintf(stderr, "\t-v\n");
......@@ -91,6 +93,9 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
fprintf(stderr, "\t-W [no-]<checkname>\n");
fprintf(stderr, "\t-E [no-]<checkname>\n");
fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
exit(3);
}
......@@ -113,7 +118,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;
while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s"))
while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
!= EOF) {
switch (opt) {
case 'I':
......@@ -149,6 +154,9 @@ int main(int argc, char *argv[])
case 'b':
cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
break;
case 'i':
srcfile_add_search_path(optarg);