diff --git a/util/dtc/dtc-lexer.l b/util/dtc/dtc-lexer.l index 239e4ccafb..d299befbf7 100644 --- a/util/dtc/dtc-lexer.l +++ b/util/dtc/dtc-lexer.l @@ -36,8 +36,6 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) #include "dtc-parser.tab.h" -/*#define LEXDEBUG 1*/ - #ifdef LEXDEBUG #define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) #else @@ -46,6 +44,21 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) char *code = 0; +YY_BUFFER_STATE bstack = NULL; + +void +switchin(FILE *f){ + YY_BUFFER_STATE b; + bstack = yy_current_buffer; + b = yy_create_buffer(f, 8192); + yy_switch_to_buffer(b); + +} + +void +switchback(void){ + yy_switch_to_buffer(bstack); +} %} %% @@ -68,7 +81,7 @@ char *code = 0; } .* { - DPRINT("Matchingin passthrough %s\n", yytext); + DPRINT("Matching in passthrough %s\n", yytext); /* you tell me why echo does not work */ /*ECHO;*/ strcat(code, yytext); @@ -101,6 +114,12 @@ char *code = 0; return ';'; } +"/config/" { + yylloc.first_line = yylineno; + DPRINT("Keyword: /config/\n"); + return DT_CONFIG; + } + [0-9a-fA-F]+ { yylloc.first_line = yylineno; if ((unsigned long)yyleng > 2*sizeof(yylval.cval)) { diff --git a/util/dtc/dtc-parser.y b/util/dtc/dtc-parser.y index 76257ef5b6..485267fc63 100644 --- a/util/dtc/dtc-parser.y +++ b/util/dtc/dtc-parser.y @@ -23,7 +23,6 @@ %{ #include "dtc.h" - int yylex (void); void yyerror (char const *); @@ -56,13 +55,11 @@ extern struct boot_info *the_boot_info; %token DT_UNIT %token DT_LABEL %token DT_REF -%token DT_CONFIG +%token DT_FILENAME +%token DT_CONFIG %type propdata %type memreserve -/* -%type config - */ %type memreserves %type celllist %type bytestring @@ -72,6 +69,7 @@ extern struct boot_info *the_boot_info; %type devicetree %type nodedef %type subnode +%type config %type subnodes %type label %type nodename @@ -107,8 +105,8 @@ devicetree: '/' nodedef { } ; -nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); +nodedef: '{' config proplist subnodes '}' ';' { + $$ = build_node($2, $3, $4); } ; @@ -120,21 +118,35 @@ proplist: propdef proplist { } ; -/* I doubt we will do this -config: DT_CONFIG '(' includepath ',' structname ')' ';' { - $$ = setupconfig($3, $5); +config: DT_CONFIG '(' + includepath { + void switchin(FILE *f); + + /* switch ... */ + char path[1024]; + FILE *f; + /* TODO: keep track of which of these we have read in. If we have already done it, then + * don't do it twice. + */ + sprintf(path, "%s/dts", $3.val); + f = fopen(path, "r"); + if (! f){ + perror(path); + exit(1); + } + switchin(f); + } '{' proplist '}' ';' { + void switchback(void); + switchback(); } + ')' ';' { $$ = $6} | - { - $$ = NULL; - } - ; - */ - -includepath: DT_STRING { $$ = $1; } ; -structname: DT_STRING {$$ = $1; } +includepath: DT_STRING { $$ = $1; } + ; + +structname: DT_FILENAME {$$ = $1; } ; propdef: label DT_PROPNAME '=' propdata ';' { diff --git a/util/dtc/dtc.h b/util/dtc/dtc.h index 93bdfce56e..954468542d 100644 --- a/util/dtc/dtc.h +++ b/util/dtc/dtc.h @@ -150,6 +150,7 @@ struct node { char *name; struct property *proplist; struct node *children; + struct property *config; struct node *parent; struct node *next_sibling; @@ -170,10 +171,13 @@ struct node { #define for_each_child(n, c) \ for ((c) = (n)->children; (c); (c) = (c)->next_sibling) +#define for_each_config(n, p) \ + for ((p) = (n)->config; (p); (p) = (p)->next) + struct property *build_property(char *name, struct data val, char *label); struct property *chain_property(struct property *first, struct property *list); -struct node *build_node(struct property *proplist, struct node *children); +struct node *build_node(struct property *config, struct property *proplist, struct node *children); struct node *name_node(struct node *node, char *name, char *label); struct node *chain_node(struct node *first, struct node *list); diff --git a/util/dtc/flattree.c b/util/dtc/flattree.c index f28a5168f6..8f4771f73e 100644 --- a/util/dtc/flattree.c +++ b/util/dtc/flattree.c @@ -432,6 +432,7 @@ static void linuxbios_emit_data(void *e, struct property *p) FILE *f = e; int i; char *cleanname; + int vallen = d.len > 4 ? 4 : d.len; /* nothing to do? */ if (d.len == 0) @@ -441,8 +442,10 @@ static void linuxbios_emit_data(void *e, struct property *p) fprintf(f, "\t.%s = {", cleanname); free(cleanname); - for(i = 0; i < d.len; i++) - fprintf(f, "0x%02x,", d.val[i]); + /* sorry, but right now, u32 is all you get */ + fprintf(f, "0"); + for(i = 0; i < vallen; i++) + fprintf(f, "|(0x%02x<<%d)", d.val[i], (3-i)*8); fprintf(f, "},\n"); } @@ -649,33 +652,35 @@ static void flatten_tree_emit_structdecls(struct node *tree, struct emitter *emi int seen_name_prop = 0; FILE *f = etarget; - treename = clean(tree->name, 0); - emit->beginnode(etarget, treename); + if (tree->config){ + treename = clean(tree->name, 0); + emit->beginnode(etarget, treename); #if 0 - if (vi->flags & FTF_FULLPATH) - emit->string(etarget, tree->fullpath, 0); - else - emit->string(etarget, tree->name, 0); + if (vi->flags & FTF_FULLPATH) + emit->string(etarget, tree->fullpath, 0); + else + emit->string(etarget, tree->name, 0); #endif - for_each_property(tree, prop) { - char *cleanname; - if (streq(prop->name, "name")) - seen_name_prop = 1; - cleanname = clean(prop->name, 0); - fprintf(f, "\tu8 %s[%d];\n", cleanname, prop->val.len); - free(cleanname); + for_each_config(tree, prop) { + char *cleanname; + if (streq(prop->name, "name")) + seen_name_prop = 1; + cleanname = clean(prop->name, 0); + fprintf(f, "\tu32 %s;\n", cleanname); + free(cleanname); - } + } #if 0 - if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) { - fprintf(f, "\tu8 %s[%d];\n", prop->name, prop->val.len); - } + if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) { + fprintf(f, "\tu8 %s[%d];\n", prop->name, prop->val.len); + } #endif - emit->endnode(etarget, treename); - free(treename); + emit->endnode(etarget, treename); + free(treename); + } for_each_child(tree, child) { flatten_tree_emit_structdecls(child, emit, etarget, strbuf, vi); @@ -692,7 +697,7 @@ static void flatten_tree_emit_structinits(struct node *tree, struct emitter *emi { char *treename; - struct property *prop; + struct property *configprop, *dtsprop; struct node *child; int seen_name_prop = 0; FILE *f = etarget; @@ -708,6 +713,52 @@ static void flatten_tree_emit_structinits(struct node *tree, struct emitter *emi else emit->string(etarget, tree->name, 0); #endif + /* here is the real action. What we have to do, given a -> config entry, is this: + * foreach property(tree->config) + * search for the property in this node's property list + * if found, then emit that with its initialization + * else emit the one from the config + * if there is a property in the list not in the config -> error + * later on, get smart, and remove properties as they are found. + * for now, be stupid. + */ + + if (tree->config){ + treename = clean(tree->name, 0); + emit->beginnode(etarget, treename); +#if 0 + if (vi->flags & FTF_FULLPATH) + emit->string(etarget, tree->fullpath, 0); + else + emit->string(etarget, tree->name, 0); +#endif + + for_each_config(tree, configprop) { + char *cleanname; + int found = 0; +#if 0 + cleanname = clean(configprop->name, 0); + fprintf(f, "\tu32 %s = \n", cleanname); + free(cleanname); +#endif + for_each_property(tree, dtsprop) { + if (streq(dtsprop->name,configprop->name)){ + emit->data(etarget, dtsprop); + found = 1; + } + } + if (! found) + emit->data(etarget, configprop); + + } +#if 0 + if ((vi->flags & FTF_NAMEPROPS) && !seen_name_configprop) { + fprintf(f, "\tu8 %s[%d];\n", configprop->name, configprop->val.len); + } +#endif + emit->endnode(etarget, treename); + free(treename); + } /* for_each_property(tree, prop) { if (streq(prop->name, "name")) @@ -739,7 +790,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit, void *etarget, struct data *strbuf, struct version_info *vi) { - struct property *prop; + struct property *prop, *config; struct node *child; int seen_name_prop = 0; @@ -787,6 +838,26 @@ static void flatten_tree(struct node *tree, struct emitter *emit, flatten_tree(child, emit, etarget, strbuf, vi); } + for_each_config(tree, prop) { + int nameoff; + + if (streq(prop->name, "name")) + seen_name_prop = 1; + + nameoff = stringtable_insert(strbuf, prop->name); + + emit->property(etarget, prop->label); + emit->cell(etarget, prop->val.len); + emit->cell(etarget, nameoff); + + if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8)) + emit->align(etarget, 8); + + emit->data(etarget, prop); + emit->align(etarget, sizeof(cell_t)); + } + + emit->endnode(etarget, tree->label); } @@ -1149,7 +1220,7 @@ void dt_to_linuxbios(FILE *f, struct boot_info *bi, int version, int boot_cpuid_ fprintf(f, "%s\n", code); -// flatten_tree_emit_structdecls(bi->dt, &linuxbios_emitter, f, &strbuf, vi); + flatten_tree_emit_structdecls(bi->dt, &linuxbios_emitter, f, &strbuf, vi); flatten_tree_emit_structinits(bi->dt, &linuxbios_emitter, f, &strbuf, vi); data_free(strbuf); /* */ @@ -1360,7 +1431,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct node *node; u32 val; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); if (flags & FTF_FULLPATH) { node->fullpath = flat_read_string(dtbuf); diff --git a/util/dtc/fstree.c b/util/dtc/fstree.c index a5bf9d3114..20ae7b9102 100644 --- a/util/dtc/fstree.c +++ b/util/dtc/fstree.c @@ -34,7 +34,7 @@ static struct node *read_fstree(char *dirname) if (! d) die("opendir(): %s\n", strerror(errno)); - tree = build_node(NULL, NULL); + tree = build_node(NULL, NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpnam; diff --git a/util/dtc/livetree.c b/util/dtc/livetree.c index bacee0df1c..80a16d1612 100644 --- a/util/dtc/livetree.c +++ b/util/dtc/livetree.c @@ -48,7 +48,7 @@ struct property *chain_property(struct property *first, struct property *list) return first; } -struct node *build_node(struct property *proplist, struct node *children) +struct node *build_node(struct property *config, struct property *proplist, struct node *children) { static struct node *last_node = NULL; @@ -57,6 +57,7 @@ struct node *build_node(struct property *proplist, struct node *children) memset(new, 0, sizeof(*new)); + new->config = config; new->proplist = proplist; new->children = children;