1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 4 */ 5 6 #include "dtc.h" 7 #include "srcpos.h" 8 9 extern FILE *yyin; 10 extern int yyparse(void); 11 extern YYLTYPE yylloc; 12 13 struct dt_info *parser_output; 14 bool treesource_error; 15 16 struct dt_info *dt_from_source(const char *fname) 17 { 18 parser_output = NULL; 19 treesource_error = false; 20 21 srcfile_push(fname); 22 yyin = current_srcfile->f; 23 yylloc.file = current_srcfile; 24 25 if (yyparse() != 0) 26 die("Unable to parse input tree\n"); 27 28 if (treesource_error) 29 die("Syntax error parsing input tree\n"); 30 31 return parser_output; 32 } 33 34 static void write_prefix(FILE *f, int level) 35 { 36 int i; 37 38 for (i = 0; i < level; i++) 39 fputc('\t', f); 40 } 41 42 static bool isstring(char c) 43 { 44 return (isprint((unsigned char)c) 45 || (c == '\0') 46 || strchr("\a\b\t\n\v\f\r", c)); 47 } 48 49 static void write_propval_string(FILE *f, const char *s, size_t len) 50 { 51 const char *end = s + len - 1; 52 53 if (!len) 54 return; 55 56 assert(*end == '\0'); 57 58 fprintf(f, "\""); 59 while (s < end) { 60 char c = *s++; 61 switch (c) { 62 case '\a': 63 fprintf(f, "\\a"); 64 break; 65 case '\b': 66 fprintf(f, "\\b"); 67 break; 68 case '\t': 69 fprintf(f, "\\t"); 70 break; 71 case '\n': 72 fprintf(f, "\\n"); 73 break; 74 case '\v': 75 fprintf(f, "\\v"); 76 break; 77 case '\f': 78 fprintf(f, "\\f"); 79 break; 80 case '\r': 81 fprintf(f, "\\r"); 82 break; 83 case '\\': 84 fprintf(f, "\\\\"); 85 break; 86 case '\"': 87 fprintf(f, "\\\""); 88 break; 89 case '\0': 90 fprintf(f, "\\0"); 91 break; 92 default: 93 if (isprint((unsigned char)c)) 94 fprintf(f, "%c", c); 95 else 96 fprintf(f, "\\x%02"PRIx8, c); 97 } 98 } 99 fprintf(f, "\""); 100 } 101 102 static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) 103 { 104 const char *end = p + len; 105 assert(len % width == 0); 106 107 for (; p < end; p += width) { 108 switch (width) { 109 case 1: 110 fprintf(f, "%02"PRIx8, *(const uint8_t*)p); 111 break; 112 case 2: 113 fprintf(f, "0x%02"PRIx16, dtb_ld16(p)); 114 break; 115 case 4: 116 fprintf(f, "0x%02"PRIx32, dtb_ld32(p)); 117 break; 118 case 8: 119 fprintf(f, "0x%02"PRIx64, dtb_ld64(p)); 120 break; 121 } 122 if (p + width < end) 123 fputc(' ', f); 124 } 125 } 126 127 static bool has_data_type_information(struct marker *m) 128 { 129 return m->type >= TYPE_UINT8; 130 } 131 132 static struct marker *next_type_marker(struct marker *m) 133 { 134 while (m && !has_data_type_information(m)) 135 m = m->next; 136 return m; 137 } 138 139 size_t type_marker_length(struct marker *m) 140 { 141 struct marker *next = next_type_marker(m->next); 142 143 if (next) 144 return next->offset - m->offset; 145 return 0; 146 } 147 148 static const char *delim_start[] = { 149 [TYPE_UINT8] = "[", 150 [TYPE_UINT16] = "/bits/ 16 <", 151 [TYPE_UINT32] = "<", 152 [TYPE_UINT64] = "/bits/ 64 <", 153 [TYPE_STRING] = "", 154 }; 155 static const char *delim_end[] = { 156 [TYPE_UINT8] = "]", 157 [TYPE_UINT16] = ">", 158 [TYPE_UINT32] = ">", 159 [TYPE_UINT64] = ">", 160 [TYPE_STRING] = "", 161 }; 162 163 static enum markertype guess_value_type(struct property *prop) 164 { 165 int len = prop->val.len; 166 const char *p = prop->val.val; 167 struct marker *m = prop->val.markers; 168 int nnotstring = 0, nnul = 0; 169 int nnotstringlbl = 0, nnotcelllbl = 0; 170 int i; 171 172 for (i = 0; i < len; i++) { 173 if (! isstring(p[i])) 174 nnotstring++; 175 if (p[i] == '\0') 176 nnul++; 177 } 178 179 for_each_marker_of_type(m, LABEL) { 180 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 181 nnotstringlbl++; 182 if ((m->offset % sizeof(cell_t)) != 0) 183 nnotcelllbl++; 184 } 185 186 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) 187 && (nnotstringlbl == 0)) { 188 return TYPE_STRING; 189 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 190 return TYPE_UINT32; 191 } 192 193 return TYPE_UINT8; 194 } 195 196 static void write_propval(FILE *f, struct property *prop) 197 { 198 size_t len = prop->val.len; 199 struct marker *m = prop->val.markers; 200 struct marker dummy_marker; 201 enum markertype emit_type = TYPE_NONE; 202 char *srcstr; 203 204 if (len == 0) { 205 fprintf(f, ";"); 206 if (annotate) { 207 srcstr = srcpos_string_first(prop->srcpos, annotate); 208 if (srcstr) { 209 fprintf(f, " /* %s */", srcstr); 210 free(srcstr); 211 } 212 } 213 fprintf(f, "\n"); 214 return; 215 } 216 217 fprintf(f, " ="); 218 219 if (!next_type_marker(m)) { 220 /* data type information missing, need to guess */ 221 dummy_marker.type = guess_value_type(prop); 222 dummy_marker.next = prop->val.markers; 223 dummy_marker.offset = 0; 224 dummy_marker.ref = NULL; 225 m = &dummy_marker; 226 } 227 228 for_each_marker(m) { 229 size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; 230 size_t data_len = type_marker_length(m) ? : len - m->offset; 231 const char *p = &prop->val.val[m->offset]; 232 233 if (has_data_type_information(m)) { 234 emit_type = m->type; 235 fprintf(f, " %s", delim_start[emit_type]); 236 } else if (m->type == LABEL) 237 fprintf(f, " %s:", m->ref); 238 else if (m->offset) 239 fputc(' ', f); 240 241 if (emit_type == TYPE_NONE) { 242 assert(chunk_len == 0); 243 continue; 244 } 245 246 switch(emit_type) { 247 case TYPE_UINT16: 248 write_propval_int(f, p, chunk_len, 2); 249 break; 250 case TYPE_UINT32: 251 write_propval_int(f, p, chunk_len, 4); 252 break; 253 case TYPE_UINT64: 254 write_propval_int(f, p, chunk_len, 8); 255 break; 256 case TYPE_STRING: 257 write_propval_string(f, p, chunk_len); 258 break; 259 default: 260 write_propval_int(f, p, chunk_len, 1); 261 } 262 263 if (chunk_len == data_len) { 264 size_t pos = m->offset + chunk_len; 265 fprintf(f, pos == len ? "%s" : "%s,", 266 delim_end[emit_type] ? : ""); 267 emit_type = TYPE_NONE; 268 } 269 } 270 fprintf(f, ";"); 271 if (annotate) { 272 srcstr = srcpos_string_first(prop->srcpos, annotate); 273 if (srcstr) { 274 fprintf(f, " /* %s */", srcstr); 275 free(srcstr); 276 } 277 } 278 fprintf(f, "\n"); 279 } 280 281 static void write_tree_source_node(FILE *f, struct node *tree, int level) 282 { 283 struct property *prop; 284 struct node *child; 285 struct label *l; 286 char *srcstr; 287 288 write_prefix(f, level); 289 for_each_label(tree->labels, l) 290 fprintf(f, "%s: ", l->label); 291 if (tree->name && (*tree->name)) 292 fprintf(f, "%s {", tree->name); 293 else 294 fprintf(f, "/ {"); 295 296 if (annotate) { 297 srcstr = srcpos_string_first(tree->srcpos, annotate); 298 if (srcstr) { 299 fprintf(f, " /* %s */", srcstr); 300 free(srcstr); 301 } 302 } 303 fprintf(f, "\n"); 304 305 for_each_property(tree, prop) { 306 write_prefix(f, level+1); 307 for_each_label(prop->labels, l) 308 fprintf(f, "%s: ", l->label); 309 fprintf(f, "%s", prop->name); 310 write_propval(f, prop); 311 } 312 for_each_child(tree, child) { 313 fprintf(f, "\n"); 314 write_tree_source_node(f, child, level+1); 315 } 316 write_prefix(f, level); 317 fprintf(f, "};"); 318 if (annotate) { 319 srcstr = srcpos_string_last(tree->srcpos, annotate); 320 if (srcstr) { 321 fprintf(f, " /* %s */", srcstr); 322 free(srcstr); 323 } 324 } 325 fprintf(f, "\n"); 326 } 327 328 void dt_to_source(FILE *f, struct dt_info *dti) 329 { 330 struct reserve_info *re; 331 332 fprintf(f, "/dts-v1/;\n\n"); 333 334 for (re = dti->reservelist; re; re = re->next) { 335 struct label *l; 336 337 for_each_label(re->labels, l) 338 fprintf(f, "%s: ", l->label); 339 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 340 (unsigned long long)re->address, 341 (unsigned long long)re->size); 342 } 343 344 write_tree_source_node(f, dti->dt, 0); 345 } 346