0001
0002
0003
0004
0005
0006 #include "dtc.h"
0007 #include "srcpos.h"
0008
0009 extern FILE *yyin;
0010 extern int yyparse(void);
0011 extern YYLTYPE yylloc;
0012
0013 struct dt_info *parser_output;
0014 bool treesource_error;
0015
0016 struct dt_info *dt_from_source(const char *fname)
0017 {
0018 parser_output = NULL;
0019 treesource_error = false;
0020
0021 srcfile_push(fname);
0022 yyin = current_srcfile->f;
0023 yylloc.file = current_srcfile;
0024
0025 if (yyparse() != 0)
0026 die("Unable to parse input tree\n");
0027
0028 if (treesource_error)
0029 die("Syntax error parsing input tree\n");
0030
0031 return parser_output;
0032 }
0033
0034 static void write_prefix(FILE *f, int level)
0035 {
0036 int i;
0037
0038 for (i = 0; i < level; i++)
0039 fputc('\t', f);
0040 }
0041
0042 static bool isstring(char c)
0043 {
0044 return (isprint((unsigned char)c)
0045 || (c == '\0')
0046 || strchr("\a\b\t\n\v\f\r", c));
0047 }
0048
0049 static void write_propval_string(FILE *f, const char *s, size_t len)
0050 {
0051 const char *end = s + len - 1;
0052
0053 if (!len)
0054 return;
0055
0056 assert(*end == '\0');
0057
0058 fprintf(f, "\"");
0059 while (s < end) {
0060 char c = *s++;
0061 switch (c) {
0062 case '\a':
0063 fprintf(f, "\\a");
0064 break;
0065 case '\b':
0066 fprintf(f, "\\b");
0067 break;
0068 case '\t':
0069 fprintf(f, "\\t");
0070 break;
0071 case '\n':
0072 fprintf(f, "\\n");
0073 break;
0074 case '\v':
0075 fprintf(f, "\\v");
0076 break;
0077 case '\f':
0078 fprintf(f, "\\f");
0079 break;
0080 case '\r':
0081 fprintf(f, "\\r");
0082 break;
0083 case '\\':
0084 fprintf(f, "\\\\");
0085 break;
0086 case '\"':
0087 fprintf(f, "\\\"");
0088 break;
0089 case '\0':
0090 fprintf(f, "\\0");
0091 break;
0092 default:
0093 if (isprint((unsigned char)c))
0094 fprintf(f, "%c", c);
0095 else
0096 fprintf(f, "\\x%02"PRIx8, c);
0097 }
0098 }
0099 fprintf(f, "\"");
0100 }
0101
0102 static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
0103 {
0104 const char *end = p + len;
0105 assert(len % width == 0);
0106
0107 for (; p < end; p += width) {
0108 switch (width) {
0109 case 1:
0110 fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
0111 break;
0112 case 2:
0113 fprintf(f, "0x%02"PRIx16, dtb_ld16(p));
0114 break;
0115 case 4:
0116 fprintf(f, "0x%02"PRIx32, dtb_ld32(p));
0117 break;
0118 case 8:
0119 fprintf(f, "0x%02"PRIx64, dtb_ld64(p));
0120 break;
0121 }
0122 if (p + width < end)
0123 fputc(' ', f);
0124 }
0125 }
0126
0127 static const char *delim_start[] = {
0128 [TYPE_UINT8] = "[",
0129 [TYPE_UINT16] = "/bits/ 16 <",
0130 [TYPE_UINT32] = "<",
0131 [TYPE_UINT64] = "/bits/ 64 <",
0132 [TYPE_STRING] = "",
0133 };
0134 static const char *delim_end[] = {
0135 [TYPE_UINT8] = "]",
0136 [TYPE_UINT16] = ">",
0137 [TYPE_UINT32] = ">",
0138 [TYPE_UINT64] = ">",
0139 [TYPE_STRING] = "",
0140 };
0141
0142 static enum markertype guess_value_type(struct property *prop)
0143 {
0144 int len = prop->val.len;
0145 const char *p = prop->val.val;
0146 struct marker *m = prop->val.markers;
0147 int nnotstring = 0, nnul = 0;
0148 int nnotstringlbl = 0, nnotcelllbl = 0;
0149 int i;
0150
0151 for (i = 0; i < len; i++) {
0152 if (! isstring(p[i]))
0153 nnotstring++;
0154 if (p[i] == '\0')
0155 nnul++;
0156 }
0157
0158 for_each_marker_of_type(m, LABEL) {
0159 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
0160 nnotstringlbl++;
0161 if ((m->offset % sizeof(cell_t)) != 0)
0162 nnotcelllbl++;
0163 }
0164
0165 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
0166 && (nnotstringlbl == 0)) {
0167 return TYPE_STRING;
0168 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
0169 return TYPE_UINT32;
0170 }
0171
0172 return TYPE_UINT8;
0173 }
0174
0175 static void write_propval(FILE *f, struct property *prop)
0176 {
0177 size_t len = prop->val.len;
0178 struct marker *m = prop->val.markers;
0179 struct marker dummy_marker;
0180 enum markertype emit_type = TYPE_NONE;
0181 char *srcstr;
0182
0183 if (len == 0) {
0184 fprintf(f, ";");
0185 if (annotate) {
0186 srcstr = srcpos_string_first(prop->srcpos, annotate);
0187 if (srcstr) {
0188 fprintf(f, " /* %s */", srcstr);
0189 free(srcstr);
0190 }
0191 }
0192 fprintf(f, "\n");
0193 return;
0194 }
0195
0196 fprintf(f, " =");
0197
0198 if (!next_type_marker(m)) {
0199
0200 dummy_marker.type = guess_value_type(prop);
0201 dummy_marker.next = prop->val.markers;
0202 dummy_marker.offset = 0;
0203 dummy_marker.ref = NULL;
0204 m = &dummy_marker;
0205 }
0206
0207 for_each_marker(m) {
0208 size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
0209 size_t data_len = type_marker_length(m) ? : len - m->offset;
0210 const char *p = &prop->val.val[m->offset];
0211 struct marker *m_phandle;
0212
0213 if (is_type_marker(m->type)) {
0214 emit_type = m->type;
0215 fprintf(f, " %s", delim_start[emit_type]);
0216 } else if (m->type == LABEL)
0217 fprintf(f, " %s:", m->ref);
0218
0219 if (emit_type == TYPE_NONE || chunk_len == 0)
0220 continue;
0221
0222 switch(emit_type) {
0223 case TYPE_UINT16:
0224 write_propval_int(f, p, chunk_len, 2);
0225 break;
0226 case TYPE_UINT32:
0227 m_phandle = prop->val.markers;
0228 for_each_marker_of_type(m_phandle, REF_PHANDLE)
0229 if (m->offset == m_phandle->offset)
0230 break;
0231
0232 if (m_phandle) {
0233 if (m_phandle->ref[0] == '/')
0234 fprintf(f, "&{%s}", m_phandle->ref);
0235 else
0236 fprintf(f, "&%s", m_phandle->ref);
0237 if (chunk_len > 4) {
0238 fputc(' ', f);
0239 write_propval_int(f, p + 4, chunk_len - 4, 4);
0240 }
0241 } else {
0242 write_propval_int(f, p, chunk_len, 4);
0243 }
0244 break;
0245 case TYPE_UINT64:
0246 write_propval_int(f, p, chunk_len, 8);
0247 break;
0248 case TYPE_STRING:
0249 write_propval_string(f, p, chunk_len);
0250 break;
0251 default:
0252 write_propval_int(f, p, chunk_len, 1);
0253 }
0254
0255 if (chunk_len == data_len) {
0256 size_t pos = m->offset + chunk_len;
0257 fprintf(f, pos == len ? "%s" : "%s,",
0258 delim_end[emit_type] ? : "");
0259 emit_type = TYPE_NONE;
0260 }
0261 }
0262 fprintf(f, ";");
0263 if (annotate) {
0264 srcstr = srcpos_string_first(prop->srcpos, annotate);
0265 if (srcstr) {
0266 fprintf(f, " /* %s */", srcstr);
0267 free(srcstr);
0268 }
0269 }
0270 fprintf(f, "\n");
0271 }
0272
0273 static void write_tree_source_node(FILE *f, struct node *tree, int level)
0274 {
0275 struct property *prop;
0276 struct node *child;
0277 struct label *l;
0278 char *srcstr;
0279
0280 write_prefix(f, level);
0281 for_each_label(tree->labels, l)
0282 fprintf(f, "%s: ", l->label);
0283 if (tree->name && (*tree->name))
0284 fprintf(f, "%s {", tree->name);
0285 else
0286 fprintf(f, "/ {");
0287
0288 if (annotate) {
0289 srcstr = srcpos_string_first(tree->srcpos, annotate);
0290 if (srcstr) {
0291 fprintf(f, " /* %s */", srcstr);
0292 free(srcstr);
0293 }
0294 }
0295 fprintf(f, "\n");
0296
0297 for_each_property(tree, prop) {
0298 write_prefix(f, level+1);
0299 for_each_label(prop->labels, l)
0300 fprintf(f, "%s: ", l->label);
0301 fprintf(f, "%s", prop->name);
0302 write_propval(f, prop);
0303 }
0304 for_each_child(tree, child) {
0305 fprintf(f, "\n");
0306 write_tree_source_node(f, child, level+1);
0307 }
0308 write_prefix(f, level);
0309 fprintf(f, "};");
0310 if (annotate) {
0311 srcstr = srcpos_string_last(tree->srcpos, annotate);
0312 if (srcstr) {
0313 fprintf(f, " /* %s */", srcstr);
0314 free(srcstr);
0315 }
0316 }
0317 fprintf(f, "\n");
0318 }
0319
0320 void dt_to_source(FILE *f, struct dt_info *dti)
0321 {
0322 struct reserve_info *re;
0323
0324 fprintf(f, "/dts-v1/;\n\n");
0325
0326 for (re = dti->reservelist; re; re = re->next) {
0327 struct label *l;
0328
0329 for_each_label(re->labels, l)
0330 fprintf(f, "%s: ", l->label);
0331 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
0332 (unsigned long long)re->address,
0333 (unsigned long long)re->size);
0334 }
0335
0336 write_tree_source_node(f, dti->dt, 0);
0337 }