11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29fffb55fSDavid Gibson /* 39fffb55fSDavid Gibson * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 49fffb55fSDavid Gibson */ 59fffb55fSDavid Gibson 69fffb55fSDavid Gibson #include "dtc.h" 79fffb55fSDavid Gibson #include "srcpos.h" 89fffb55fSDavid Gibson 99fffb55fSDavid Gibson extern FILE *yyin; 109fffb55fSDavid Gibson extern int yyparse(void); 11cd296721SStephen Warren extern YYLTYPE yylloc; 129fffb55fSDavid Gibson 136f05afcbSRob Herring struct dt_info *parser_output; 1447605971SRob Herring bool treesource_error; 159fffb55fSDavid Gibson 166f05afcbSRob Herring struct dt_info *dt_from_source(const char *fname) 179fffb55fSDavid Gibson { 186f05afcbSRob Herring parser_output = NULL; 1947605971SRob Herring treesource_error = false; 209fffb55fSDavid Gibson 21658f29a5SJohn Bonesio srcfile_push(fname); 22658f29a5SJohn Bonesio yyin = current_srcfile->f; 23cd296721SStephen Warren yylloc.file = current_srcfile; 249fffb55fSDavid Gibson 259fffb55fSDavid Gibson if (yyparse() != 0) 269fffb55fSDavid Gibson die("Unable to parse input tree\n"); 279fffb55fSDavid Gibson 289fffb55fSDavid Gibson if (treesource_error) 299fffb55fSDavid Gibson die("Syntax error parsing input tree\n"); 309fffb55fSDavid Gibson 316f05afcbSRob Herring return parser_output; 329fffb55fSDavid Gibson } 339fffb55fSDavid Gibson 349fffb55fSDavid Gibson static void write_prefix(FILE *f, int level) 359fffb55fSDavid Gibson { 369fffb55fSDavid Gibson int i; 379fffb55fSDavid Gibson 389fffb55fSDavid Gibson for (i = 0; i < level; i++) 399fffb55fSDavid Gibson fputc('\t', f); 409fffb55fSDavid Gibson } 419fffb55fSDavid Gibson 4247605971SRob Herring static bool isstring(char c) 439fffb55fSDavid Gibson { 4447605971SRob Herring return (isprint((unsigned char)c) 459fffb55fSDavid Gibson || (c == '\0') 469fffb55fSDavid Gibson || strchr("\a\b\t\n\v\f\r", c)); 479fffb55fSDavid Gibson } 489fffb55fSDavid Gibson 49f858927fSRob Herring static void write_propval_string(FILE *f, const char *s, size_t len) 509fffb55fSDavid Gibson { 51f858927fSRob Herring const char *end = s + len - 1; 52c2e7075cSRob Herring 53c2e7075cSRob Herring if (!len) 54c2e7075cSRob Herring return; 55c2e7075cSRob Herring 56f858927fSRob Herring assert(*end == '\0'); 579fffb55fSDavid Gibson 589fffb55fSDavid Gibson fprintf(f, "\""); 59f858927fSRob Herring while (s < end) { 60f858927fSRob Herring char c = *s++; 619fffb55fSDavid Gibson switch (c) { 629fffb55fSDavid Gibson case '\a': 639fffb55fSDavid Gibson fprintf(f, "\\a"); 649fffb55fSDavid Gibson break; 659fffb55fSDavid Gibson case '\b': 669fffb55fSDavid Gibson fprintf(f, "\\b"); 679fffb55fSDavid Gibson break; 689fffb55fSDavid Gibson case '\t': 699fffb55fSDavid Gibson fprintf(f, "\\t"); 709fffb55fSDavid Gibson break; 719fffb55fSDavid Gibson case '\n': 729fffb55fSDavid Gibson fprintf(f, "\\n"); 739fffb55fSDavid Gibson break; 749fffb55fSDavid Gibson case '\v': 759fffb55fSDavid Gibson fprintf(f, "\\v"); 769fffb55fSDavid Gibson break; 779fffb55fSDavid Gibson case '\f': 789fffb55fSDavid Gibson fprintf(f, "\\f"); 799fffb55fSDavid Gibson break; 809fffb55fSDavid Gibson case '\r': 819fffb55fSDavid Gibson fprintf(f, "\\r"); 829fffb55fSDavid Gibson break; 839fffb55fSDavid Gibson case '\\': 849fffb55fSDavid Gibson fprintf(f, "\\\\"); 859fffb55fSDavid Gibson break; 869fffb55fSDavid Gibson case '\"': 879fffb55fSDavid Gibson fprintf(f, "\\\""); 889fffb55fSDavid Gibson break; 899fffb55fSDavid Gibson case '\0': 90f858927fSRob Herring fprintf(f, "\\0"); 919fffb55fSDavid Gibson break; 929fffb55fSDavid Gibson default: 9347605971SRob Herring if (isprint((unsigned char)c)) 949fffb55fSDavid Gibson fprintf(f, "%c", c); 959fffb55fSDavid Gibson else 96f858927fSRob Herring fprintf(f, "\\x%02"PRIx8, c); 979fffb55fSDavid Gibson } 989fffb55fSDavid Gibson } 999fffb55fSDavid Gibson fprintf(f, "\""); 1009fffb55fSDavid Gibson } 1019fffb55fSDavid Gibson 102f858927fSRob Herring static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) 1039fffb55fSDavid Gibson { 104f858927fSRob Herring const char *end = p + len; 105f858927fSRob Herring assert(len % width == 0); 1069fffb55fSDavid Gibson 107f858927fSRob Herring for (; p < end; p += width) { 108f858927fSRob Herring switch (width) { 109f858927fSRob Herring case 1: 110f858927fSRob Herring fprintf(f, "%02"PRIx8, *(const uint8_t*)p); 1119fffb55fSDavid Gibson break; 112f858927fSRob Herring case 2: 113*3eb619b2SRob Herring fprintf(f, "0x%02"PRIx16, dtb_ld16(p)); 114f858927fSRob Herring break; 115f858927fSRob Herring case 4: 116*3eb619b2SRob Herring fprintf(f, "0x%02"PRIx32, dtb_ld32(p)); 117f858927fSRob Herring break; 118f858927fSRob Herring case 8: 119*3eb619b2SRob Herring fprintf(f, "0x%02"PRIx64, dtb_ld64(p)); 120f858927fSRob Herring break; 121f858927fSRob Herring } 122c2e7075cSRob Herring if (p + width < end) 123c2e7075cSRob Herring fputc(' ', f); 124f858927fSRob Herring } 1259fffb55fSDavid Gibson } 1269fffb55fSDavid Gibson 127f858927fSRob Herring static bool has_data_type_information(struct marker *m) 1289fffb55fSDavid Gibson { 129f858927fSRob Herring return m->type >= TYPE_UINT8; 130f858927fSRob Herring } 1319fffb55fSDavid Gibson 132f858927fSRob Herring static struct marker *next_type_marker(struct marker *m) 133f858927fSRob Herring { 134f858927fSRob Herring while (m && !has_data_type_information(m)) 1359fffb55fSDavid Gibson m = m->next; 136f858927fSRob Herring return m; 1379fffb55fSDavid Gibson } 1389fffb55fSDavid Gibson 139f858927fSRob Herring size_t type_marker_length(struct marker *m) 140f858927fSRob Herring { 141f858927fSRob Herring struct marker *next = next_type_marker(m->next); 142f858927fSRob Herring 143f858927fSRob Herring if (next) 144f858927fSRob Herring return next->offset - m->offset; 145f858927fSRob Herring return 0; 1469fffb55fSDavid Gibson } 1479fffb55fSDavid Gibson 148f858927fSRob Herring static const char *delim_start[] = { 149f858927fSRob Herring [TYPE_UINT8] = "[", 150f858927fSRob Herring [TYPE_UINT16] = "/bits/ 16 <", 151f858927fSRob Herring [TYPE_UINT32] = "<", 152f858927fSRob Herring [TYPE_UINT64] = "/bits/ 64 <", 153f858927fSRob Herring [TYPE_STRING] = "", 154f858927fSRob Herring }; 155f858927fSRob Herring static const char *delim_end[] = { 156f858927fSRob Herring [TYPE_UINT8] = "]", 157f858927fSRob Herring [TYPE_UINT16] = ">", 158f858927fSRob Herring [TYPE_UINT32] = ">", 159f858927fSRob Herring [TYPE_UINT64] = ">", 160f858927fSRob Herring [TYPE_STRING] = "", 161f858927fSRob Herring }; 1629fffb55fSDavid Gibson 163f858927fSRob Herring static enum markertype guess_value_type(struct property *prop) 1649fffb55fSDavid Gibson { 1659fffb55fSDavid Gibson int len = prop->val.len; 1669fffb55fSDavid Gibson const char *p = prop->val.val; 1679fffb55fSDavid Gibson struct marker *m = prop->val.markers; 1689fffb55fSDavid Gibson int nnotstring = 0, nnul = 0; 1699fffb55fSDavid Gibson int nnotstringlbl = 0, nnotcelllbl = 0; 1709fffb55fSDavid Gibson int i; 1719fffb55fSDavid Gibson 1729fffb55fSDavid Gibson for (i = 0; i < len; i++) { 1739fffb55fSDavid Gibson if (! isstring(p[i])) 1749fffb55fSDavid Gibson nnotstring++; 1759fffb55fSDavid Gibson if (p[i] == '\0') 1769fffb55fSDavid Gibson nnul++; 1779fffb55fSDavid Gibson } 1789fffb55fSDavid Gibson 1799fffb55fSDavid Gibson for_each_marker_of_type(m, LABEL) { 1809fffb55fSDavid Gibson if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 1819fffb55fSDavid Gibson nnotstringlbl++; 1829fffb55fSDavid Gibson if ((m->offset % sizeof(cell_t)) != 0) 1839fffb55fSDavid Gibson nnotcelllbl++; 1849fffb55fSDavid Gibson } 1859fffb55fSDavid Gibson 186*3eb619b2SRob Herring if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) 1879fffb55fSDavid Gibson && (nnotstringlbl == 0)) { 188f858927fSRob Herring return TYPE_STRING; 1899fffb55fSDavid Gibson } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 190f858927fSRob Herring return TYPE_UINT32; 1919fffb55fSDavid Gibson } 1929fffb55fSDavid Gibson 193f858927fSRob Herring return TYPE_UINT8; 194f858927fSRob Herring } 195f858927fSRob Herring 196f858927fSRob Herring static void write_propval(FILE *f, struct property *prop) 197f858927fSRob Herring { 198f858927fSRob Herring size_t len = prop->val.len; 199f858927fSRob Herring struct marker *m = prop->val.markers; 200f858927fSRob Herring struct marker dummy_marker; 201f858927fSRob Herring enum markertype emit_type = TYPE_NONE; 202c2e7075cSRob Herring char *srcstr; 203f858927fSRob Herring 204f858927fSRob Herring if (len == 0) { 205c2e7075cSRob Herring fprintf(f, ";"); 206c2e7075cSRob Herring if (annotate) { 207c2e7075cSRob Herring srcstr = srcpos_string_first(prop->srcpos, annotate); 208c2e7075cSRob Herring if (srcstr) { 209c2e7075cSRob Herring fprintf(f, " /* %s */", srcstr); 210c2e7075cSRob Herring free(srcstr); 211c2e7075cSRob Herring } 212c2e7075cSRob Herring } 213c2e7075cSRob Herring fprintf(f, "\n"); 214f858927fSRob Herring return; 215f858927fSRob Herring } 216f858927fSRob Herring 217f858927fSRob Herring fprintf(f, " ="); 218f858927fSRob Herring 219f858927fSRob Herring if (!next_type_marker(m)) { 220f858927fSRob Herring /* data type information missing, need to guess */ 221f858927fSRob Herring dummy_marker.type = guess_value_type(prop); 222f858927fSRob Herring dummy_marker.next = prop->val.markers; 223f858927fSRob Herring dummy_marker.offset = 0; 224f858927fSRob Herring dummy_marker.ref = NULL; 225f858927fSRob Herring m = &dummy_marker; 226f858927fSRob Herring } 227f858927fSRob Herring 228f858927fSRob Herring for_each_marker(m) { 229c2e7075cSRob Herring size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; 230c2e7075cSRob Herring size_t data_len = type_marker_length(m) ? : len - m->offset; 231f858927fSRob Herring const char *p = &prop->val.val[m->offset]; 232f858927fSRob Herring 233c2e7075cSRob Herring if (has_data_type_information(m)) { 234f858927fSRob Herring emit_type = m->type; 235f858927fSRob Herring fprintf(f, " %s", delim_start[emit_type]); 236c2e7075cSRob Herring } else if (m->type == LABEL) 237c2e7075cSRob Herring fprintf(f, " %s:", m->ref); 238c2e7075cSRob Herring else if (m->offset) 239c2e7075cSRob Herring fputc(' ', f); 240f858927fSRob Herring 241c2e7075cSRob Herring if (emit_type == TYPE_NONE) { 242c2e7075cSRob Herring assert(chunk_len == 0); 243f858927fSRob Herring continue; 244c2e7075cSRob Herring } 245f858927fSRob Herring 246f858927fSRob Herring switch(emit_type) { 247f858927fSRob Herring case TYPE_UINT16: 248f858927fSRob Herring write_propval_int(f, p, chunk_len, 2); 249f858927fSRob Herring break; 250f858927fSRob Herring case TYPE_UINT32: 251f858927fSRob Herring write_propval_int(f, p, chunk_len, 4); 252f858927fSRob Herring break; 253f858927fSRob Herring case TYPE_UINT64: 254f858927fSRob Herring write_propval_int(f, p, chunk_len, 8); 255f858927fSRob Herring break; 256f858927fSRob Herring case TYPE_STRING: 257f858927fSRob Herring write_propval_string(f, p, chunk_len); 258f858927fSRob Herring break; 259f858927fSRob Herring default: 260f858927fSRob Herring write_propval_int(f, p, chunk_len, 1); 261f858927fSRob Herring } 262f858927fSRob Herring 263c2e7075cSRob Herring if (chunk_len == data_len) { 264c2e7075cSRob Herring size_t pos = m->offset + chunk_len; 265c2e7075cSRob Herring fprintf(f, pos == len ? "%s" : "%s,", 266c2e7075cSRob Herring delim_end[emit_type] ? : ""); 267c2e7075cSRob Herring emit_type = TYPE_NONE; 268f858927fSRob Herring } 269c2e7075cSRob Herring } 270c2e7075cSRob Herring fprintf(f, ";"); 271c2e7075cSRob Herring if (annotate) { 272c2e7075cSRob Herring srcstr = srcpos_string_first(prop->srcpos, annotate); 273c2e7075cSRob Herring if (srcstr) { 274c2e7075cSRob Herring fprintf(f, " /* %s */", srcstr); 275c2e7075cSRob Herring free(srcstr); 276c2e7075cSRob Herring } 277c2e7075cSRob Herring } 278c2e7075cSRob Herring fprintf(f, "\n"); 2799fffb55fSDavid Gibson } 2809fffb55fSDavid Gibson 2819fffb55fSDavid Gibson static void write_tree_source_node(FILE *f, struct node *tree, int level) 2829fffb55fSDavid Gibson { 2839fffb55fSDavid Gibson struct property *prop; 2849fffb55fSDavid Gibson struct node *child; 285658f29a5SJohn Bonesio struct label *l; 286c2e7075cSRob Herring char *srcstr; 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)) 292c2e7075cSRob Herring fprintf(f, "%s {", tree->name); 2939fffb55fSDavid Gibson else 294c2e7075cSRob Herring fprintf(f, "/ {"); 295c2e7075cSRob Herring 296c2e7075cSRob Herring if (annotate) { 297c2e7075cSRob Herring srcstr = srcpos_string_first(tree->srcpos, annotate); 298c2e7075cSRob Herring if (srcstr) { 299c2e7075cSRob Herring fprintf(f, " /* %s */", srcstr); 300c2e7075cSRob Herring free(srcstr); 301c2e7075cSRob Herring } 302c2e7075cSRob Herring } 303c2e7075cSRob Herring fprintf(f, "\n"); 3049fffb55fSDavid Gibson 3059fffb55fSDavid Gibson for_each_property(tree, prop) { 3069fffb55fSDavid Gibson write_prefix(f, level+1); 307658f29a5SJohn Bonesio for_each_label(prop->labels, l) 308658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 3099fffb55fSDavid Gibson fprintf(f, "%s", prop->name); 3109fffb55fSDavid Gibson write_propval(f, prop); 3119fffb55fSDavid Gibson } 3129fffb55fSDavid Gibson for_each_child(tree, child) { 3139fffb55fSDavid Gibson fprintf(f, "\n"); 3149fffb55fSDavid Gibson write_tree_source_node(f, child, level+1); 3159fffb55fSDavid Gibson } 3169fffb55fSDavid Gibson write_prefix(f, level); 317c2e7075cSRob Herring fprintf(f, "};"); 318c2e7075cSRob Herring if (annotate) { 319c2e7075cSRob Herring srcstr = srcpos_string_last(tree->srcpos, annotate); 320c2e7075cSRob Herring if (srcstr) { 321c2e7075cSRob Herring fprintf(f, " /* %s */", srcstr); 322c2e7075cSRob Herring free(srcstr); 3239fffb55fSDavid Gibson } 324c2e7075cSRob Herring } 325c2e7075cSRob Herring fprintf(f, "\n"); 326c2e7075cSRob Herring } 3279fffb55fSDavid Gibson 3286f05afcbSRob Herring void dt_to_source(FILE *f, struct dt_info *dti) 3299fffb55fSDavid Gibson { 3309fffb55fSDavid Gibson struct reserve_info *re; 3319fffb55fSDavid Gibson 3329fffb55fSDavid Gibson fprintf(f, "/dts-v1/;\n\n"); 3339fffb55fSDavid Gibson 3346f05afcbSRob Herring for (re = dti->reservelist; re; re = re->next) { 335658f29a5SJohn Bonesio struct label *l; 336658f29a5SJohn Bonesio 337658f29a5SJohn Bonesio for_each_label(re->labels, l) 338658f29a5SJohn Bonesio fprintf(f, "%s: ", l->label); 3399fffb55fSDavid Gibson fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 34089d12310SRob Herring (unsigned long long)re->address, 34189d12310SRob Herring (unsigned long long)re->size); 3429fffb55fSDavid Gibson } 3439fffb55fSDavid Gibson 3446f05afcbSRob Herring write_tree_source_node(f, dti->dt, 0); 3459fffb55fSDavid Gibson } 346