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