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 %locations
0006 
0007 %{
0008 #include <stdio.h>
0009 #include <inttypes.h>
0010 
0011 #include "dtc.h"
0012 #include "srcpos.h"
0013 
0014 extern int yylex(void);
0015 extern void yyerror(char const *s);
0016 #define ERROR(loc, ...) \
0017         do { \
0018                 srcpos_error((loc), "Error", __VA_ARGS__); \
0019                 treesource_error = true; \
0020         } while (0)
0021 
0022 #define YYERROR_CALL(msg) yyerror(msg)
0023 
0024 extern struct dt_info *parser_output;
0025 extern bool treesource_error;
0026 %}
0027 
0028 %union {
0029         char *propnodename;
0030         char *labelref;
0031         uint8_t byte;
0032         struct data data;
0033 
0034         struct {
0035                 struct data     data;
0036                 int             bits;
0037         } array;
0038 
0039         struct property *prop;
0040         struct property *proplist;
0041         struct node *node;
0042         struct node *nodelist;
0043         struct reserve_info *re;
0044         uint64_t integer;
0045         unsigned int flags;
0046 }
0047 
0048 %token DT_V1
0049 %token DT_PLUGIN
0050 %token DT_MEMRESERVE
0051 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
0052 %token DT_BITS
0053 %token DT_DEL_PROP
0054 %token DT_DEL_NODE
0055 %token DT_OMIT_NO_REF
0056 %token <propnodename> DT_PROPNODENAME
0057 %token <integer> DT_LITERAL
0058 %token <integer> DT_CHAR_LITERAL
0059 %token <byte> DT_BYTE
0060 %token <data> DT_STRING
0061 %token <labelref> DT_LABEL
0062 %token <labelref> DT_LABEL_REF
0063 %token <labelref> DT_PATH_REF
0064 %token DT_INCBIN
0065 
0066 %type <data> propdata
0067 %type <data> propdataprefix
0068 %type <flags> header
0069 %type <flags> headers
0070 %type <re> memreserve
0071 %type <re> memreserves
0072 %type <array> arrayprefix
0073 %type <data> bytestring
0074 %type <prop> propdef
0075 %type <proplist> proplist
0076 %type <labelref> dt_ref
0077 
0078 %type <node> devicetree
0079 %type <node> nodedef
0080 %type <node> subnode
0081 %type <nodelist> subnodes
0082 
0083 %type <integer> integer_prim
0084 %type <integer> integer_unary
0085 %type <integer> integer_mul
0086 %type <integer> integer_add
0087 %type <integer> integer_shift
0088 %type <integer> integer_rela
0089 %type <integer> integer_eq
0090 %type <integer> integer_bitand
0091 %type <integer> integer_bitxor
0092 %type <integer> integer_bitor
0093 %type <integer> integer_and
0094 %type <integer> integer_or
0095 %type <integer> integer_trinary
0096 %type <integer> integer_expr
0097 
0098 %%
0099 
0100 sourcefile:
0101           headers memreserves devicetree
0102                 {
0103                         parser_output = build_dt_info($1, $2, $3,
0104                                                       guess_boot_cpuid($3));
0105                 }
0106         ;
0107 
0108 header:
0109           DT_V1 ';'
0110                 {
0111                         $$ = DTSF_V1;
0112                 }
0113         | DT_V1 ';' DT_PLUGIN ';'
0114                 {
0115                         $$ = DTSF_V1 | DTSF_PLUGIN;
0116                 }
0117         ;
0118 
0119 headers:
0120           header
0121         | header headers
0122                 {
0123                         if ($2 != $1)
0124                                 ERROR(&@2, "Header flags don't match earlier ones");
0125                         $$ = $1;
0126                 }
0127         ;
0128 
0129 memreserves:
0130           /* empty */
0131                 {
0132                         $$ = NULL;
0133                 }
0134         | memreserve memreserves
0135                 {
0136                         $$ = chain_reserve_entry($1, $2);
0137                 }
0138         ;
0139 
0140 memreserve:
0141           DT_MEMRESERVE integer_prim integer_prim ';'
0142                 {
0143                         $$ = build_reserve_entry($2, $3);
0144                 }
0145         | DT_LABEL memreserve
0146                 {
0147                         add_label(&$2->labels, $1);
0148                         $$ = $2;
0149                 }
0150         ;
0151 
0152 dt_ref: DT_LABEL_REF | DT_PATH_REF;
0153 
0154 devicetree:
0155           '/' nodedef
0156                 {
0157                         $$ = name_node($2, "");
0158                 }
0159         | devicetree '/' nodedef
0160                 {
0161                         $$ = merge_nodes($1, $3);
0162                 }
0163         | dt_ref nodedef
0164                 {
0165                         /*
0166                          * We rely on the rule being always:
0167                          *   versioninfo plugindecl memreserves devicetree
0168                          * so $-1 is what we want (plugindecl)
0169                          */
0170                         if (!($<flags>-1 & DTSF_PLUGIN))
0171                                 ERROR(&@2, "Label or path %s not found", $1);
0172                         $$ = add_orphan_node(
0173                                         name_node(build_node(NULL, NULL, NULL),
0174                                                   ""),
0175                                         $2, $1);
0176                 }
0177         | devicetree DT_LABEL dt_ref nodedef
0178                 {
0179                         struct node *target = get_node_by_ref($1, $3);
0180 
0181                         if (target) {
0182                                 add_label(&target->labels, $2);
0183                                 merge_nodes(target, $4);
0184                         } else
0185                                 ERROR(&@3, "Label or path %s not found", $3);
0186                         $$ = $1;
0187                 }
0188         | devicetree DT_PATH_REF nodedef
0189                 {
0190                         /*
0191                          * We rely on the rule being always:
0192                          *   versioninfo plugindecl memreserves devicetree
0193                          * so $-1 is what we want (plugindecl)
0194                          */
0195                         if ($<flags>-1 & DTSF_PLUGIN) {
0196                                 add_orphan_node($1, $3, $2);
0197                         } else {
0198                                 struct node *target = get_node_by_ref($1, $2);
0199 
0200                                 if (target)
0201                                         merge_nodes(target, $3);
0202                                 else
0203                                         ERROR(&@2, "Label or path %s not found", $2);
0204                         }
0205                         $$ = $1;
0206                 }
0207         | devicetree DT_LABEL_REF nodedef
0208                 {
0209                         struct node *target = get_node_by_ref($1, $2);
0210 
0211                         if (target) {
0212                                 merge_nodes(target, $3);
0213                         } else {
0214                                 /*
0215                                  * We rely on the rule being always:
0216                                  *   versioninfo plugindecl memreserves devicetree
0217                                  * so $-1 is what we want (plugindecl)
0218                                  */
0219                                 if ($<flags>-1 & DTSF_PLUGIN)
0220                                         add_orphan_node($1, $3, $2);
0221                                 else
0222                                         ERROR(&@2, "Label or path %s not found", $2);
0223                         }
0224                         $$ = $1;
0225                 }
0226         | devicetree DT_DEL_NODE dt_ref ';'
0227                 {
0228                         struct node *target = get_node_by_ref($1, $3);
0229 
0230                         if (target)
0231                                 delete_node(target);
0232                         else
0233                                 ERROR(&@3, "Label or path %s not found", $3);
0234 
0235 
0236                         $$ = $1;
0237                 }
0238         | devicetree DT_OMIT_NO_REF dt_ref ';'
0239                 {
0240                         struct node *target = get_node_by_ref($1, $3);
0241 
0242                         if (target)
0243                                 omit_node_if_unused(target);
0244                         else
0245                                 ERROR(&@3, "Label or path %s not found", $3);
0246 
0247 
0248                         $$ = $1;
0249                 }
0250         ;
0251 
0252 nodedef:
0253           '{' proplist subnodes '}' ';'
0254                 {
0255                         $$ = build_node($2, $3, &@$);
0256                 }
0257         ;
0258 
0259 proplist:
0260           /* empty */
0261                 {
0262                         $$ = NULL;
0263                 }
0264         | proplist propdef
0265                 {
0266                         $$ = chain_property($2, $1);
0267                 }
0268         ;
0269 
0270 propdef:
0271           DT_PROPNODENAME '=' propdata ';'
0272                 {
0273                         $$ = build_property($1, $3, &@$);
0274                 }
0275         | DT_PROPNODENAME ';'
0276                 {
0277                         $$ = build_property($1, empty_data, &@$);
0278                 }
0279         | DT_DEL_PROP DT_PROPNODENAME ';'
0280                 {
0281                         $$ = build_property_delete($2);
0282                 }
0283         | DT_LABEL propdef
0284                 {
0285                         add_label(&$2->labels, $1);
0286                         $$ = $2;
0287                 }
0288         ;
0289 
0290 propdata:
0291           propdataprefix DT_STRING
0292                 {
0293                         $$ = data_merge($1, $2);
0294                 }
0295         | propdataprefix arrayprefix '>'
0296                 {
0297                         $$ = data_merge($1, $2.data);
0298                 }
0299         | propdataprefix '[' bytestring ']'
0300                 {
0301                         $$ = data_merge($1, $3);
0302                 }
0303         | propdataprefix dt_ref
0304                 {
0305                         $1 = data_add_marker($1, TYPE_STRING, $2);
0306                         $$ = data_add_marker($1, REF_PATH, $2);
0307                 }
0308         | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
0309                 {
0310                         FILE *f = srcfile_relative_open($4.val, NULL);
0311                         struct data d;
0312 
0313                         if ($6 != 0)
0314                                 if (fseek(f, $6, SEEK_SET) != 0)
0315                                         die("Couldn't seek to offset %llu in \"%s\": %s",
0316                                             (unsigned long long)$6, $4.val,
0317                                             strerror(errno));
0318 
0319                         d = data_copy_file(f, $8);
0320 
0321                         $$ = data_merge($1, d);
0322                         fclose(f);
0323                 }
0324         | propdataprefix DT_INCBIN '(' DT_STRING ')'
0325                 {
0326                         FILE *f = srcfile_relative_open($4.val, NULL);
0327                         struct data d = empty_data;
0328 
0329                         d = data_copy_file(f, -1);
0330 
0331                         $$ = data_merge($1, d);
0332                         fclose(f);
0333                 }
0334         | propdata DT_LABEL
0335                 {
0336                         $$ = data_add_marker($1, LABEL, $2);
0337                 }
0338         ;
0339 
0340 propdataprefix:
0341           /* empty */
0342                 {
0343                         $$ = empty_data;
0344                 }
0345         | propdata ','
0346                 {
0347                         $$ = $1;
0348                 }
0349         | propdataprefix DT_LABEL
0350                 {
0351                         $$ = data_add_marker($1, LABEL, $2);
0352                 }
0353         ;
0354 
0355 arrayprefix:
0356         DT_BITS DT_LITERAL '<'
0357                 {
0358                         unsigned long long bits;
0359                         enum markertype type = TYPE_UINT32;
0360 
0361                         bits = $2;
0362 
0363                         switch (bits) {
0364                         case 8: type = TYPE_UINT8; break;
0365                         case 16: type = TYPE_UINT16; break;
0366                         case 32: type = TYPE_UINT32; break;
0367                         case 64: type = TYPE_UINT64; break;
0368                         default:
0369                                 ERROR(&@2, "Array elements must be"
0370                                       " 8, 16, 32 or 64-bits");
0371                                 bits = 32;
0372                         }
0373 
0374                         $$.data = data_add_marker(empty_data, type, NULL);
0375                         $$.bits = bits;
0376                 }
0377         | '<'
0378                 {
0379                         $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
0380                         $$.bits = 32;
0381                 }
0382         | arrayprefix integer_prim
0383                 {
0384                         if ($1.bits < 64) {
0385                                 uint64_t mask = (1ULL << $1.bits) - 1;
0386                                 /*
0387                                  * Bits above mask must either be all zero
0388                                  * (positive within range of mask) or all one
0389                                  * (negative and sign-extended). The second
0390                                  * condition is true if when we set all bits
0391                                  * within the mask to one (i.e. | in the
0392                                  * mask), all bits are one.
0393                                  */
0394                                 if (($2 > mask) && (($2 | mask) != -1ULL))
0395                                         ERROR(&@2, "Value out of range for"
0396                                               " %d-bit array element", $1.bits);
0397                         }
0398 
0399                         $$.data = data_append_integer($1.data, $2, $1.bits);
0400                 }
0401         | arrayprefix dt_ref
0402                 {
0403                         uint64_t val = ~0ULL >> (64 - $1.bits);
0404 
0405                         if ($1.bits == 32)
0406                                 $1.data = data_add_marker($1.data,
0407                                                           REF_PHANDLE,
0408                                                           $2);
0409                         else
0410                                 ERROR(&@2, "References are only allowed in "
0411                                             "arrays with 32-bit elements.");
0412 
0413                         $$.data = data_append_integer($1.data, val, $1.bits);
0414                 }
0415         | arrayprefix DT_LABEL
0416                 {
0417                         $$.data = data_add_marker($1.data, LABEL, $2);
0418                 }
0419         ;
0420 
0421 integer_prim:
0422           DT_LITERAL
0423         | DT_CHAR_LITERAL
0424         | '(' integer_expr ')'
0425                 {
0426                         $$ = $2;
0427                 }
0428         ;
0429 
0430 integer_expr:
0431         integer_trinary
0432         ;
0433 
0434 integer_trinary:
0435           integer_or
0436         | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
0437         ;
0438 
0439 integer_or:
0440           integer_and
0441         | integer_or DT_OR integer_and { $$ = $1 || $3; }
0442         ;
0443 
0444 integer_and:
0445           integer_bitor
0446         | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
0447         ;
0448 
0449 integer_bitor:
0450           integer_bitxor
0451         | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
0452         ;
0453 
0454 integer_bitxor:
0455           integer_bitand
0456         | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
0457         ;
0458 
0459 integer_bitand:
0460           integer_eq
0461         | integer_bitand '&' integer_eq { $$ = $1 & $3; }
0462         ;
0463 
0464 integer_eq:
0465           integer_rela
0466         | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
0467         | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
0468         ;
0469 
0470 integer_rela:
0471           integer_shift
0472         | integer_rela '<' integer_shift { $$ = $1 < $3; }
0473         | integer_rela '>' integer_shift { $$ = $1 > $3; }
0474         | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
0475         | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
0476         ;
0477 
0478 integer_shift:
0479           integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
0480         | integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
0481         | integer_add
0482         ;
0483 
0484 integer_add:
0485           integer_add '+' integer_mul { $$ = $1 + $3; }
0486         | integer_add '-' integer_mul { $$ = $1 - $3; }
0487         | integer_mul
0488         ;
0489 
0490 integer_mul:
0491           integer_mul '*' integer_unary { $$ = $1 * $3; }
0492         | integer_mul '/' integer_unary
0493                 {
0494                         if ($3 != 0) {
0495                                 $$ = $1 / $3;
0496                         } else {
0497                                 ERROR(&@$, "Division by zero");
0498                                 $$ = 0;
0499                         }
0500                 }
0501         | integer_mul '%' integer_unary
0502                 {
0503                         if ($3 != 0) {
0504                                 $$ = $1 % $3;
0505                         } else {
0506                                 ERROR(&@$, "Division by zero");
0507                                 $$ = 0;
0508                         }
0509                 }
0510         | integer_unary
0511         ;
0512 
0513 integer_unary:
0514           integer_prim
0515         | '-' integer_unary { $$ = -$2; }
0516         | '~' integer_unary { $$ = ~$2; }
0517         | '!' integer_unary { $$ = !$2; }
0518         ;
0519 
0520 bytestring:
0521           /* empty */
0522                 {
0523                         $$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
0524                 }
0525         | bytestring DT_BYTE
0526                 {
0527                         $$ = data_append_byte($1, $2);
0528                 }
0529         | bytestring DT_LABEL
0530                 {
0531                         $$ = data_add_marker($1, LABEL, $2);
0532                 }
0533         ;
0534 
0535 subnodes:
0536           /* empty */
0537                 {
0538                         $$ = NULL;
0539                 }
0540         | subnode subnodes
0541                 {
0542                         $$ = chain_node($1, $2);
0543                 }
0544         | subnode propdef
0545                 {
0546                         ERROR(&@2, "Properties must precede subnodes");
0547                         YYERROR;
0548                 }
0549         ;
0550 
0551 subnode:
0552           DT_PROPNODENAME nodedef
0553                 {
0554                         $$ = name_node($2, $1);
0555                 }
0556         | DT_DEL_NODE DT_PROPNODENAME ';'
0557                 {
0558                         $$ = name_node(build_node_delete(&@$), $2);
0559                 }
0560         | DT_OMIT_NO_REF subnode
0561                 {
0562                         $$ = omit_node_if_unused($2);
0563                 }
0564         | DT_LABEL subnode
0565                 {
0566                         add_label(&$2->labels, $1);
0567                         $$ = $2;
0568                 }
0569         ;
0570 
0571 %%
0572 
0573 void yyerror(char const *s)
0574 {
0575         ERROR(&yylloc, "%s", s);
0576 }