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 const char *delim_start[] = { 128 [TYPE_UINT8] = "[", 129 [TYPE_UINT16] = "/bits/ 16 <", 130 [TYPE_UINT32] = "<", 131 [TYPE_UINT64] = "/bits/ 64 <", 132 [TYPE_STRING] = "", 133 }; 134 static const char *delim_end[] = { 135 [TYPE_UINT8] = "]", 136 [TYPE_UINT16] = ">", 137 [TYPE_UINT32] = ">", 138 [TYPE_UINT64] = ">", 139 [TYPE_STRING] = "", 140 }; 141 142 static enum markertype guess_value_type(struct property *prop) 143 { 144 int len = prop->val.len; 145 const char *p = prop->val.val; 146 struct marker *m = prop->val.markers; 147 int nnotstring = 0, nnul = 0; 148 int nnotstringlbl = 0, nnotcelllbl = 0; 149 int i; 150 151 for (i = 0; i < len; i++) { 152 if (! isstring(p[i])) 153 nnotstring++; 154 if (p[i] == '\0') 155 nnul++; 156 } 157 158 for_each_marker_of_type(m, LABEL) { 159 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 160 nnotstringlbl++; 161 if ((m->offset % sizeof(cell_t)) != 0) 162 nnotcelllbl++; 163 } 164 165 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) 166 && (nnotstringlbl == 0)) { 167 return TYPE_STRING; 168 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 169 return TYPE_UINT32; 170 } 171 172 return TYPE_UINT8; 173 } 174 175 static void write_propval(FILE *f, struct property *prop) 176 { 177 size_t len = prop->val.len; 178 struct marker *m = prop->val.markers; 179 struct marker dummy_marker; 180 enum markertype emit_type = TYPE_NONE; 181 char *srcstr; 182 183 if (len == 0) { 184 fprintf(f, ";"); 185 if (annotate) { 186 srcstr = srcpos_string_first(prop->srcpos, annotate); 187 if (srcstr) { 188 fprintf(f, " /* %s */", srcstr); 189 free(srcstr); 190 } 191 } 192 fprintf(f, "\n"); 193 return; 194 } 195 196 fprintf(f, " ="); 197 198 if (!next_type_marker(m)) { 199 /* data type information missing, need to guess */ 200 dummy_marker.type = guess_value_type(prop); 201 dummy_marker.next = prop->val.markers; 202 dummy_marker.offset = 0; 203 dummy_marker.ref = NULL; 204 m = &dummy_marker; 205 } 206 207 for_each_marker(m) { 208 size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; 209 size_t data_len = type_marker_length(m) ? : len - m->offset; 210 const char *p = &prop->val.val[m->offset]; 211 struct marker *m_phandle; 212 213 if (is_type_marker(m->type)) { 214 emit_type = m->type; 215 fprintf(f, " %s", delim_start[emit_type]); 216 } else if (m->type == LABEL) 217 fprintf(f, " %s:", m->ref); 218 219 if (emit_type == TYPE_NONE || chunk_len == 0) 220 continue; 221 222 switch(emit_type) { 223 case TYPE_UINT16: 224 write_propval_int(f, p, chunk_len, 2); 225 break; 226 case TYPE_UINT32: 227 m_phandle = prop->val.markers; 228 for_each_marker_of_type(m_phandle, REF_PHANDLE) 229 if (m->offset == m_phandle->offset) 230 break; 231 232 if (m_phandle) { 233 if (m_phandle->ref[0] == '/') 234 fprintf(f, "&{%s}", m_phandle->ref); 235 else 236 fprintf(f, "&%s", m_phandle->ref); 237 if (chunk_len > 4) { 238 fputc(' ', f); 239 write_propval_int(f, p + 4, chunk_len - 4, 4); 240 } 241 } else { 242 write_propval_int(f, p, chunk_len, 4); 243 } 244 break; 245 case TYPE_UINT64: 246 write_propval_int(f, p, chunk_len, 8); 247 break; 248 case TYPE_STRING: 249 write_propval_string(f, p, chunk_len); 250 break; 251 default: 252 write_propval_int(f, p, chunk_len, 1); 253 } 254 255 if (chunk_len == data_len) { 256 size_t pos = m->offset + chunk_len; 257 fprintf(f, pos == len ? "%s" : "%s,", 258 delim_end[emit_type] ? : ""); 259 emit_type = TYPE_NONE; 260 } 261 } 262 fprintf(f, ";"); 263 if (annotate) { 264 srcstr = srcpos_string_first(prop->srcpos, annotate); 265 if (srcstr) { 266 fprintf(f, " /* %s */", srcstr); 267 free(srcstr); 268 } 269 } 270 fprintf(f, "\n"); 271 } 272 273 static void write_tree_source_node(FILE *f, struct node *tree, int level) 274 { 275 struct property *prop; 276 struct node *child; 277 struct label *l; 278 char *srcstr; 279 280 write_prefix(f, level); 281 for_each_label(tree->labels, l) 282 fprintf(f, "%s: ", l->label); 283 if (tree->name && (*tree->name)) 284 fprintf(f, "%s {", tree->name); 285 else 286 fprintf(f, "/ {"); 287 288 if (annotate) { 289 srcstr = srcpos_string_first(tree->srcpos, annotate); 290 if (srcstr) { 291 fprintf(f, " /* %s */", srcstr); 292 free(srcstr); 293 } 294 } 295 fprintf(f, "\n"); 296 297 for_each_property(tree, prop) { 298 write_prefix(f, level+1); 299 for_each_label(prop->labels, l) 300 fprintf(f, "%s: ", l->label); 301 fprintf(f, "%s", prop->name); 302 write_propval(f, prop); 303 } 304 for_each_child(tree, child) { 305 fprintf(f, "\n"); 306 write_tree_source_node(f, child, level+1); 307 } 308 write_prefix(f, level); 309 fprintf(f, "};"); 310 if (annotate) { 311 srcstr = srcpos_string_last(tree->srcpos, annotate); 312 if (srcstr) { 313 fprintf(f, " /* %s */", srcstr); 314 free(srcstr); 315 } 316 } 317 fprintf(f, "\n"); 318 } 319 320 void dt_to_source(FILE *f, struct dt_info *dti) 321 { 322 struct reserve_info *re; 323 324 fprintf(f, "/dts-v1/;\n\n"); 325 326 for (re = dti->reservelist; re; re = re->next) { 327 struct label *l; 328 329 for_each_label(re->labels, l) 330 fprintf(f, "%s: ", l->label); 331 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 332 (unsigned long long)re->address, 333 (unsigned long long)re->size); 334 } 335 336 write_tree_source_node(f, dti->dt, 0); 337 } 338