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 assert(*end == '\0'); 68 69 fprintf(f, "\""); 70 while (s < end) { 71 char c = *s++; 72 switch (c) { 73 case '\a': 74 fprintf(f, "\\a"); 75 break; 76 case '\b': 77 fprintf(f, "\\b"); 78 break; 79 case '\t': 80 fprintf(f, "\\t"); 81 break; 82 case '\n': 83 fprintf(f, "\\n"); 84 break; 85 case '\v': 86 fprintf(f, "\\v"); 87 break; 88 case '\f': 89 fprintf(f, "\\f"); 90 break; 91 case '\r': 92 fprintf(f, "\\r"); 93 break; 94 case '\\': 95 fprintf(f, "\\\\"); 96 break; 97 case '\"': 98 fprintf(f, "\\\""); 99 break; 100 case '\0': 101 fprintf(f, "\\0"); 102 break; 103 default: 104 if (isprint((unsigned char)c)) 105 fprintf(f, "%c", c); 106 else 107 fprintf(f, "\\x%02"PRIx8, c); 108 } 109 } 110 fprintf(f, "\""); 111 } 112 113 static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) 114 { 115 const char *end = p + len; 116 assert(len % width == 0); 117 118 for (; p < end; p += width) { 119 switch (width) { 120 case 1: 121 fprintf(f, " %02"PRIx8, *(const uint8_t*)p); 122 break; 123 case 2: 124 fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); 125 break; 126 case 4: 127 fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); 128 break; 129 case 8: 130 fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); 131 break; 132 } 133 } 134 } 135 136 static bool has_data_type_information(struct marker *m) 137 { 138 return m->type >= TYPE_UINT8; 139 } 140 141 static struct marker *next_type_marker(struct marker *m) 142 { 143 while (m && !has_data_type_information(m)) 144 m = m->next; 145 return m; 146 } 147 148 size_t type_marker_length(struct marker *m) 149 { 150 struct marker *next = next_type_marker(m->next); 151 152 if (next) 153 return next->offset - m->offset; 154 return 0; 155 } 156 157 static const char *delim_start[] = { 158 [TYPE_UINT8] = "[", 159 [TYPE_UINT16] = "/bits/ 16 <", 160 [TYPE_UINT32] = "<", 161 [TYPE_UINT64] = "/bits/ 64 <", 162 [TYPE_STRING] = "", 163 }; 164 static const char *delim_end[] = { 165 [TYPE_UINT8] = " ]", 166 [TYPE_UINT16] = " >", 167 [TYPE_UINT32] = " >", 168 [TYPE_UINT64] = " >", 169 [TYPE_STRING] = "", 170 }; 171 172 static enum markertype guess_value_type(struct property *prop) 173 { 174 int len = prop->val.len; 175 const char *p = prop->val.val; 176 struct marker *m = prop->val.markers; 177 int nnotstring = 0, nnul = 0; 178 int nnotstringlbl = 0, nnotcelllbl = 0; 179 int i; 180 181 for (i = 0; i < len; i++) { 182 if (! isstring(p[i])) 183 nnotstring++; 184 if (p[i] == '\0') 185 nnul++; 186 } 187 188 for_each_marker_of_type(m, LABEL) { 189 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) 190 nnotstringlbl++; 191 if ((m->offset % sizeof(cell_t)) != 0) 192 nnotcelllbl++; 193 } 194 195 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) 196 && (nnotstringlbl == 0)) { 197 return TYPE_STRING; 198 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 199 return TYPE_UINT32; 200 } 201 202 return TYPE_UINT8; 203 } 204 205 static void write_propval(FILE *f, struct property *prop) 206 { 207 size_t len = prop->val.len; 208 struct marker *m = prop->val.markers; 209 struct marker dummy_marker; 210 enum markertype emit_type = TYPE_NONE; 211 212 if (len == 0) { 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 struct marker *m_label = prop->val.markers; 229 for_each_marker(m) { 230 size_t chunk_len; 231 const char *p = &prop->val.val[m->offset]; 232 233 if (!has_data_type_information(m)) 234 continue; 235 236 chunk_len = type_marker_length(m); 237 if (!chunk_len) 238 chunk_len = len - m->offset; 239 240 if (emit_type != TYPE_NONE) 241 fprintf(f, "%s, ", delim_end[emit_type]); 242 emit_type = m->type; 243 244 for_each_marker_of_type(m_label, LABEL) { 245 if (m_label->offset > m->offset) 246 break; 247 fprintf(f, "%s: ", m_label->ref); 248 } 249 250 fprintf(f, "%s", delim_start[emit_type]); 251 252 if (chunk_len <= 0) 253 continue; 254 255 switch(emit_type) { 256 case TYPE_UINT16: 257 write_propval_int(f, p, chunk_len, 2); 258 break; 259 case TYPE_UINT32: 260 write_propval_int(f, p, chunk_len, 4); 261 break; 262 case TYPE_UINT64: 263 write_propval_int(f, p, chunk_len, 8); 264 break; 265 case TYPE_STRING: 266 write_propval_string(f, p, chunk_len); 267 break; 268 default: 269 write_propval_int(f, p, chunk_len, 1); 270 } 271 } 272 273 /* Wrap up any labels at the end of the value */ 274 for_each_marker_of_type(m_label, LABEL) { 275 assert (m_label->offset == len); 276 fprintf(f, " %s:", m_label->ref); 277 } 278 279 fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); 280 } 281 282 static void write_tree_source_node(FILE *f, struct node *tree, int level) 283 { 284 struct property *prop; 285 struct node *child; 286 struct label *l; 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 {\n", tree->name); 293 else 294 fprintf(f, "/ {\n"); 295 296 for_each_property(tree, prop) { 297 write_prefix(f, level+1); 298 for_each_label(prop->labels, l) 299 fprintf(f, "%s: ", l->label); 300 fprintf(f, "%s", prop->name); 301 write_propval(f, prop); 302 } 303 for_each_child(tree, child) { 304 fprintf(f, "\n"); 305 write_tree_source_node(f, child, level+1); 306 } 307 write_prefix(f, level); 308 fprintf(f, "};\n"); 309 } 310 311 312 void dt_to_source(FILE *f, struct dt_info *dti) 313 { 314 struct reserve_info *re; 315 316 fprintf(f, "/dts-v1/;\n\n"); 317 318 for (re = dti->reservelist; re; re = re->next) { 319 struct label *l; 320 321 for_each_label(re->labels, l) 322 fprintf(f, "%s: ", l->label); 323 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", 324 (unsigned long long)re->address, 325 (unsigned long long)re->size); 326 } 327 328 write_tree_source_node(f, dti->dt, 0); 329 } 330