Merge branch 'ieee802154-for-davem-2019-08-24' of git://git.kernel.org/pub/scm/linux...
[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 %{
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 }