~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to dtc/dtc-parser.y

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

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