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 286f05afcbSRob Herring struct dt_info *parser_output; 2947605971SRob Herring bool treesource_error; 309fffb55fSDavid Gibson 316f05afcbSRob Herring struct dt_info *dt_from_source(const char *fname) 329fffb55fSDavid Gibson { 336f05afcbSRob 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 466f05afcbSRob 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 64*f858927fSRob Herring static void write_propval_string(FILE *f, const char *s, size_t len) 659fffb55fSDavid Gibson { 66*f858927fSRob Herring const char *end = s + len - 1; 67*f858927fSRob Herring assert(*end == '\0'); 689fffb55fSDavid Gibson 699fffb55fSDavid Gibson fprintf(f, "\""); 70*f858927fSRob Herring while (s < end) { 71*f858927fSRob Herring char c = *s++; 729fffb55fSDavid Gibson switch (c) { 739fffb55fSDavid Gibson case '\a': 749fffb55fSDavid Gibson fprintf(f, "\\a"); 759fffb55fSDavid Gibson break; 769fffb55fSDavid Gibson case '\b': 779fffb55fSDavid Gibson fprintf(f, "\\b"); 789fffb55fSDavid Gibson break; 799fffb55fSDavid Gibson case '\t': 809fffb55fSDavid Gibson fprintf(f, "\\t"); 819fffb55fSDavid Gibson break; 829fffb55fSDavid Gibson case '\n': 839fffb55fSDavid Gibson fprintf(f, "\\n"); 849fffb55fSDavid Gibson break; 859fffb55fSDavid Gibson case '\v': 869fffb55fSDavid Gibson fprintf(f, "\\v"); 879fffb55fSDavid Gibson break; 889fffb55fSDavid Gibson case '\f': 899fffb55fSDavid Gibson fprintf(f, "\\f"); 909fffb55fSDavid Gibson break; 919fffb55fSDavid Gibson case '\r': 929fffb55fSDavid Gibson fprintf(f, "\\r"); 939fffb55fSDavid Gibson break; 949fffb55fSDavid Gibson case '\\': 959fffb55fSDavid Gibson fprintf(f, "\\\\"); 969fffb55fSDavid Gibson break; 979fffb55fSDavid Gibson case '\"': 989fffb55fSDavid Gibson fprintf(f, "\\\""); 999fffb55fSDavid Gibson break; 1009fffb55fSDavid Gibson case '\0': 101*f858927fSRob Herring fprintf(f, "\\0"); 1029fffb55fSDavid Gibson break; 1039fffb55fSDavid Gibson default: 10447605971SRob Herring if (isprint((unsigned char)c)) 1059fffb55fSDavid Gibson fprintf(f, "%c", c); 1069fffb55fSDavid Gibson else 107*f858927fSRob Herring fprintf(f, "\\x%02"PRIx8, c); 1089fffb55fSDavid Gibson } 1099fffb55fSDavid Gibson } 1109fffb55fSDavid Gibson fprintf(f, "\""); 1119fffb55fSDavid Gibson } 1129fffb55fSDavid Gibson 113*f858927fSRob Herring static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) 1149fffb55fSDavid Gibson { 115*f858927fSRob Herring const char *end = p + len; 116*f858927fSRob Herring assert(len % width == 0); 1179fffb55fSDavid Gibson 118*f858927fSRob Herring for (; p < end; p += width) { 119*f858927fSRob Herring switch (width) { 120*f858927fSRob Herring case 1: 121*f858927fSRob Herring fprintf(f, " %02"PRIx8, *(const uint8_t*)p); 1229fffb55fSDavid Gibson break; 123*f858927fSRob Herring case 2: 124*f858927fSRob Herring fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); 125*f858927fSRob Herring break; 126*f858927fSRob Herring case 4: 127*f858927fSRob Herring fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); 128*f858927fSRob Herring break; 129*f858927fSRob Herring case 8: 130*f858927fSRob Herring fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); 131*f858927fSRob Herring break; 132*f858927fSRob Herring } 133*f858927fSRob Herring } 1349fffb55fSDavid Gibson } 1359fffb55fSDavid Gibson 136*f858927fSRob Herring static bool has_data_type_information(struct marker *m) 1379fffb55fSDavid Gibson { 138*f858927fSRob Herring return m->type >= TYPE_UINT8; 139*f858927fSRob Herring } 1409fffb55fSDavid Gibson 141*f858927fSRob Herring static struct marker *next_type_marker(struct marker *m) 142*f858927fSRob Herring { 143*f858927fSRob Herring while (m && !has_data_type_information(m)) 1449fffb55fSDavid Gibson m = m->next; 145*f858927fSRob Herring return m; 1469fffb55fSDavid Gibson } 1479fffb55fSDavid Gibson 148*f858927fSRob Herring size_t type_marker_length(struct marker *m) 149*f858927fSRob Herring { 150*f858927fSRob Herring struct marker *next = next_type_marker(m->next); 151*f858927fSRob Herring 152*f858927fSRob Herring if (next) 153*f858927fSRob Herring return next->offset - m->offset; 154*f858927fSRob Herring return 0; 1559fffb55fSDavid Gibson } 1569fffb55fSDavid Gibson 157*f858927fSRob Herring static const char *delim_start[] = { 158*f858927fSRob Herring [TYPE_UINT8] = "[", 159*f858927fSRob Herring [TYPE_UINT16] = "/bits/ 16 <", 160*f858927fSRob Herring [TYPE_UINT32] = "<", 161*f858927fSRob Herring [TYPE_UINT64] = "/bits/ 64 <", 162*f858927fSRob Herring [TYPE_STRING] = "", 163*f858927fSRob Herring }; 164*f858927fSRob Herring static const char *delim_end[] = { 165*f858927fSRob Herring [TYPE_UINT8] = " ]", 166*f858927fSRob Herring [TYPE_UINT16] = " >", 167*f858927fSRob Herring [TYPE_UINT32] = " >", 168*f858927fSRob Herring [TYPE_UINT64] = " >", 169*f858927fSRob Herring [TYPE_STRING] = "", 170*f858927fSRob Herring }; 1719fffb55fSDavid Gibson 172*f858927fSRob Herring static enum markertype guess_value_type(struct property *prop) 1739fffb55fSDavid Gibson { 1749fffb55fSDavid Gibson int len = prop->val.len; 1759fffb55fSDavid Gibson const char *p = prop->val.val; 1769fffb55fSDavid Gibson struct marker *m = prop->val.markers; 1779fffb55fSDavid Gibson int nnotstring = 0, nnul = 0; 1789fffb55fSDavid Gibson int nnotstringlbl = 0, nnotcelllbl = 0; 1799fffb55fSDavid Gibson int i; 1809fffb55fSDavid Gibson 1819fffb55fSDavid Gibson for (i = 0; i < len; i++) { 1829fffb55fSDavid Gibson if (! isstring(p[i])) 1839fffb55fSDavid Gibson nnotstring++; 1849fffb55fSDavid Gibson if (p[i] == '\0') 1859fffb55fSDavid Gibson nnul++; 1869fffb55fSDavid Gibson } 1879fffb55fSDavid Gibson 1889fffb55fSDavid Gibson for_each_marker_of_type(m, LABEL) { 1899fffb55fSDavid Gibson if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 1909fffb55fSDavid Gibson nnotstringlbl++; 1919fffb55fSDavid Gibson if ((m->offset % sizeof(cell_t)) != 0) 1929fffb55fSDavid Gibson nnotcelllbl++; 1939fffb55fSDavid Gibson } 1949fffb55fSDavid Gibson 1959fffb55fSDavid Gibson if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) 1969fffb55fSDavid Gibson && (nnotstringlbl == 0)) { 197*f858927fSRob Herring return TYPE_STRING; 1989fffb55fSDavid Gibson } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 199*f858927fSRob Herring return TYPE_UINT32; 2009fffb55fSDavid Gibson } 2019fffb55fSDavid Gibson 202*f858927fSRob Herring return TYPE_UINT8; 203*f858927fSRob Herring } 204*f858927fSRob Herring 205*f858927fSRob Herring static void write_propval(FILE *f, struct property *prop) 206*f858927fSRob Herring { 207*f858927fSRob Herring size_t len = prop->val.len; 208*f858927fSRob Herring struct marker *m = prop->val.markers; 209*f858927fSRob Herring struct marker dummy_marker; 210*f858927fSRob Herring enum markertype emit_type = TYPE_NONE; 211*f858927fSRob Herring 212*f858927fSRob Herring if (len == 0) { 2139fffb55fSDavid Gibson fprintf(f, ";\n"); 214*f858927fSRob Herring return; 215*f858927fSRob Herring } 216*f858927fSRob Herring 217*f858927fSRob Herring fprintf(f, " = "); 218*f858927fSRob Herring 219*f858927fSRob Herring if (!next_type_marker(m)) { 220*f858927fSRob Herring /* data type information missing, need to guess */ 221*f858927fSRob Herring dummy_marker.type = guess_value_type(prop); 222*f858927fSRob Herring dummy_marker.next = prop->val.markers; 223*f858927fSRob Herring dummy_marker.offset = 0; 224*f858927fSRob Herring dummy_marker.ref = NULL; 225*f858927fSRob Herring m = &dummy_marker; 226*f858927fSRob Herring } 227*f858927fSRob Herring 228*f858927fSRob Herring struct marker *m_label = prop->val.markers; 229*f858927fSRob Herring for_each_marker(m) { 230*f858927fSRob Herring size_t chunk_len; 231*f858927fSRob Herring const char *p = &prop->val.val[m->offset]; 232*f858927fSRob Herring 233*f858927fSRob Herring if (!has_data_type_information(m)) 234*f858927fSRob Herring continue; 235*f858927fSRob Herring 236*f858927fSRob Herring chunk_len = type_marker_length(m); 237*f858927fSRob Herring if (!chunk_len) 238*f858927fSRob Herring chunk_len = len - m->offset; 239*f858927fSRob Herring 240*f858927fSRob Herring if (emit_type != TYPE_NONE) 241*f858927fSRob Herring fprintf(f, "%s, ", delim_end[emit_type]); 242*f858927fSRob Herring emit_type = m->type; 243*f858927fSRob Herring 244*f858927fSRob Herring for_each_marker_of_type(m_label, LABEL) { 245*f858927fSRob Herring if (m_label->offset > m->offset) 246*f858927fSRob Herring break; 247*f858927fSRob Herring fprintf(f, "%s: ", m_label->ref); 248*f858927fSRob Herring } 249*f858927fSRob Herring 250*f858927fSRob Herring fprintf(f, "%s", delim_start[emit_type]); 251*f858927fSRob Herring 252*f858927fSRob Herring if (chunk_len <= 0) 253*f858927fSRob Herring continue; 254*f858927fSRob Herring 255*f858927fSRob Herring switch(emit_type) { 256*f858927fSRob Herring case TYPE_UINT16: 257*f858927fSRob Herring write_propval_int(f, p, chunk_len, 2); 258*f858927fSRob Herring break; 259*f858927fSRob Herring case TYPE_UINT32: 260*f858927fSRob Herring write_propval_int(f, p, chunk_len, 4); 261*f858927fSRob Herring break; 262*f858927fSRob Herring case TYPE_UINT64: 263*f858927fSRob Herring write_propval_int(f, p, chunk_len, 8); 264*f858927fSRob Herring break; 265*f858927fSRob Herring case TYPE_STRING: 266*f858927fSRob Herring write_propval_string(f, p, chunk_len); 267*f858927fSRob Herring break; 268*f858927fSRob Herring default: 269*f858927fSRob Herring write_propval_int(f, p, chunk_len, 1); 270*f858927fSRob Herring } 271*f858927fSRob Herring } 272*f858927fSRob Herring 273*f858927fSRob Herring /* Wrap up any labels at the end of the value */ 274*f858927fSRob Herring for_each_marker_of_type(m_label, LABEL) { 275*f858927fSRob Herring assert (m_label->offset == len); 276*f858927fSRob Herring fprintf(f, " %s:", m_label->ref); 277*f858927fSRob Herring } 278*f858927fSRob Herring 279*f858927fSRob Herring fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); 2809fffb55fSDavid Gibson } 2819fffb55fSDavid Gibson 2829fffb55fSDavid Gibson static void write_tree_source_node(FILE *f, struct node *tree, int level) 2839fffb55fSDavid Gibson { 2849fffb55fSDavid Gibson struct property *prop; 2859fffb55fSDavid Gibson struct node *child; 286658f29a5SJohn Bonesio struct label *l; 2879fffb55fSDavid Gibson 2889fffb55fSDavid Gibson write_prefix(f, level); 289658f29a5SJohn Bonesio for_each_label(tree->labels, l) 290658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 2919fffb55fSDavid Gibson if (tree->name && (*tree->name)) 2929fffb55fSDavid Gibson fprintf(f, "%s {\n", tree->name); 2939fffb55fSDavid Gibson else 2949fffb55fSDavid Gibson fprintf(f, "/ {\n"); 2959fffb55fSDavid Gibson 2969fffb55fSDavid Gibson for_each_property(tree, prop) { 2979fffb55fSDavid Gibson write_prefix(f, level+1); 298658f29a5SJohn Bonesio for_each_label(prop->labels, l) 299658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 3009fffb55fSDavid Gibson fprintf(f, "%s", prop->name); 3019fffb55fSDavid Gibson write_propval(f, prop); 3029fffb55fSDavid Gibson } 3039fffb55fSDavid Gibson for_each_child(tree, child) { 3049fffb55fSDavid Gibson fprintf(f, "\n"); 3059fffb55fSDavid Gibson write_tree_source_node(f, child, level+1); 3069fffb55fSDavid Gibson } 3079fffb55fSDavid Gibson write_prefix(f, level); 3089fffb55fSDavid Gibson fprintf(f, "};\n"); 3099fffb55fSDavid Gibson } 3109fffb55fSDavid Gibson 3119fffb55fSDavid Gibson 3126f05afcbSRob Herring void dt_to_source(FILE *f, struct dt_info *dti) 3139fffb55fSDavid Gibson { 3149fffb55fSDavid Gibson struct reserve_info *re; 3159fffb55fSDavid Gibson 3169fffb55fSDavid Gibson fprintf(f, "/dts-v1/;\n\n"); 3179fffb55fSDavid Gibson 3186f05afcbSRob Herring for (re = dti->reservelist; re; re = re->next) { 319658f29a5SJohn Bonesio struct label *l; 320658f29a5SJohn Bonesio 321658f29a5SJohn Bonesio for_each_label(re->labels, l) 322658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 3239fffb55fSDavid Gibson fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 32489d12310SRob Herring (unsigned long long)re->address, 32589d12310SRob Herring (unsigned long long)re->size); 3269fffb55fSDavid Gibson } 3279fffb55fSDavid Gibson 3286f05afcbSRob Herring write_tree_source_node(f, dti->dt, 0); 3299fffb55fSDavid Gibson } 330