DeviceTree updates for 4.6:

- New tool dtx_diff to diff DT files.
 
 - Sync kernel's dtc/libfdt to current dtc repo master.
 
 - Fix for reserved memory regions located in highmem.
 
 - Document standard unit suffixes for DT properties.
 
 - Various DT binding doc updates.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJW7B34AAoJEPr7XbWNvGHDI4QP/0W0s3dvJ4l/TNeu/n1ZN8i7
 H4FYNcNGVEPJMaI4gIV+GOnxJ4hTnEX2ftG9MEZCywVHWNCg4IAaIW1wQ52Sufnc
 Uncc9qO0MMR5Y1Siu/DuLi+ARyPQrke3M/o5xU9XJjSdz9QpnYw1MpMnpAJANomk
 /8Wjn2jEBHDJrxmJ73nE/CAVu8iFyWHTmt5pDQBoQub2NVuAX6rNcVmpmr0PhDMd
 0CKokB+wmLHZEA2R4BBefjLwwKU1WrF/5ytXpsJ01NeZsExagJZz1fQdy3Z6o1Xx
 PRTukmmNhknatNTJOD8XmLr/SWN2CKNuJK5EOoV2opAvN/fc+mrk95DGKzjh5n64
 aCRHzZgKAOYOqdVJKHfJ9hfzgG/zdt4mt1RKhLD+6qZNoSeQSrtikN3DWibPMZQR
 uHRC9fqalx+W4cBH4jakGYrpsbQOaQFjb6vHY8V/auSB2cx97YVuKCawnSerjWZv
 1tu8dqNG0qwt9g0hgA+ycwitulUNSLSvLGp3mxBJXN2ULPHygCw53JUWFQEZhoAa
 JQqZ7lrUSE+AEp6Cwc0sNn07UMoCAoZKbTaurm2rn2RrKMfnirbf/sdZkc9Hq2pg
 TIJOJlmJmvheoCl7894iV1l18ooPqldk6h8d9fc6rngaQYkNaV0c9nlaMLTa2Rwi
 bVztrJItiymIhjIB86Iw
 =hz7v
 -----END PGP SIGNATURE-----

Merge tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull DeviceTree updates from Rob Herring:

 - new tool 'dtx_diff' to diff DT files

 - sync kernel's dtc/libfdt to current dtc repo master

 - fix for reserved memory regions located in highmem

 - document standard unit suffixes for DT properties

 - various DT binding doc updates

* tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
  of: Add vendor prefix for eGalax_eMPIA Technology Inc
  Input: ads7846: Add description how to use internal reference (ADS7846)
  ARM: realview: add EB syscon variants to bindings
  devicetree: bindings: ARM: Use "uV" for micro-volt
  serial: fsl-imx-uart: Fix typo in fsl,dte-mode description
  of: add 'const' for of_property_*_string*() parameter '*np'
  of/unittest: fix infinite loop in of_unittest_destroy_tracked_overlays()
  of: alloc anywhere from memblock if range not specified
  kbuild: Allow using host dtc instead of kernel's copy
  of: resolver: Add missing of_node_get and of_node_put
  of: Add United Radiant Technology Corporation vendor prefix
  dt/bindings: add documentation on standard property unit suffixes
  scripts/dtc: Update to upstream commit b06e55c88b9b
  ARM: boot: Add an implementation of strnlen for libfdt
  scripts/dtc: dtx_diff - add info to error message
  dtc: create tool to diff device trees
This commit is contained in:
Linus Torvalds 2016-03-19 15:15:07 -07:00
commit 31e182363b
25 changed files with 836 additions and 142 deletions

View file

@ -269,6 +269,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb= DTB $@
@ -291,7 +292,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
quiet_cmd_dtc = DTC $@
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
$(DTC) -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)

View file

@ -560,7 +560,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);

View file

@ -73,24 +73,32 @@ static void lexical_error(const char *fmt, ...);
}
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
char *line, *tmp, *fn;
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
line = yytext;
while (!isdigit((unsigned char)*line))
line++;
/* skip digits in line # */
tmp = line;
while (!isspace((unsigned char)*tmp))
tmp++;
/* "NULL"-terminate line # */
*tmp = '\0';
/* start of filename */
fn = strchr(tmp + 1, '"') + 1;
/* strip trailing " from filename */
tmp = strchr(fn, '"');
*tmp = 0;
/* regexp ensures that first and list "
* in the whole yytext are those at
* beginning and end of the filename string */
fnstart = memchr(yytext, '"', yyleng);
for (fnend = yytext + yyleng - 1;
*fnend != '"'; fnend--)
;
assert(fnstart && fnend && (fnend > fnstart));
fn = data_copy_escape_string(fnstart + 1,
fnend - fnstart - 1);
/* Don't allow nuls in filenames */
if (memchr(fn.val, '\0', fn.len - 1))
lexical_error("nul in line number directive");
/* -1 since #line is the number of the next line */
srcpos_set_line(xstrdup(fn), atoi(line) - 1);
srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
data_free(fn);
}
<*><<EOF>> {
@ -153,7 +161,10 @@ static void lexical_error(const char *fmt, ...);
errno = 0;
yylval.integer = strtoull(yytext, &e, 0);
assert(!(*e) || !e[strspn(e, "UL")]);
if (*e && e[strspn(e, "UL")]) {
lexical_error("Bad integer literal '%s'",
yytext);
}
if (errno == ERANGE)
lexical_error("Integer literal '%s' out of range",

View file

@ -951,31 +951,39 @@ case 2:
YY_RULE_SETUP
#line 75 "dtc-lexer.l"
{
char *line, *tmp, *fn;
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
line = yytext;
while (!isdigit((unsigned char)*line))
line++;
/* skip digits in line # */
tmp = line;
while (!isspace((unsigned char)*tmp))
tmp++;
/* "NULL"-terminate line # */
*tmp = '\0';
/* start of filename */
fn = strchr(tmp + 1, '"') + 1;
/* strip trailing " from filename */
tmp = strchr(fn, '"');
*tmp = 0;
/* regexp ensures that first and list "
* in the whole yytext are those at
* beginning and end of the filename string */
fnstart = memchr(yytext, '"', yyleng);
for (fnend = yytext + yyleng - 1;
*fnend != '"'; fnend--)
;
assert(fnstart && fnend && (fnend > fnstart));
fn = data_copy_escape_string(fnstart + 1,
fnend - fnstart - 1);
/* Don't allow nuls in filenames */
if (memchr(fn.val, '\0', fn.len - 1))
lexical_error("nul in line number directive");
/* -1 since #line is the number of the next line */
srcpos_set_line(xstrdup(fn), atoi(line) - 1);
srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
data_free(fn);
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1):
#line 96 "dtc-lexer.l"
#line 104 "dtc-lexer.l"
{
if (!pop_input_file()) {
yyterminate();
@ -985,7 +993,7 @@ case YY_STATE_EOF(V1):
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
#line 102 "dtc-lexer.l"
#line 110 "dtc-lexer.l"
{
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
@ -995,7 +1003,7 @@ YY_RULE_SETUP
YY_BREAK
case 4:
YY_RULE_SETUP
#line 109 "dtc-lexer.l"
#line 117 "dtc-lexer.l"
{
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
@ -1005,7 +1013,7 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
#line 116 "dtc-lexer.l"
#line 124 "dtc-lexer.l"
{
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
@ -1014,7 +1022,7 @@ YY_RULE_SETUP
YY_BREAK
case 6:
YY_RULE_SETUP
#line 122 "dtc-lexer.l"
#line 130 "dtc-lexer.l"
{
DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT();
@ -1023,7 +1031,7 @@ YY_RULE_SETUP
YY_BREAK
case 7:
YY_RULE_SETUP
#line 128 "dtc-lexer.l"
#line 136 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n");
@ -1033,7 +1041,7 @@ YY_RULE_SETUP
YY_BREAK
case 8:
YY_RULE_SETUP
#line 135 "dtc-lexer.l"
#line 143 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n");
@ -1043,7 +1051,7 @@ YY_RULE_SETUP
YY_BREAK
case 9:
YY_RULE_SETUP
#line 142 "dtc-lexer.l"
#line 150 "dtc-lexer.l"
{
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@ -1053,7 +1061,7 @@ YY_RULE_SETUP
YY_BREAK
case 10:
YY_RULE_SETUP
#line 149 "dtc-lexer.l"
#line 157 "dtc-lexer.l"
{
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
@ -1061,7 +1069,10 @@ YY_RULE_SETUP
errno = 0;
yylval.integer = strtoull(yytext, &e, 0);
assert(!(*e) || !e[strspn(e, "UL")]);
if (*e && e[strspn(e, "UL")]) {
lexical_error("Bad integer literal '%s'",
yytext);
}
if (errno == ERANGE)
lexical_error("Integer literal '%s' out of range",
@ -1076,7 +1087,7 @@ YY_RULE_SETUP
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
#line 168 "dtc-lexer.l"
#line 179 "dtc-lexer.l"
{
struct data d;
DPRINT("Character literal: %s\n", yytext);
@ -1100,7 +1111,7 @@ YY_RULE_SETUP
YY_BREAK
case 12:
YY_RULE_SETUP
#line 189 "dtc-lexer.l"
#line 200 "dtc-lexer.l"
{ /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
@ -1109,7 +1120,7 @@ YY_RULE_SETUP
YY_BREAK
case 13:
YY_RULE_SETUP
#line 195 "dtc-lexer.l"
#line 206 "dtc-lexer.l"
{ /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@ -1119,7 +1130,7 @@ YY_RULE_SETUP
YY_BREAK
case 14:
YY_RULE_SETUP
#line 202 "dtc-lexer.l"
#line 213 "dtc-lexer.l"
{
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
@ -1128,7 +1139,7 @@ YY_RULE_SETUP
YY_BREAK
case 15:
YY_RULE_SETUP
#line 208 "dtc-lexer.l"
#line 219 "dtc-lexer.l"
{
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
@ -1137,7 +1148,7 @@ YY_RULE_SETUP
YY_BREAK
case 16:
YY_RULE_SETUP
#line 214 "dtc-lexer.l"
#line 225 "dtc-lexer.l"
{
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@ -1148,7 +1159,7 @@ YY_RULE_SETUP
YY_BREAK
case 17:
YY_RULE_SETUP
#line 222 "dtc-lexer.l"
#line 233 "dtc-lexer.l"
{
DPRINT("Binary Include\n");
return DT_INCBIN;
@ -1157,64 +1168,64 @@ YY_RULE_SETUP
case 18:
/* rule 18 can match eol */
YY_RULE_SETUP
#line 227 "dtc-lexer.l"
#line 238 "dtc-lexer.l"
/* eat whitespace */
YY_BREAK
case 19:
/* rule 19 can match eol */
YY_RULE_SETUP
#line 228 "dtc-lexer.l"
#line 239 "dtc-lexer.l"
/* eat C-style comments */
YY_BREAK
case 20:
/* rule 20 can match eol */
YY_RULE_SETUP
#line 229 "dtc-lexer.l"
#line 240 "dtc-lexer.l"
/* eat C++-style comments */
YY_BREAK
case 21:
YY_RULE_SETUP
#line 231 "dtc-lexer.l"
#line 242 "dtc-lexer.l"
{ return DT_LSHIFT; };
YY_BREAK
case 22:
YY_RULE_SETUP
#line 232 "dtc-lexer.l"
#line 243 "dtc-lexer.l"
{ return DT_RSHIFT; };
YY_BREAK
case 23:
YY_RULE_SETUP
#line 233 "dtc-lexer.l"
#line 244 "dtc-lexer.l"
{ return DT_LE; };
YY_BREAK
case 24:
YY_RULE_SETUP
#line 234 "dtc-lexer.l"
#line 245 "dtc-lexer.l"
{ return DT_GE; };
YY_BREAK
case 25:
YY_RULE_SETUP
#line 235 "dtc-lexer.l"
#line 246 "dtc-lexer.l"
{ return DT_EQ; };
YY_BREAK
case 26:
YY_RULE_SETUP
#line 236 "dtc-lexer.l"
#line 247 "dtc-lexer.l"
{ return DT_NE; };
YY_BREAK
case 27:
YY_RULE_SETUP
#line 237 "dtc-lexer.l"
#line 248 "dtc-lexer.l"
{ return DT_AND; };
YY_BREAK
case 28:
YY_RULE_SETUP
#line 238 "dtc-lexer.l"
#line 249 "dtc-lexer.l"
{ return DT_OR; };
YY_BREAK
case 29:
YY_RULE_SETUP
#line 240 "dtc-lexer.l"
#line 251 "dtc-lexer.l"
{
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
@ -1232,10 +1243,10 @@ YY_RULE_SETUP
YY_BREAK
case 30:
YY_RULE_SETUP
#line 255 "dtc-lexer.l"
#line 266 "dtc-lexer.l"
ECHO;
YY_BREAK
#line 1239 "dtc-lexer.lex.c"
#line 1250 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER:
{
@ -2195,7 +2206,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
#line 254 "dtc-lexer.l"
#line 265 "dtc-lexer.l"

View file

@ -499,9 +499,9 @@ static const yytype_uint16 yyrline[] =
298, 303, 322, 336, 343, 344, 345, 352, 356, 357,
361, 362, 366, 367, 371, 372, 376, 377, 381, 382,
386, 387, 388, 392, 393, 394, 395, 396, 400, 401,
402, 406, 407, 408, 412, 413, 414, 415, 419, 420,
421, 422, 427, 430, 434, 442, 445, 449, 457, 461,
465
402, 406, 407, 408, 412, 413, 422, 431, 435, 436,
437, 438, 443, 446, 450, 458, 461, 465, 473, 477,
481
};
#endif
@ -1909,111 +1909,125 @@ yyreduce:
break;
case 65:
#line 413 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
#line 1915 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 414 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
} else {
ERROR(&(yyloc), "Division by zero");
(yyval.integer) = 0;
}
}
#line 1922 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 66:
#line 414 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
#line 1921 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 423 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
} else {
ERROR(&(yyloc), "Division by zero");
(yyval.integer) = 0;
}
}
#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 69:
#line 420 "dtc-parser.y" /* yacc.c:1646 */
#line 436 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = -(yyvsp[0].integer); }
#line 1927 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 70:
#line 421 "dtc-parser.y" /* yacc.c:1646 */
#line 437 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = ~(yyvsp[0].integer); }
#line 1933 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 71:
#line 422 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = !(yyvsp[0].integer); }
#line 1939 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 72:
#line 427 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = empty_data;
}
#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 71:
#line 438 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = !(yyvsp[0].integer); }
#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 72:
#line 443 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = empty_data;
}
#line 1961 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 73:
#line 431 "dtc-parser.y" /* yacc.c:1646 */
#line 447 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
}
#line 1955 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1969 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 74:
#line 435 "dtc-parser.y" /* yacc.c:1646 */
#line 451 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
}
#line 1963 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1977 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 75:
#line 442 "dtc-parser.y" /* yacc.c:1646 */
#line 458 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.nodelist) = NULL;
}
#line 1971 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 76:
#line 446 "dtc-parser.y" /* yacc.c:1646 */
#line 462 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
}
#line 1979 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 77:
#line 450 "dtc-parser.y" /* yacc.c:1646 */
#line 466 "dtc-parser.y" /* yacc.c:1646 */
{
ERROR(&(yylsp[0]), "Properties must precede subnodes");
YYERROR;
}
#line 1988 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2002 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 78:
#line 458 "dtc-parser.y" /* yacc.c:1646 */
#line 474 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
}
#line 1996 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2010 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 79:
#line 462 "dtc-parser.y" /* yacc.c:1646 */
#line 478 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
}
#line 2004 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2018 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 80:
#line 466 "dtc-parser.y" /* yacc.c:1646 */
#line 482 "dtc-parser.y" /* yacc.c:1646 */
{
add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[0].node);
}
#line 2013 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2027 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
#line 2017 "dtc-parser.tab.c" /* yacc.c:1646 */
#line 2031 "dtc-parser.tab.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@ -2248,7 +2262,7 @@ yyreturn:
#endif
return yyresult;
}
#line 472 "dtc-parser.y" /* yacc.c:1906 */
#line 488 "dtc-parser.y" /* yacc.c:1906 */
void yyerror(char const *s)

View file

@ -410,8 +410,24 @@ integer_add:
integer_mul:
integer_mul '*' integer_unary { $$ = $1 * $3; }
| integer_mul '/' integer_unary { $$ = $1 / $3; }
| integer_mul '%' integer_unary { $$ = $1 % $3; }
| integer_mul '/' integer_unary
{
if ($3 != 0) {
$$ = $1 / $3;
} else {
ERROR(&@$, "Division by zero");
$$ = 0;
}
}
| integer_mul '%' integer_unary
{
if ($3 != 0) {
$$ = $1 % $3;
} else {
ERROR(&@$, "Division by zero");
$$ = 0;
}
}
| integer_unary
;

View file

@ -18,6 +18,8 @@
* USA
*/
#include <sys/stat.h>
#include "dtc.h"
#include "srcpos.h"
@ -104,11 +106,56 @@ static const char * const usage_opts_help[] = {
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;
@ -213,6 +260,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"))

349
scripts/dtc/dtx_diff Executable file
View file

@ -0,0 +1,349 @@
#! /bin/bash
# Copyright (C) 2015 Frank Rowand
#
# 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
# the Free Software Foundation; version 2 of the License.
usage() {
# use spaces instead of tabs in the usage message
cat >&2 <<eod
Usage:
`basename $0` DTx
decompile DTx
`basename $0` DTx_1 DTx_2
diff DTx_1 and DTx_2
-f print full dts in diff (--unified=99999)
-h synonym for --help
-help synonym for --help
--help print this message and exit
-s SRCTREE linux kernel source tree is at path SRCTREE
(default is current directory)
-S linux kernel source tree is at root of current git repo
-u unsorted, do not sort DTx
Each DTx is processed by the dtc compiler to produce a sorted dts source
file. If DTx is a dts source file then it is pre-processed in the same
manner as done for the compile of the dts source file in the Linux kernel
build system ('#include' and '/include/' directives are processed).
If two DTx are provided, the resulting dts source files are diffed.
If DTx is a directory, it is treated as a DT subtree, such as
/proc/device-tree.
If DTx contains the binary blob magic value in the first four bytes,
it is treated as a binary blob (aka .dtb or FDT).
Otherwise DTx is treated as a dts source file (aka .dts).
If this script is not run from the root of the linux source tree,
and DTx utilizes '#include' or '/include/' then the path of the
linux source tree can be provided by '-s SRCTREE' or '-S' so that
include paths will be set properly.
The shell variable \${ARCH} must provide the architecture containing
the dts source file for include paths to be set properly for '#include'
or '/include/' to be processed.
If DTx_1 and DTx_2 are in different architectures, then this script
may not work since \${ARCH} is part of the include path. Two possible
workarounds:
`basename $0` \\
<(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\
<(ARCH=arch_of_dtx_2 `basename $0` DTx_2)
`basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
`basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
`basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
rm tmp_dtx_1.dts tmp_dtx_2.dts
If DTx_1 and DTx_2 are in different directories, then this script will
add the path of DTx_1 and DTx_2 to the include paths. If DTx_2 includes
a local file that exists in both the path of DTx_1 and DTx_2 then the
file in the path of DTx_1 will incorrectly be included. Possible
workaround:
`basename $0` DTx_1 >tmp_dtx_1.dts
`basename $0` DTx_2 >tmp_dtx_2.dts
`basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
rm tmp_dtx_1.dts tmp_dtx_2.dts
eod
}
compile_to_dts() {
dtx="$1"
if [ -d "${dtx}" ] ; then
# ----- input is file tree
if ( ! ${DTC} -I fs ${dtx} ) ; then
exit 3
fi
elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then
magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}`
if [ "${magic}" = "d00dfeed" ] ; then
# ----- input is FDT (binary blob)
if ( ! ${DTC} -I dtb ${dtx} ) ; then
exit 3
fi
return
fi
# ----- input is DTS (source)
if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
| ${DTC} -I dts ) ; then
return
fi
echo "" >&2
echo "Possible hints to resolve the above error:" >&2
echo " (hints might not fix the problem)" >&2
hint_given=0
if [ "${ARCH}" = "" ] ; then
hint_given=1
echo "" >&2
echo " shell variable \$ARCH not set" >&2
fi
dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'`
if [ "${dtx_arch}" != "" -a "${dtx_arch}" != "${ARCH}" ] ; then
hint_given=1
echo "" >&2
echo " architecture ${dtx_arch} is in file path," >&2
echo " but does not match shell variable \$ARCH" >&2
echo " >>\$ARCH<< is: >>${ARCH}<<" >&2
fi
if [ ! -d ${srctree}/arch/${ARCH} ] ; then
hint_given=1
echo "" >&2
echo " ${srctree}/arch/${ARCH}/ does not exist" >&2
echo " Is \$ARCH='${ARCH}' correct?" >&2
echo " Possible fix: use '-s' option" >&2
git_root=`git rev-parse --show-toplevel 2>/dev/null`
if [ -d ${git_root}/arch/ ] ; then
echo " Possible fix: use '-S' option" >&2
fi
fi
if [ $hint_given = 0 ] ; then
echo "" >&2
echo " No hints available." >&2
fi
echo "" >&2
exit 3
else
echo "" >&2
echo "ERROR: ${dtx} does not exist or is not readable" >&2
echo "" >&2
exit 2
fi
}
# ----- start of script
cmd_diff=0
diff_flags="-u"
dtx_file_1=""
dtx_file_2=""
dtc_sort="-s"
help=0
srctree=""
while [ $# -gt 0 ] ; do
case $1 in
-f )
diff_flags="--unified=999999"
shift
;;
-h | -help | --help )
help=1
shift
;;
-s )
srctree="$2"
shift 2
;;
-S )
git_root=`git rev-parse --show-toplevel 2>/dev/null`
srctree="${git_root}"
shift
;;
-u )
dtc_sort=""
shift
;;
*)
if [ "${dtx_file_1}" = "" ] ; then
dtx_file_1="$1"
elif [ "${dtx_file_2}" = "" ] ; then
dtx_file_2="$1"
else
echo "" >&2
echo "ERROR: Unexpected parameter: $1" >&2
echo "" >&2
exit 2
fi
shift
;;
esac
done
if [ "${srctree}" = "" ] ; then
srctree="."
fi
if [ "${dtx_file_2}" != "" ]; then
cmd_diff=1
fi
if (( ${help} )) ; then
usage
exit 1
fi
# this must follow check for ${help}
if [ "${dtx_file_1}" = "" ]; then
echo "" >&2
echo "ERROR: parameter DTx required" >&2
echo "" >&2
exit 2
fi
# ----- prefer dtc from linux kernel, allow fallback to dtc in $PATH
if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then
__KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}"
elif [ "${KBUILD_OUTPUT}" = "" ] ; then
__KBUILD_OUTPUT="."
else
__KBUILD_OUTPUT="${KBUILD_OUTPUT}"
fi
DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc"
if [ ! -x ${DTC} ] ; then
__DTC="dtc"
if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config ; then
make_command='
make scripts'
else
make_command='
Enable CONFIG_DTC in the kernel configuration
make scripts'
fi
if ( ! which ${__DTC} >/dev/null ) ; then
# use spaces instead of tabs in the error message
cat >&2 <<eod
ERROR: unable to find a 'dtc' program
Preferred 'dtc' (built from Linux kernel source tree) was not found or
is not executable.
'dtc' is: ${DTC}
If it does not exist, create it from the root of the Linux source tree:
${make_command}
If not at the root of the Linux kernel source tree -s SRCTREE or -S
may need to be specified to find 'dtc'.
If 'O=\${dir}' is specified in your Linux builds, this script requires
'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH
before running.
If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run
this script from the root of the Linux kernel source tree is required.
Fallback '${__DTC}' was also not in \${PATH} or is not executable.
eod
exit 2
fi
DTC=${__DTC}
fi
# ----- cpp and dtc flags same as for linux source tree build of .dtb files,
# plus directories of the dtx file(s)
dtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`"
dtx_path_2_dtc_include=""
if (( ${cmd_diff} )) ; then
dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`"
fi
cpp_flags="\
-nostdinc \
-I${srctree}/arch/${ARCH}/boot/dts \
-I${srctree}/arch/${ARCH}/boot/dts/include \
-I${srctree}/drivers/of/testcase-data \
-undef -D__DTS__"
dtc_flags="\
-i ${srctree}/arch/${ARCH}/boot/dts/ \
-i ${srctree}/kernel/dts \
${dtx_path_1_dtc_include} \
${dtx_path_2_dtc_include}"
DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
# ----- do the diff or decompile
if (( ${cmd_diff} )) ; then
diff ${diff_flags} \
<(compile_to_dts "${dtx_file_1}") \
<(compile_to_dts "${dtx_file_2}")
else
compile_to_dts "${dtx_file_1}"
fi

View file

@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
const char *p;
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
if ((absoffset < offset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;
if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
p = _fdt_offset_ptr(fdt, offset);
if (p + len < p)
return NULL;
return p;
return _fdt_offset_ptr(fdt, offset);
}
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)

View file

@ -538,6 +538,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
return 0;
}
int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
{
const char *list, *end;
int length, count = 0;
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
return -length;
end = list + length;
while (list < end) {
length = strnlen(list, end - list) + 1;
/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end)
return -FDT_ERR_BADVALUE;
list += length;
count++;
}
return count;
}
int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
const char *string)
{
int length, len, idx = 0;
const char *list, *end;
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
return -length;
len = strlen(string) + 1;
end = list + length;
while (list < end) {
length = strnlen(list, end - list) + 1;
/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end)
return -FDT_ERR_BADVALUE;
if (length == len && memcmp(list, string, length) == 0)
return idx;
list += length;
idx++;
}
return -FDT_ERR_NOTFOUND;
}
const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
const char *property, int idx,
int *lenp)
{
const char *list, *end;
int length;
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list) {
if (lenp)
*lenp = length;
return NULL;
}
end = list + length;
while (list < end) {
length = strnlen(list, end - list) + 1;
/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end) {
if (lenp)
*lenp = -FDT_ERR_BADVALUE;
return NULL;
}
if (idx == 0) {
if (lenp)
*lenp = length - 1;
return list;
}
list += length;
idx--;
}
if (lenp)
*lenp = -FDT_ERR_NOTFOUND;
return NULL;
}
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
const char *compatible)
{

View file

@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
if (((p + oldlen) < p) || ((p + oldlen) > end))
return -FDT_ERR_BADOFFSET;
if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
return -FDT_ERR_BADOFFSET;
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
return -FDT_ERR_NOSPACE;
memmove(p + newlen, p + oldlen, end - p - oldlen);

View file

@ -121,7 +121,12 @@
/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
* or similar property with a bad format or value */
#define FDT_ERR_MAX 14
#define FDT_ERR_BADVALUE 15
/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
* value. For example: a property expected to contain a string list
* is not NUL-terminated within the length of its value. */
#define FDT_ERR_MAX 15
/**********************************************************************/
/* Low-level functions (you probably don't need these) */
@ -457,8 +462,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
* @namelen: number of characters of name to consider
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* Identical to fdt_get_property_namelen(), but only examine the first
* namelen characters of name for matching the property name.
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
*/
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset,
@ -868,6 +873,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
/**
* fdt_stringlist_count - count the number of strings in a string list
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @return:
* the number of strings in the given property
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
*/
int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
/**
* fdt_stringlist_search - find a string in a string list and return its index
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @string: string to look up in the string list
*
* Note that it is possible for this function to succeed on property values
* that are not NUL-terminated. That's because the function will stop after
* finding the first occurrence of @string. This can for example happen with
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
* @return:
* the index of the string in the list of strings
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
* the given string
*/
int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
const char *string);
/**
* fdt_stringlist_get() - obtain the string at a given index in a string list
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @index: index of the string to return
* @lenp: return location for the string length or an error code on failure
*
* Note that this will successfully extract strings from properties with
* non-NUL-terminated values. For example on small-valued cell properties
* this function will return the empty string.
*
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
* @return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
* the following negative error codes will be returned in the lenp parameter
* (if non-NULL):
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
*/
const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
const char *property, int index,
int *lenp);
/**********************************************************************/
/* Read-only functions (addressing related) */
/**********************************************************************/

View file

@ -152,7 +152,6 @@ char get_escape_char(const char *s, int *i)
int j = *i + 1;
char val;
assert(c);
switch (c) {
case 'a':
val = '\a';
@ -349,7 +348,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 +374,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 ? " " : "");

View file

@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.1-g9d3649bd"
#define DTC_VERSION "DTC 1.4.1-gb06e55c8"