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