19fffb55fSDavid Gibson /* 29fffb55fSDavid Gibson * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 39fffb55fSDavid Gibson * 49fffb55fSDavid Gibson * 59fffb55fSDavid Gibson * This program is free software; you can redistribute it and/or 69fffb55fSDavid Gibson * modify it under the terms of the GNU General Public License as 79fffb55fSDavid Gibson * published by the Free Software Foundation; either version 2 of the 89fffb55fSDavid Gibson * License, or (at your option) any later version. 99fffb55fSDavid Gibson * 109fffb55fSDavid Gibson * This program is distributed in the hope that it will be useful, 119fffb55fSDavid Gibson * but WITHOUT ANY WARRANTY; without even the implied warranty of 129fffb55fSDavid Gibson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 139fffb55fSDavid Gibson * General Public License for more details. 149fffb55fSDavid Gibson * 159fffb55fSDavid Gibson * You should have received a copy of the GNU General Public License 169fffb55fSDavid Gibson * along with this program; if not, write to the Free Software 179fffb55fSDavid Gibson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 189fffb55fSDavid Gibson * USA 199fffb55fSDavid Gibson */ 209fffb55fSDavid Gibson 219fffb55fSDavid Gibson #include "dtc.h" 229fffb55fSDavid Gibson #include "srcpos.h" 239fffb55fSDavid Gibson 249fffb55fSDavid Gibson extern FILE *yyin; 259fffb55fSDavid Gibson extern int yyparse(void); 26cd296721SStephen Warren extern YYLTYPE yylloc; 279fffb55fSDavid Gibson 28*6f05afcbSRob Herring struct dt_info *parser_output; 2947605971SRob Herring bool treesource_error; 309fffb55fSDavid Gibson 31*6f05afcbSRob Herring struct dt_info *dt_from_source(const char *fname) 329fffb55fSDavid Gibson { 33*6f05afcbSRob Herring parser_output = NULL; 3447605971SRob Herring treesource_error = false; 359fffb55fSDavid Gibson 36658f29a5SJohn Bonesio srcfile_push(fname); 37658f29a5SJohn Bonesio yyin = current_srcfile->f; 38cd296721SStephen Warren yylloc.file = current_srcfile; 399fffb55fSDavid Gibson 409fffb55fSDavid Gibson if (yyparse() != 0) 419fffb55fSDavid Gibson die("Unable to parse input tree\n"); 429fffb55fSDavid Gibson 439fffb55fSDavid Gibson if (treesource_error) 449fffb55fSDavid Gibson die("Syntax error parsing input tree\n"); 459fffb55fSDavid Gibson 46*6f05afcbSRob Herring return parser_output; 479fffb55fSDavid Gibson } 489fffb55fSDavid Gibson 499fffb55fSDavid Gibson static void write_prefix(FILE *f, int level) 509fffb55fSDavid Gibson { 519fffb55fSDavid Gibson int i; 529fffb55fSDavid Gibson 539fffb55fSDavid Gibson for (i = 0; i < level; i++) 549fffb55fSDavid Gibson fputc('\t', f); 559fffb55fSDavid Gibson } 569fffb55fSDavid Gibson 5747605971SRob Herring static bool isstring(char c) 589fffb55fSDavid Gibson { 5947605971SRob Herring return (isprint((unsigned char)c) 609fffb55fSDavid Gibson || (c == '\0') 619fffb55fSDavid Gibson || strchr("\a\b\t\n\v\f\r", c)); 629fffb55fSDavid Gibson } 639fffb55fSDavid Gibson 649fffb55fSDavid Gibson static void write_propval_string(FILE *f, struct data val) 659fffb55fSDavid Gibson { 669fffb55fSDavid Gibson const char *str = val.val; 679fffb55fSDavid Gibson int i; 689fffb55fSDavid Gibson struct marker *m = val.markers; 699fffb55fSDavid Gibson 709fffb55fSDavid Gibson assert(str[val.len-1] == '\0'); 719fffb55fSDavid Gibson 72658f29a5SJohn Bonesio while (m && (m->offset == 0)) { 73658f29a5SJohn Bonesio if (m->type == LABEL) 749fffb55fSDavid Gibson fprintf(f, "%s: ", m->ref); 759fffb55fSDavid Gibson m = m->next; 769fffb55fSDavid Gibson } 779fffb55fSDavid Gibson fprintf(f, "\""); 78658f29a5SJohn Bonesio 79658f29a5SJohn Bonesio for (i = 0; i < (val.len-1); i++) { 80658f29a5SJohn Bonesio char c = str[i]; 819fffb55fSDavid Gibson 829fffb55fSDavid Gibson switch (c) { 839fffb55fSDavid Gibson case '\a': 849fffb55fSDavid Gibson fprintf(f, "\\a"); 859fffb55fSDavid Gibson break; 869fffb55fSDavid Gibson case '\b': 879fffb55fSDavid Gibson fprintf(f, "\\b"); 889fffb55fSDavid Gibson break; 899fffb55fSDavid Gibson case '\t': 909fffb55fSDavid Gibson fprintf(f, "\\t"); 919fffb55fSDavid Gibson break; 929fffb55fSDavid Gibson case '\n': 939fffb55fSDavid Gibson fprintf(f, "\\n"); 949fffb55fSDavid Gibson break; 959fffb55fSDavid Gibson case '\v': 969fffb55fSDavid Gibson fprintf(f, "\\v"); 979fffb55fSDavid Gibson break; 989fffb55fSDavid Gibson case '\f': 999fffb55fSDavid Gibson fprintf(f, "\\f"); 1009fffb55fSDavid Gibson break; 1019fffb55fSDavid Gibson case '\r': 1029fffb55fSDavid Gibson fprintf(f, "\\r"); 1039fffb55fSDavid Gibson break; 1049fffb55fSDavid Gibson case '\\': 1059fffb55fSDavid Gibson fprintf(f, "\\\\"); 1069fffb55fSDavid Gibson break; 1079fffb55fSDavid Gibson case '\"': 1089fffb55fSDavid Gibson fprintf(f, "\\\""); 1099fffb55fSDavid Gibson break; 1109fffb55fSDavid Gibson case '\0': 1119fffb55fSDavid Gibson fprintf(f, "\", "); 11247605971SRob Herring while (m && (m->offset <= (i + 1))) { 113658f29a5SJohn Bonesio if (m->type == LABEL) { 114658f29a5SJohn Bonesio assert(m->offset == (i+1)); 115658f29a5SJohn Bonesio fprintf(f, "%s: ", m->ref); 116658f29a5SJohn Bonesio } 117658f29a5SJohn Bonesio m = m->next; 118658f29a5SJohn Bonesio } 119658f29a5SJohn Bonesio fprintf(f, "\""); 1209fffb55fSDavid Gibson break; 1219fffb55fSDavid Gibson default: 12247605971SRob Herring if (isprint((unsigned char)c)) 1239fffb55fSDavid Gibson fprintf(f, "%c", c); 1249fffb55fSDavid Gibson else 1259fffb55fSDavid Gibson fprintf(f, "\\x%02hhx", c); 1269fffb55fSDavid Gibson } 1279fffb55fSDavid Gibson } 1289fffb55fSDavid Gibson fprintf(f, "\""); 1299fffb55fSDavid Gibson 1309fffb55fSDavid Gibson /* Wrap up any labels at the end of the value */ 1319fffb55fSDavid Gibson for_each_marker_of_type(m, LABEL) { 1329fffb55fSDavid Gibson assert (m->offset == val.len); 1339fffb55fSDavid Gibson fprintf(f, " %s:", m->ref); 1349fffb55fSDavid Gibson } 1359fffb55fSDavid Gibson } 1369fffb55fSDavid Gibson 1379fffb55fSDavid Gibson static void write_propval_cells(FILE *f, struct data val) 1389fffb55fSDavid Gibson { 1399fffb55fSDavid Gibson void *propend = val.val + val.len; 1409fffb55fSDavid Gibson cell_t *cp = (cell_t *)val.val; 1419fffb55fSDavid Gibson struct marker *m = val.markers; 1429fffb55fSDavid Gibson 1439fffb55fSDavid Gibson fprintf(f, "<"); 1449fffb55fSDavid Gibson for (;;) { 1459fffb55fSDavid Gibson while (m && (m->offset <= ((char *)cp - val.val))) { 1469fffb55fSDavid Gibson if (m->type == LABEL) { 1479fffb55fSDavid Gibson assert(m->offset == ((char *)cp - val.val)); 1489fffb55fSDavid Gibson fprintf(f, "%s: ", m->ref); 1499fffb55fSDavid Gibson } 1509fffb55fSDavid Gibson m = m->next; 1519fffb55fSDavid Gibson } 1529fffb55fSDavid Gibson 1539fffb55fSDavid Gibson fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); 1549fffb55fSDavid Gibson if ((void *)cp >= propend) 1559fffb55fSDavid Gibson break; 1569fffb55fSDavid Gibson fprintf(f, " "); 1579fffb55fSDavid Gibson } 1589fffb55fSDavid Gibson 1599fffb55fSDavid Gibson /* Wrap up any labels at the end of the value */ 1609fffb55fSDavid Gibson for_each_marker_of_type(m, LABEL) { 1619fffb55fSDavid Gibson assert (m->offset == val.len); 1629fffb55fSDavid Gibson fprintf(f, " %s:", m->ref); 1639fffb55fSDavid Gibson } 1649fffb55fSDavid Gibson fprintf(f, ">"); 1659fffb55fSDavid Gibson } 1669fffb55fSDavid Gibson 1679fffb55fSDavid Gibson static void write_propval_bytes(FILE *f, struct data val) 1689fffb55fSDavid Gibson { 1699fffb55fSDavid Gibson void *propend = val.val + val.len; 1709fffb55fSDavid Gibson const char *bp = val.val; 1719fffb55fSDavid Gibson struct marker *m = val.markers; 1729fffb55fSDavid Gibson 1739fffb55fSDavid Gibson fprintf(f, "["); 1749fffb55fSDavid Gibson for (;;) { 1759fffb55fSDavid Gibson while (m && (m->offset == (bp-val.val))) { 1769fffb55fSDavid Gibson if (m->type == LABEL) 1779fffb55fSDavid Gibson fprintf(f, "%s: ", m->ref); 1789fffb55fSDavid Gibson m = m->next; 1799fffb55fSDavid Gibson } 1809fffb55fSDavid Gibson 18147605971SRob Herring fprintf(f, "%02hhx", (unsigned char)(*bp++)); 1829fffb55fSDavid Gibson if ((const void *)bp >= propend) 1839fffb55fSDavid Gibson break; 1849fffb55fSDavid Gibson fprintf(f, " "); 1859fffb55fSDavid Gibson } 1869fffb55fSDavid Gibson 1879fffb55fSDavid Gibson /* Wrap up any labels at the end of the value */ 1889fffb55fSDavid Gibson for_each_marker_of_type(m, LABEL) { 1899fffb55fSDavid Gibson assert (m->offset == val.len); 1909fffb55fSDavid Gibson fprintf(f, " %s:", m->ref); 1919fffb55fSDavid Gibson } 1929fffb55fSDavid Gibson fprintf(f, "]"); 1939fffb55fSDavid Gibson } 1949fffb55fSDavid Gibson 1959fffb55fSDavid Gibson static void write_propval(FILE *f, struct property *prop) 1969fffb55fSDavid Gibson { 1979fffb55fSDavid Gibson int len = prop->val.len; 1989fffb55fSDavid Gibson const char *p = prop->val.val; 1999fffb55fSDavid Gibson struct marker *m = prop->val.markers; 2009fffb55fSDavid Gibson int nnotstring = 0, nnul = 0; 2019fffb55fSDavid Gibson int nnotstringlbl = 0, nnotcelllbl = 0; 2029fffb55fSDavid Gibson int i; 2039fffb55fSDavid Gibson 2049fffb55fSDavid Gibson if (len == 0) { 2059fffb55fSDavid Gibson fprintf(f, ";\n"); 2069fffb55fSDavid Gibson return; 2079fffb55fSDavid Gibson } 2089fffb55fSDavid Gibson 2099fffb55fSDavid Gibson for (i = 0; i < len; i++) { 2109fffb55fSDavid Gibson if (! isstring(p[i])) 2119fffb55fSDavid Gibson nnotstring++; 2129fffb55fSDavid Gibson if (p[i] == '\0') 2139fffb55fSDavid Gibson nnul++; 2149fffb55fSDavid Gibson } 2159fffb55fSDavid Gibson 2169fffb55fSDavid Gibson for_each_marker_of_type(m, LABEL) { 2179fffb55fSDavid Gibson if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 2189fffb55fSDavid Gibson nnotstringlbl++; 2199fffb55fSDavid Gibson if ((m->offset % sizeof(cell_t)) != 0) 2209fffb55fSDavid Gibson nnotcelllbl++; 2219fffb55fSDavid Gibson } 2229fffb55fSDavid Gibson 2239fffb55fSDavid Gibson fprintf(f, " = "); 2249fffb55fSDavid Gibson if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) 2259fffb55fSDavid Gibson && (nnotstringlbl == 0)) { 2269fffb55fSDavid Gibson write_propval_string(f, prop->val); 2279fffb55fSDavid Gibson } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 2289fffb55fSDavid Gibson write_propval_cells(f, prop->val); 2299fffb55fSDavid Gibson } else { 2309fffb55fSDavid Gibson write_propval_bytes(f, prop->val); 2319fffb55fSDavid Gibson } 2329fffb55fSDavid Gibson 2339fffb55fSDavid Gibson fprintf(f, ";\n"); 2349fffb55fSDavid Gibson } 2359fffb55fSDavid Gibson 2369fffb55fSDavid Gibson static void write_tree_source_node(FILE *f, struct node *tree, int level) 2379fffb55fSDavid Gibson { 2389fffb55fSDavid Gibson struct property *prop; 2399fffb55fSDavid Gibson struct node *child; 240658f29a5SJohn Bonesio struct label *l; 2419fffb55fSDavid Gibson 2429fffb55fSDavid Gibson write_prefix(f, level); 243658f29a5SJohn Bonesio for_each_label(tree->labels, l) 244658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 2459fffb55fSDavid Gibson if (tree->name && (*tree->name)) 2469fffb55fSDavid Gibson fprintf(f, "%s {\n", tree->name); 2479fffb55fSDavid Gibson else 2489fffb55fSDavid Gibson fprintf(f, "/ {\n"); 2499fffb55fSDavid Gibson 2509fffb55fSDavid Gibson for_each_property(tree, prop) { 2519fffb55fSDavid Gibson write_prefix(f, level+1); 252658f29a5SJohn Bonesio for_each_label(prop->labels, l) 253658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 2549fffb55fSDavid Gibson fprintf(f, "%s", prop->name); 2559fffb55fSDavid Gibson write_propval(f, prop); 2569fffb55fSDavid Gibson } 2579fffb55fSDavid Gibson for_each_child(tree, child) { 2589fffb55fSDavid Gibson fprintf(f, "\n"); 2599fffb55fSDavid Gibson write_tree_source_node(f, child, level+1); 2609fffb55fSDavid Gibson } 2619fffb55fSDavid Gibson write_prefix(f, level); 2629fffb55fSDavid Gibson fprintf(f, "};\n"); 2639fffb55fSDavid Gibson } 2649fffb55fSDavid Gibson 2659fffb55fSDavid Gibson 266*6f05afcbSRob Herring void dt_to_source(FILE *f, struct dt_info *dti) 2679fffb55fSDavid Gibson { 2689fffb55fSDavid Gibson struct reserve_info *re; 2699fffb55fSDavid Gibson 2709fffb55fSDavid Gibson fprintf(f, "/dts-v1/;\n\n"); 2719fffb55fSDavid Gibson 272*6f05afcbSRob Herring for (re = dti->reservelist; re; re = re->next) { 273658f29a5SJohn Bonesio struct label *l; 274658f29a5SJohn Bonesio 275658f29a5SJohn Bonesio for_each_label(re->labels, l) 276658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 2779fffb55fSDavid Gibson fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 2789fffb55fSDavid Gibson (unsigned long long)re->re.address, 2799fffb55fSDavid Gibson (unsigned long long)re->re.size); 2809fffb55fSDavid Gibson } 2819fffb55fSDavid Gibson 282*6f05afcbSRob Herring write_tree_source_node(f, dti->dt, 0); 2839fffb55fSDavid Gibson } 28447605971SRob Herring 285