Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
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         /* data type information missing, need to guess */
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 }