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