diff --git a/data.c b/data.c index d3b55f9..1907a1a 100644 --- a/data.c +++ b/data.c @@ -197,6 +197,33 @@ struct data data_append_data(struct data d, void *p, int len) return d; } +struct data data_merge(struct data d1, struct data d2) +{ + struct data d; + struct fixup **ff; + struct fixup *f, *f2; + + d = data_append_data(d1, d2.val, d2.len); + + /* Extract d2's fixups */ + f2 = d2.refs; + d2.refs = NULL; + + /* Tack them onto d's list of fixups */ + ff = &d.refs; + while (*ff) + ff = &((*ff)->next); + *ff = f2; + + /* And correct them for their new position */ + for (f = f2; f; f = f->next) + f->offset += d1.len; + + data_free(d2); + + return d; +} + struct data data_append_cell(struct data d, cell_t word) { cell_t beword = cpu_to_be32(word); diff --git a/dtc-lexer.l b/dtc-lexer.l index c082228..6146bad 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -123,6 +123,15 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return ']'; } +, { /* Technically this is a valid property name, + but we'd rather use it as punctuation, so detect it + here in preference */ + yylloc.first_line = yylineno; + DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], + (unsigned)yytext[0]); + return yytext[0]; + } + {PROPCHAR}+ { yylloc.first_line = yylineno; DPRINT("PropName: %s\n", yytext); diff --git a/dtc-parser.y b/dtc-parser.y index 16d2277..bd725fe 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -58,6 +58,7 @@ extern struct boot_info *the_boot_info; %token DT_REF %type propdata +%type propdataprefix %type memreserve %type memreserves %type celllist @@ -121,9 +122,15 @@ propdef: label DT_PROPNAME '=' propdata ';' { } ; -propdata: DT_STRING { $$ = $1; } - | '<' celllist '>' { $$ = $2; } - | '[' bytestring ']' { $$ = $2; } +propdata: propdataprefix DT_STRING { $$ = data_merge($1, $2); } + | propdataprefix '<' celllist '>' { + $$ = data_merge(data_append_align($1, sizeof(cell_t)), $3); + } + | propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); } + ; + +propdataprefix: propdata ',' { $$ = $1; } + | /* empty */ { $$ = empty_data; } ; celllist: celllist DT_CELL { $$ = data_append_cell($1, $2); } diff --git a/dtc.h b/dtc.h index 42e9de0..8d3964c 100644 --- a/dtc.h +++ b/dtc.h @@ -119,6 +119,7 @@ struct data data_copy_escape_string(char *s, int len); struct data data_copy_file(FILE *f, size_t len); struct data data_append_data(struct data d, void *p, int len); +struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); struct data data_append_re(struct data d, struct reserve_entry *re); struct data data_append_addr(struct data d, u64 addr); diff --git a/test.dts b/test.dts index 742d874..ed2b178 100644 --- a/test.dts +++ b/test.dts @@ -4,7 +4,7 @@ / { model = "MyBoardName"; - compatible = "MyBoardFamilyName"; + compatible = "MyBoardName", "MyBoardFamilyName"; #address-cells = <2>; #size-cells = <2>; @@ -39,6 +39,7 @@ string = "\xff\0stuffstuff\t\t\t\n\n\n"; blob = [0a 0b 0c 0d de ea ad be ef]; ref = < &/memory@0 >; + mixed = "abc", [1234], ; }; memory@0 {