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