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