linux/scripts/dtc/dtc-parser.y
<<
>>
Prefs
   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%locations
  22
  23%{
  24#include <stdio.h>
  25
  26#include "dtc.h"
  27#include "srcpos.h"
  28
  29extern int yylex(void);
  30
  31extern struct boot_info *the_boot_info;
  32extern int treesource_error;
  33
  34static unsigned long long eval_literal(const char *s, int base, int bits);
  35%}
  36
  37%union {
  38        char *propnodename;
  39        char *literal;
  40        char *labelref;
  41        unsigned int cbase;
  42        uint8_t byte;
  43        struct data data;
  44
  45        uint64_t addr;
  46        cell_t cell;
  47        struct property *prop;
  48        struct property *proplist;
  49        struct node *node;
  50        struct node *nodelist;
  51        struct reserve_info *re;
  52}
  53
  54%token DT_V1
  55%token DT_MEMRESERVE
  56%token <propnodename> DT_PROPNODENAME
  57%token <literal> DT_LITERAL
  58%token <literal> DT_LEGACYLITERAL
  59%token <cbase> DT_BASE
  60%token <byte> DT_BYTE
  61%token <data> DT_STRING
  62%token <labelref> DT_LABEL
  63%token <labelref> DT_REF
  64%token DT_INCBIN
  65
  66%type <data> propdata
  67%type <data> propdataprefix
  68%type <re> memreserve
  69%type <re> memreserves
  70%type <re> v0_memreserve
  71%type <re> v0_memreserves
  72%type <addr> addr
  73%type <data> celllist
  74%type <cbase> cellbase
  75%type <cell> cellval
  76%type <data> bytestring
  77%type <prop> propdef
  78%type <proplist> proplist
  79
  80%type <node> devicetree
  81%type <node> nodedef
  82%type <node> subnode
  83%type <nodelist> subnodes
  84%type <labelref> label
  85
  86%%
  87
  88sourcefile:
  89          DT_V1 ';' memreserves devicetree
  90                {
  91                        the_boot_info = build_boot_info($3, $4, 0);
  92                }
  93        | v0_memreserves devicetree
  94                {
  95                        the_boot_info = build_boot_info($1, $2, 0);
  96                }
  97        ;
  98
  99memreserves:
 100          /* empty */
 101                {
 102                        $$ = NULL;
 103                }
 104        | memreserve memreserves
 105                {
 106                        $$ = chain_reserve_entry($1, $2);
 107                }
 108        ;
 109
 110memreserve:
 111          label DT_MEMRESERVE addr addr ';'
 112                {
 113                        $$ = build_reserve_entry($3, $4, $1);
 114                }
 115        ;
 116
 117v0_memreserves:
 118          /* empty */
 119                {
 120                        $$ = NULL;
 121                }
 122        | v0_memreserve v0_memreserves
 123                {
 124                        $$ = chain_reserve_entry($1, $2);
 125                };
 126        ;
 127
 128v0_memreserve:
 129          memreserve
 130                {
 131                        $$ = $1;
 132                }
 133        | label DT_MEMRESERVE addr '-' addr ';'
 134                {
 135                        $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
 136                }
 137        ;
 138
 139addr:
 140          DT_LITERAL
 141                {
 142                        $$ = eval_literal($1, 0, 64);
 143                }
 144        | DT_LEGACYLITERAL
 145                {
 146                        $$ = eval_literal($1, 16, 64);
 147                }
 148          ;
 149
 150devicetree:
 151          '/' nodedef
 152                {
 153                        $$ = name_node($2, "", NULL);
 154                }
 155        ;
 156
 157nodedef:
 158          '{' proplist subnodes '}' ';'
 159                {
 160                        $$ = build_node($2, $3);
 161                }
 162        ;
 163
 164proplist:
 165          /* empty */
 166                {
 167                        $$ = NULL;
 168                }
 169        | proplist propdef
 170                {
 171                        $$ = chain_property($2, $1);
 172                }
 173        ;
 174
 175propdef:
 176          label DT_PROPNODENAME '=' propdata ';'
 177                {
 178                        $$ = build_property($2, $4, $1);
 179                }
 180        | label DT_PROPNODENAME ';'
 181                {
 182                        $$ = build_property($2, empty_data, $1);
 183                }
 184        ;
 185
 186propdata:
 187          propdataprefix DT_STRING
 188                {
 189                        $$ = data_merge($1, $2);
 190                }
 191        | propdataprefix '<' celllist '>'
 192                {
 193                        $$ = data_merge($1, $3);
 194                }
 195        | propdataprefix '[' bytestring ']'
 196                {
 197                        $$ = data_merge($1, $3);
 198                }
 199        | propdataprefix DT_REF
 200                {
 201                        $$ = data_add_marker($1, REF_PATH, $2);
 202                }
 203        | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
 204                {
 205                        struct search_path path = { srcpos_file->dir, NULL, NULL };
 206                        struct dtc_file *file = dtc_open_file($4.val, &path);
 207                        struct data d = empty_data;
 208
 209                        if ($6 != 0)
 210                                if (fseek(file->file, $6, SEEK_SET) != 0)
 211                                        yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
 212                                                 (unsigned long long)$6,
 213                                                 $4.val, strerror(errno));
 214
 215                        d = data_copy_file(file->file, $8);
 216
 217                        $$ = data_merge($1, d);
 218                        dtc_close_file(file);
 219                }
 220        | propdataprefix DT_INCBIN '(' DT_STRING ')'
 221                {
 222                        struct search_path path = { srcpos_file->dir, NULL, NULL };
 223                        struct dtc_file *file = dtc_open_file($4.val, &path);
 224                        struct data d = empty_data;
 225
 226                        d = data_copy_file(file->file, -1);
 227
 228                        $$ = data_merge($1, d);
 229                        dtc_close_file(file);
 230                }
 231        | propdata DT_LABEL
 232                {
 233                        $$ = data_add_marker($1, LABEL, $2);
 234                }
 235        ;
 236
 237propdataprefix:
 238          /* empty */
 239                {
 240                        $$ = empty_data;
 241                }
 242        | propdata ','
 243                {
 244                        $$ = $1;
 245                }
 246        | propdataprefix DT_LABEL
 247                {
 248                        $$ = data_add_marker($1, LABEL, $2);
 249                }
 250        ;
 251
 252celllist:
 253          /* empty */
 254                {
 255                        $$ = empty_data;
 256                }
 257        | celllist cellval
 258                {
 259                        $$ = data_append_cell($1, $2);
 260                }
 261        | celllist DT_REF
 262                {
 263                        $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
 264                                                              $2), -1);
 265                }
 266        | celllist DT_LABEL
 267                {
 268                        $$ = data_add_marker($1, LABEL, $2);
 269                }
 270        ;
 271
 272cellbase:
 273          /* empty */
 274                {
 275                        $$ = 16;
 276                }
 277        | DT_BASE
 278        ;
 279
 280cellval:
 281          DT_LITERAL
 282                {
 283                        $$ = eval_literal($1, 0, 32);
 284                }
 285        | cellbase DT_LEGACYLITERAL
 286                {
 287                        $$ = eval_literal($2, $1, 32);
 288                }
 289        ;
 290
 291bytestring:
 292          /* empty */
 293                {
 294                        $$ = empty_data;
 295                }
 296        | bytestring DT_BYTE
 297                {
 298                        $$ = data_append_byte($1, $2);
 299                }
 300        | bytestring DT_LABEL
 301                {
 302                        $$ = data_add_marker($1, LABEL, $2);
 303                }
 304        ;
 305
 306subnodes:
 307          /* empty */
 308                {
 309                        $$ = NULL;
 310                }
 311        |  subnode subnodes
 312                {
 313                        $$ = chain_node($1, $2);
 314                }
 315        | subnode propdef
 316                {
 317                        yyerror("syntax error: properties must precede subnodes");
 318                        YYERROR;
 319                }
 320        ;
 321
 322subnode:
 323          label DT_PROPNODENAME nodedef
 324                {
 325                        $$ = name_node($3, $2, $1);
 326                }
 327        ;
 328
 329label:
 330          /* empty */
 331                {
 332                        $$ = NULL;
 333                }
 334        | DT_LABEL
 335                {
 336                        $$ = $1;
 337                }
 338        ;
 339
 340%%
 341
 342void yyerrorf(char const *s, ...)
 343{
 344        const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
 345        va_list va;
 346        va_start(va, s);
 347
 348        if (strcmp(fname, "-") == 0)
 349                fname = "stdin";
 350
 351        fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
 352        vfprintf(stderr, s, va);
 353        fprintf(stderr, "\n");
 354
 355        treesource_error = 1;
 356        va_end(va);
 357}
 358
 359void yyerror (char const *s)
 360{
 361        yyerrorf("%s", s);
 362}
 363
 364static unsigned long long eval_literal(const char *s, int base, int bits)
 365{
 366        unsigned long long val;
 367        char *e;
 368
 369        errno = 0;
 370        val = strtoull(s, &e, base);
 371        if (*e)
 372                yyerror("bad characters in literal");
 373        else if ((errno == ERANGE)
 374                 || ((bits < 64) && (val >= (1ULL << bits))))
 375                yyerror("literal out of range");
 376        else if (errno != 0)
 377                yyerror("bad literal");
 378        return val;
 379}
 380