root/scripts/dtc/dtc-parser.y

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. yyerror

   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 <stdio.h>
   7 #include <inttypes.h>
   8 
   9 #include "dtc.h"
  10 #include "srcpos.h"
  11 
  12 extern int yylex(void);
  13 extern void yyerror(char const *s);
  14 #define ERROR(loc, ...) \
  15         do { \
  16                 srcpos_error((loc), "Error", __VA_ARGS__); \
  17                 treesource_error = true; \
  18         } while (0)
  19 
  20 extern struct dt_info *parser_output;
  21 extern bool treesource_error;
  22 %}
  23 
  24 %union {
  25         char *propnodename;
  26         char *labelref;
  27         uint8_t byte;
  28         struct data data;
  29 
  30         struct {
  31                 struct data     data;
  32                 int             bits;
  33         } array;
  34 
  35         struct property *prop;
  36         struct property *proplist;
  37         struct node *node;
  38         struct node *nodelist;
  39         struct reserve_info *re;
  40         uint64_t integer;
  41         unsigned int flags;
  42 }
  43 
  44 %token DT_V1
  45 %token DT_PLUGIN
  46 %token DT_MEMRESERVE
  47 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
  48 %token DT_BITS
  49 %token DT_DEL_PROP
  50 %token DT_DEL_NODE
  51 %token DT_OMIT_NO_REF
  52 %token <propnodename> DT_PROPNODENAME
  53 %token <integer> DT_LITERAL
  54 %token <integer> DT_CHAR_LITERAL
  55 %token <byte> DT_BYTE
  56 %token <data> DT_STRING
  57 %token <labelref> DT_LABEL
  58 %token <labelref> DT_LABEL_REF
  59 %token <labelref> DT_PATH_REF
  60 %token DT_INCBIN
  61 
  62 %type <data> propdata
  63 %type <data> propdataprefix
  64 %type <flags> header
  65 %type <flags> headers
  66 %type <re> memreserve
  67 %type <re> memreserves
  68 %type <array> arrayprefix
  69 %type <data> bytestring
  70 %type <prop> propdef
  71 %type <proplist> proplist
  72 %type <labelref> dt_ref
  73 
  74 %type <node> devicetree
  75 %type <node> nodedef
  76 %type <node> subnode
  77 %type <nodelist> subnodes
  78 
  79 %type <integer> integer_prim
  80 %type <integer> integer_unary
  81 %type <integer> integer_mul
  82 %type <integer> integer_add
  83 %type <integer> integer_shift
  84 %type <integer> integer_rela
  85 %type <integer> integer_eq
  86 %type <integer> integer_bitand
  87 %type <integer> integer_bitxor
  88 %type <integer> integer_bitor
  89 %type <integer> integer_and
  90 %type <integer> integer_or
  91 %type <integer> integer_trinary
  92 %type <integer> integer_expr
  93 
  94 %%
  95 
  96 sourcefile:
  97           headers memreserves devicetree
  98                 {
  99                         parser_output = build_dt_info($1, $2, $3,
 100                                                       guess_boot_cpuid($3));
 101                 }
 102         ;
 103 
 104 header:
 105           DT_V1 ';'
 106                 {
 107                         $$ = DTSF_V1;
 108                 }
 109         | DT_V1 ';' DT_PLUGIN ';'
 110                 {
 111                         $$ = DTSF_V1 | DTSF_PLUGIN;
 112                 }
 113         ;
 114 
 115 headers:
 116           header
 117         | header headers
 118                 {
 119                         if ($2 != $1)
 120                                 ERROR(&@2, "Header flags don't match earlier ones");
 121                         $$ = $1;
 122                 }
 123         ;
 124 
 125 memreserves:
 126           /* empty */
 127                 {
 128                         $$ = NULL;
 129                 }
 130         | memreserve memreserves
 131                 {
 132                         $$ = chain_reserve_entry($1, $2);
 133                 }
 134         ;
 135 
 136 memreserve:
 137           DT_MEMRESERVE integer_prim integer_prim ';'
 138                 {
 139                         $$ = build_reserve_entry($2, $3);
 140                 }
 141         | DT_LABEL memreserve
 142                 {
 143                         add_label(&$2->labels, $1);
 144                         $$ = $2;
 145                 }
 146         ;
 147 
 148 dt_ref: DT_LABEL_REF | DT_PATH_REF;
 149 
 150 devicetree:
 151           '/' nodedef
 152                 {
 153                         $$ = name_node($2, "");
 154                 }
 155         | devicetree '/' nodedef
 156                 {
 157                         $$ = merge_nodes($1, $3);
 158                 }
 159         | dt_ref nodedef
 160                 {
 161                         /*
 162                          * We rely on the rule being always:
 163                          *   versioninfo plugindecl memreserves devicetree
 164                          * so $-1 is what we want (plugindecl)
 165                          */
 166                         if (!($<flags>-1 & DTSF_PLUGIN))
 167                                 ERROR(&@2, "Label or path %s not found", $1);
 168                         $$ = add_orphan_node(
 169                                         name_node(build_node(NULL, NULL, NULL),
 170                                                   ""),
 171                                         $2, $1);
 172                 }
 173         | devicetree DT_LABEL dt_ref nodedef
 174                 {
 175                         struct node *target = get_node_by_ref($1, $3);
 176 
 177                         if (target) {
 178                                 add_label(&target->labels, $2);
 179                                 merge_nodes(target, $4);
 180                         } else
 181                                 ERROR(&@3, "Label or path %s not found", $3);
 182                         $$ = $1;
 183                 }
 184         | devicetree DT_PATH_REF nodedef
 185                 {
 186                         /*
 187                          * We rely on the rule being always:
 188                          *   versioninfo plugindecl memreserves devicetree
 189                          * so $-1 is what we want (plugindecl)
 190                          */
 191                         if ($<flags>-1 & DTSF_PLUGIN) {
 192                                 add_orphan_node($1, $3, $2);
 193                         } else {
 194                                 struct node *target = get_node_by_ref($1, $2);
 195 
 196                                 if (target)
 197                                         merge_nodes(target, $3);
 198                                 else
 199                                         ERROR(&@2, "Label or path %s not found", $2);
 200                         }
 201                         $$ = $1;
 202                 }
 203         | devicetree DT_LABEL_REF nodedef
 204                 {
 205                         struct node *target = get_node_by_ref($1, $2);
 206 
 207                         if (target) {
 208                                 merge_nodes(target, $3);
 209                         } else {
 210                                 /*
 211                                  * We rely on the rule being always:
 212                                  *   versioninfo plugindecl memreserves devicetree
 213                                  * so $-1 is what we want (plugindecl)
 214                                  */
 215                                 if ($<flags>-1 & DTSF_PLUGIN)
 216                                         add_orphan_node($1, $3, $2);
 217                                 else
 218                                         ERROR(&@2, "Label or path %s not found", $2);
 219                         }
 220                         $$ = $1;
 221                 }
 222         | devicetree DT_DEL_NODE dt_ref ';'
 223                 {
 224                         struct node *target = get_node_by_ref($1, $3);
 225 
 226                         if (target)
 227                                 delete_node(target);
 228                         else
 229                                 ERROR(&@3, "Label or path %s not found", $3);
 230 
 231 
 232                         $$ = $1;
 233                 }
 234         | devicetree DT_OMIT_NO_REF dt_ref ';'
 235                 {
 236                         struct node *target = get_node_by_ref($1, $3);
 237 
 238                         if (target)
 239                                 omit_node_if_unused(target);
 240                         else
 241                                 ERROR(&@3, "Label or path %s not found", $3);
 242 
 243 
 244                         $$ = $1;
 245                 }
 246         ;
 247 
 248 nodedef:
 249           '{' proplist subnodes '}' ';'
 250                 {
 251                         $$ = build_node($2, $3, &@$);
 252                 }
 253         ;
 254 
 255 proplist:
 256           /* empty */
 257                 {
 258                         $$ = NULL;
 259                 }
 260         | proplist propdef
 261                 {
 262                         $$ = chain_property($2, $1);
 263                 }
 264         ;
 265 
 266 propdef:
 267           DT_PROPNODENAME '=' propdata ';'
 268                 {
 269                         $$ = build_property($1, $3, &@$);
 270                 }
 271         | DT_PROPNODENAME ';'
 272                 {
 273                         $$ = build_property($1, empty_data, &@$);
 274                 }
 275         | DT_DEL_PROP DT_PROPNODENAME ';'
 276                 {
 277                         $$ = build_property_delete($2);
 278                 }
 279         | DT_LABEL propdef
 280                 {
 281                         add_label(&$2->labels, $1);
 282                         $$ = $2;
 283                 }
 284         ;
 285 
 286 propdata:
 287           propdataprefix DT_STRING
 288                 {
 289                         $$ = data_merge($1, $2);
 290                 }
 291         | propdataprefix arrayprefix '>'
 292                 {
 293                         $$ = data_merge($1, $2.data);
 294                 }
 295         | propdataprefix '[' bytestring ']'
 296                 {
 297                         $$ = data_merge($1, $3);
 298                 }
 299         | propdataprefix dt_ref
 300                 {
 301                         $1 = data_add_marker($1, TYPE_STRING, $2);
 302                         $$ = data_add_marker($1, REF_PATH, $2);
 303                 }
 304         | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
 305                 {
 306                         FILE *f = srcfile_relative_open($4.val, NULL);
 307                         struct data d;
 308 
 309                         if ($6 != 0)
 310                                 if (fseek(f, $6, SEEK_SET) != 0)
 311                                         die("Couldn't seek to offset %llu in \"%s\": %s",
 312                                             (unsigned long long)$6, $4.val,
 313                                             strerror(errno));
 314 
 315                         d = data_copy_file(f, $8);
 316 
 317                         $$ = data_merge($1, d);
 318                         fclose(f);
 319                 }
 320         | propdataprefix DT_INCBIN '(' DT_STRING ')'
 321                 {
 322                         FILE *f = srcfile_relative_open($4.val, NULL);
 323                         struct data d = empty_data;
 324 
 325                         d = data_copy_file(f, -1);
 326 
 327                         $$ = data_merge($1, d);
 328                         fclose(f);
 329                 }
 330         | propdata DT_LABEL
 331                 {
 332                         $$ = data_add_marker($1, LABEL, $2);
 333                 }
 334         ;
 335 
 336 propdataprefix:
 337           /* empty */
 338                 {
 339                         $$ = empty_data;
 340                 }
 341         | propdata ','
 342                 {
 343                         $$ = $1;
 344                 }
 345         | propdataprefix DT_LABEL
 346                 {
 347                         $$ = data_add_marker($1, LABEL, $2);
 348                 }
 349         ;
 350 
 351 arrayprefix:
 352         DT_BITS DT_LITERAL '<'
 353                 {
 354                         unsigned long long bits;
 355                         enum markertype type = TYPE_UINT32;
 356 
 357                         bits = $2;
 358 
 359                         switch (bits) {
 360                         case 8: type = TYPE_UINT8; break;
 361                         case 16: type = TYPE_UINT16; break;
 362                         case 32: type = TYPE_UINT32; break;
 363                         case 64: type = TYPE_UINT64; break;
 364                         default:
 365                                 ERROR(&@2, "Array elements must be"
 366                                       " 8, 16, 32 or 64-bits");
 367                                 bits = 32;
 368                         }
 369 
 370                         $$.data = data_add_marker(empty_data, type, NULL);
 371                         $$.bits = bits;
 372                 }
 373         | '<'
 374                 {
 375                         $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
 376                         $$.bits = 32;
 377                 }
 378         | arrayprefix integer_prim
 379                 {
 380                         if ($1.bits < 64) {
 381                                 uint64_t mask = (1ULL << $1.bits) - 1;
 382                                 /*
 383                                  * Bits above mask must either be all zero
 384                                  * (positive within range of mask) or all one
 385                                  * (negative and sign-extended). The second
 386                                  * condition is true if when we set all bits
 387                                  * within the mask to one (i.e. | in the
 388                                  * mask), all bits are one.
 389                                  */
 390                                 if (($2 > mask) && (($2 | mask) != -1ULL))
 391                                         ERROR(&@2, "Value out of range for"
 392                                               " %d-bit array element", $1.bits);
 393                         }
 394 
 395                         $$.data = data_append_integer($1.data, $2, $1.bits);
 396                 }
 397         | arrayprefix dt_ref
 398                 {
 399                         uint64_t val = ~0ULL >> (64 - $1.bits);
 400 
 401                         if ($1.bits == 32)
 402                                 $1.data = data_add_marker($1.data,
 403                                                           REF_PHANDLE,
 404                                                           $2);
 405                         else
 406                                 ERROR(&@2, "References are only allowed in "
 407                                             "arrays with 32-bit elements.");
 408 
 409                         $$.data = data_append_integer($1.data, val, $1.bits);
 410                 }
 411         | arrayprefix DT_LABEL
 412                 {
 413                         $$.data = data_add_marker($1.data, LABEL, $2);
 414                 }
 415         ;
 416 
 417 integer_prim:
 418           DT_LITERAL
 419         | DT_CHAR_LITERAL
 420         | '(' integer_expr ')'
 421                 {
 422                         $$ = $2;
 423                 }
 424         ;
 425 
 426 integer_expr:
 427         integer_trinary
 428         ;
 429 
 430 integer_trinary:
 431           integer_or
 432         | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
 433         ;
 434 
 435 integer_or:
 436           integer_and
 437         | integer_or DT_OR integer_and { $$ = $1 || $3; }
 438         ;
 439 
 440 integer_and:
 441           integer_bitor
 442         | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
 443         ;
 444 
 445 integer_bitor:
 446           integer_bitxor
 447         | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
 448         ;
 449 
 450 integer_bitxor:
 451           integer_bitand
 452         | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
 453         ;
 454 
 455 integer_bitand:
 456           integer_eq
 457         | integer_bitand '&' integer_eq { $$ = $1 & $3; }
 458         ;
 459 
 460 integer_eq:
 461           integer_rela
 462         | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
 463         | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
 464         ;
 465 
 466 integer_rela:
 467           integer_shift
 468         | integer_rela '<' integer_shift { $$ = $1 < $3; }
 469         | integer_rela '>' integer_shift { $$ = $1 > $3; }
 470         | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
 471         | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
 472         ;
 473 
 474 integer_shift:
 475           integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
 476         | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
 477         | integer_add
 478         ;
 479 
 480 integer_add:
 481           integer_add '+' integer_mul { $$ = $1 + $3; }
 482         | integer_add '-' integer_mul { $$ = $1 - $3; }
 483         | integer_mul
 484         ;
 485 
 486 integer_mul:
 487           integer_mul '*' integer_unary { $$ = $1 * $3; }
 488         | integer_mul '/' integer_unary
 489                 {
 490                         if ($3 != 0) {
 491                                 $$ = $1 / $3;
 492                         } else {
 493                                 ERROR(&@$, "Division by zero");
 494                                 $$ = 0;
 495                         }
 496                 }
 497         | integer_mul '%' integer_unary
 498                 {
 499                         if ($3 != 0) {
 500                                 $$ = $1 % $3;
 501                         } else {
 502                                 ERROR(&@$, "Division by zero");
 503                                 $$ = 0;
 504                         }
 505                 }
 506         | integer_unary
 507         ;
 508 
 509 integer_unary:
 510           integer_prim
 511         | '-' integer_unary { $$ = -$2; }
 512         | '~' integer_unary { $$ = ~$2; }
 513         | '!' integer_unary { $$ = !$2; }
 514         ;
 515 
 516 bytestring:
 517           /* empty */
 518                 {
 519                         $$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
 520                 }
 521         | bytestring DT_BYTE
 522                 {
 523                         $$ = data_append_byte($1, $2);
 524                 }
 525         | bytestring DT_LABEL
 526                 {
 527                         $$ = data_add_marker($1, LABEL, $2);
 528                 }
 529         ;
 530 
 531 subnodes:
 532           /* empty */
 533                 {
 534                         $$ = NULL;
 535                 }
 536         | subnode subnodes
 537                 {
 538                         $$ = chain_node($1, $2);
 539                 }
 540         | subnode propdef
 541                 {
 542                         ERROR(&@2, "Properties must precede subnodes");
 543                         YYERROR;
 544                 }
 545         ;
 546 
 547 subnode:
 548           DT_PROPNODENAME nodedef
 549                 {
 550                         $$ = name_node($2, $1);
 551                 }
 552         | DT_DEL_NODE DT_PROPNODENAME ';'
 553                 {
 554                         $$ = name_node(build_node_delete(&@$), $2);
 555                 }
 556         | DT_OMIT_NO_REF subnode
 557                 {
 558                         $$ = omit_node_if_unused($2);
 559                 }
 560         | DT_LABEL subnode
 561                 {
 562                         add_label(&$2->labels, $1);
 563                         $$ = $2;
 564                 }
 565         ;
 566 
 567 %%
 568 
 569 void yyerror(char const *s)
 570 {
 571         ERROR(&yylloc, "%s", s);
 572 }

/* [<][>][^][v][top][bottom][index][help] */