diff options
Diffstat (limited to 'scripts/dtc')
-rw-r--r-- | scripts/dtc/checks.c | 2 | ||||
-rw-r--r-- | scripts/dtc/dtc-lexer.l | 39 | ||||
-rw-r--r-- | scripts/dtc/dtc-lexer.lex.c_shipped | 101 | ||||
-rw-r--r-- | scripts/dtc/dtc-parser.tab.c_shipped | 84 | ||||
-rw-r--r-- | scripts/dtc/dtc-parser.y | 20 | ||||
-rw-r--r-- | scripts/dtc/dtc.c | 62 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt.c | 13 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_ro.c | 100 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_rw.c | 2 | ||||
-rw-r--r-- | scripts/dtc/libfdt/libfdt.h | 73 | ||||
-rw-r--r-- | scripts/dtc/util.c | 3 | ||||
-rw-r--r-- | scripts/dtc/version_gen.h | 2 |
12 files changed, 390 insertions, 111 deletions
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index e81a8c74b8d2..0c03ac9159c1 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -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); diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 0ee1caf03dd0..790fbf6cf2d7 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -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", diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index 11cd78e72305..ba525c2f9fc2 100644 --- a/scripts/dtc/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped @@ -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" diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index 116458c8dfc4..31cec50a1265 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -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 */ +#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 71: -#line 422 "dtc-parser.y" /* yacc.c:1646 */ +#line 438 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = !(yyvsp[0].integer); } -#line 1939 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 72: -#line 427 "dtc-parser.y" /* yacc.c:1646 */ +#line 443 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = empty_data; } -#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ +#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) diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 5a897e36562d..000873f070fd 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -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 ; diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index 8c4add69a765..5fa23c406266 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -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")) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 2ce6a44179de..22286a1aaeaf 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -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) diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index a65e4b5b72b6..e5b313682007 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -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) { diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 70adec6c371b..8be02b1f68f3 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -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); diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ea35ac3c9be4..59ca33976e56 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -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) */ /**********************************************************************/ diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 9d65226df9e4..fb124eea4919 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -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 ? " " : ""); diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 5b8c7d53d608..11d93e6d8220 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.1-g9d3649bd" +#define DTC_VERSION "DTC 1.4.1-gb06e55c8" |