blob: b4acf7f43c084a3a7af56daccd999aa58de90a4c [file] [log] [blame]
Rob Herringacfe84f2019-06-20 15:19:38 -06001// SPDX-License-Identifier: GPL-2.0-or-later
David Gibsonfc14dad2005-06-08 17:18:34 +10002/*
3 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
David Gibsonfc14dad2005-06-08 17:18:34 +10004 */
Ethan Sommer71502862019-10-29 12:26:19 -04005%locations
6
David Gibsonfc14dad2005-06-08 17:18:34 +10007%{
David Gibsone37ec7d2008-06-11 11:58:39 +10008#include <stdio.h>
Pantelis Antoniou20f29d82016-12-07 14:48:18 +02009#include <inttypes.h>
David Gibsone37ec7d2008-06-11 11:58:39 +100010
David Gibsonfc14dad2005-06-08 17:18:34 +100011#include "dtc.h"
Jon Loeligere45e6fd2007-03-23 15:18:41 -050012#include "srcpos.h"
David Gibsonfc14dad2005-06-08 17:18:34 +100013
David Gibson6b8e0562008-03-05 11:47:54 +110014extern int yylex(void);
Jon Loeligere5c8e1d2008-09-12 13:39:49 -050015extern void yyerror(char const *s);
David Gibsonfa3f3f02014-01-03 23:57:39 +110016#define ERROR(loc, ...) \
17 do { \
18 srcpos_error((loc), "Error", __VA_ARGS__); \
19 treesource_error = true; \
20 } while (0)
David Gibsonfc14dad2005-06-08 17:18:34 +100021
Ethan Sommer71502862019-10-29 12:26:19 -040022#define YYERROR_CALL(msg) yyerror(msg)
23
David Gibson00fbb862016-05-31 11:58:42 +100024extern struct dt_info *parser_output;
David Gibson17625372013-10-28 21:06:53 +110025extern bool treesource_error;
Pierre-Clément Tosief1978a2022-05-30 20:57:34 +010026
27static bool is_ref_relative(const char *ref)
28{
29 return ref[0] != '/' && strchr(&ref[1], '/');
30}
31
David Gibsonfc14dad2005-06-08 17:18:34 +100032%}
33
34%union {
David Gibson9ed27a22007-11-07 11:16:19 +110035 char *propnodename;
David Gibson9ed27a22007-11-07 11:16:19 +110036 char *labelref;
David Gibson53359012008-06-25 13:53:07 +100037 uint8_t byte;
David Gibsonfc14dad2005-06-08 17:18:34 +100038 struct data data;
David Gibson9ed27a22007-11-07 11:16:19 +110039
Anton Staaf033089f2011-10-11 10:22:29 -070040 struct {
41 struct data data;
42 int bits;
43 } array;
44
David Gibsonfc14dad2005-06-08 17:18:34 +100045 struct property *prop;
46 struct property *proplist;
47 struct node *node;
48 struct node *nodelist;
David Gibsonf040d952005-10-24 18:18:38 +100049 struct reserve_info *re;
Stephen Warren5f0c3b22012-04-03 20:56:00 -060050 uint64_t integer;
Pantelis Antoniou20f29d82016-12-07 14:48:18 +020051 unsigned int flags;
David Gibsonfc14dad2005-06-08 17:18:34 +100052}
53
David Gibson9138db52007-11-07 11:17:17 +110054%token DT_V1
Pantelis Antoniou20f29d82016-12-07 14:48:18 +020055%token DT_PLUGIN
David Gibsonf0517db2005-07-15 17:14:24 +100056%token DT_MEMRESERVE
Stephen Warren5f0c3b22012-04-03 20:56:00 -060057%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
Anton Staaf033089f2011-10-11 10:22:29 -070058%token DT_BITS
Stephen Warren45013d82012-08-07 22:50:15 -060059%token DT_DEL_PROP
60%token DT_DEL_NODE
Maxime Ripard4038fd92018-05-03 22:27:26 +020061%token DT_OMIT_NO_REF
David Gibson9ed27a22007-11-07 11:16:19 +110062%token <propnodename> DT_PROPNODENAME
David Gibsonb82b9772014-01-03 20:00:01 +110063%token <integer> DT_LITERAL
David Gibsoncfc65232014-01-04 10:03:55 +110064%token <integer> DT_CHAR_LITERAL
David Gibsonfc14dad2005-06-08 17:18:34 +100065%token <byte> DT_BYTE
66%token <data> DT_STRING
David Gibson9ed27a22007-11-07 11:16:19 +110067%token <labelref> DT_LABEL
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +020068%token <labelref> DT_LABEL_REF
69%token <labelref> DT_PATH_REF
David Gibsone37ec7d2008-06-11 11:58:39 +100070%token DT_INCBIN
David Gibsonfc14dad2005-06-08 17:18:34 +100071
72%type <data> propdata
David Gibson32da4752007-02-07 16:37:50 +110073%type <data> propdataprefix
David Gibson1ef86ad2016-12-09 16:23:23 +110074%type <flags> header
75%type <flags> headers
David Gibsonf0517db2005-07-15 17:14:24 +100076%type <re> memreserve
David Gibsonf040d952005-10-24 18:18:38 +100077%type <re> memreserves
Anton Staaf033089f2011-10-11 10:22:29 -070078%type <array> arrayprefix
David Gibsonfc14dad2005-06-08 17:18:34 +100079%type <data> bytestring
80%type <prop> propdef
81%type <proplist> proplist
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +020082%type <labelref> dt_ref
David Gibsonfc14dad2005-06-08 17:18:34 +100083
David Gibsonf0517db2005-07-15 17:14:24 +100084%type <node> devicetree
David Gibsonfc14dad2005-06-08 17:18:34 +100085%type <node> nodedef
86%type <node> subnode
87%type <nodelist> subnodes
David Gibson4102d842005-06-16 14:36:37 +100088
Stephen Warren5f0c3b22012-04-03 20:56:00 -060089%type <integer> integer_prim
90%type <integer> integer_unary
91%type <integer> integer_mul
92%type <integer> integer_add
93%type <integer> integer_shift
94%type <integer> integer_rela
95%type <integer> integer_eq
96%type <integer> integer_bitand
97%type <integer> integer_bitxor
98%type <integer> integer_bitor
99%type <integer> integer_and
100%type <integer> integer_or
101%type <integer> integer_trinary
102%type <integer> integer_expr
103
David Gibsonfc14dad2005-06-08 17:18:34 +1000104%%
105
Jon Loeliger30807ca2007-10-18 09:42:16 -0500106sourcefile:
David Gibson1ef86ad2016-12-09 16:23:23 +1100107 headers memreserves devicetree
David Gibson9138db52007-11-07 11:17:17 +1100108 {
David Gibson00fbb862016-05-31 11:58:42 +1000109 parser_output = build_dt_info($1, $2, $3,
110 guess_boot_cpuid($3));
Pantelis Antoniou20f29d82016-12-07 14:48:18 +0200111 }
112 ;
113
David Gibson1ef86ad2016-12-09 16:23:23 +1100114header:
115 DT_V1 ';'
Pantelis Antoniou20f29d82016-12-07 14:48:18 +0200116 {
117 $$ = DTSF_V1;
David Gibson9138db52007-11-07 11:17:17 +1100118 }
David Gibson1ef86ad2016-12-09 16:23:23 +1100119 | DT_V1 ';' DT_PLUGIN ';'
120 {
121 $$ = DTSF_V1 | DTSF_PLUGIN;
122 }
David Gibsonf0517db2005-07-15 17:14:24 +1000123 ;
124
David Gibson1ef86ad2016-12-09 16:23:23 +1100125headers:
126 header
127 | header headers
Pantelis Antoniou20f29d82016-12-07 14:48:18 +0200128 {
David Gibson1ef86ad2016-12-09 16:23:23 +1100129 if ($2 != $1)
130 ERROR(&@2, "Header flags don't match earlier ones");
131 $$ = $1;
Pantelis Antoniou20f29d82016-12-07 14:48:18 +0200132 }
David Gibsonc4cb12e2014-06-02 15:23:40 +1000133 ;
134
Jon Loeliger30807ca2007-10-18 09:42:16 -0500135memreserves:
Jon Loeliger56412892007-10-23 09:28:54 -0500136 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500137 {
David Gibsonf040d952005-10-24 18:18:38 +1000138 $$ = NULL;
David Gibsonf0517db2005-07-15 17:14:24 +1000139 }
Jon Loeliger56412892007-10-23 09:28:54 -0500140 | memreserve memreserves
141 {
142 $$ = chain_reserve_entry($1, $2);
143 }
David Gibsonf0517db2005-07-15 17:14:24 +1000144 ;
145
Jon Loeliger30807ca2007-10-18 09:42:16 -0500146memreserve:
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600147 DT_MEMRESERVE integer_prim integer_prim ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500148 {
David Gibson05898c62010-02-24 18:22:17 +1100149 $$ = build_reserve_entry($2, $3);
150 }
151 | DT_LABEL memreserve
152 {
153 add_label(&$2->labels, $1);
154 $$ = $2;
David Gibsonf0517db2005-07-15 17:14:24 +1000155 }
David Gibson9138db52007-11-07 11:17:17 +1100156 ;
157
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200158dt_ref: DT_LABEL_REF | DT_PATH_REF;
159
Jon Loeliger30807ca2007-10-18 09:42:16 -0500160devicetree:
161 '/' nodedef
162 {
David Gibson05898c62010-02-24 18:22:17 +1100163 $$ = name_node($2, "");
David Gibsonf0517db2005-07-15 17:14:24 +1000164 }
David Gibson8773e122010-09-20 16:33:34 -0600165 | devicetree '/' nodedef
166 {
167 $$ = merge_nodes($1, $3);
168 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200169 | dt_ref nodedef
Grant Likelyb260c4f2017-11-20 17:12:18 +0000170 {
171 /*
172 * We rely on the rule being always:
173 * versioninfo plugindecl memreserves devicetree
174 * so $-1 is what we want (plugindecl)
175 */
176 if (!($<flags>-1 & DTSF_PLUGIN))
177 ERROR(&@2, "Label or path %s not found", $1);
Pierre-Clément Tosief1978a2022-05-30 20:57:34 +0100178 else if (is_ref_relative($1))
179 ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
Julia Lawall8e20ccf2018-11-16 17:29:59 +0100180 $$ = add_orphan_node(
181 name_node(build_node(NULL, NULL, NULL),
182 ""),
183 $2, $1);
Grant Likelyb260c4f2017-11-20 17:12:18 +0000184 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200185 | devicetree DT_LABEL dt_ref nodedef
Nikhil Devshatwar3346e062015-02-23 12:29:19 +1100186 {
187 struct node *target = get_node_by_ref($1, $3);
188
Pierre-Clément Tosief1978a2022-05-30 20:57:34 +0100189 if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
190 ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
191
Stephen Boyd3b9c9702017-01-30 14:06:17 -0800192 if (target) {
193 add_label(&target->labels, $2);
Nikhil Devshatwar3346e062015-02-23 12:29:19 +1100194 merge_nodes(target, $4);
Stephen Boyd3b9c9702017-01-30 14:06:17 -0800195 } else
Nikhil Devshatwar3346e062015-02-23 12:29:19 +1100196 ERROR(&@3, "Label or path %s not found", $3);
197 $$ = $1;
198 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200199 | devicetree DT_PATH_REF nodedef
David Gibson8773e122010-09-20 16:33:34 -0600200 {
David Gibson8f1b35f2018-03-06 13:27:53 +1100201 /*
202 * We rely on the rule being always:
203 * versioninfo plugindecl memreserves devicetree
204 * so $-1 is what we want (plugindecl)
205 */
206 if ($<flags>-1 & DTSF_PLUGIN) {
Pierre-Clément Tosief1978a2022-05-30 20:57:34 +0100207 if (is_ref_relative($2))
208 ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
David Gibson8f1b35f2018-03-06 13:27:53 +1100209 add_orphan_node($1, $3, $2);
Pantelis Antoniou737b2df2017-06-14 17:53:05 +0300210 } else {
David Gibson8f1b35f2018-03-06 13:27:53 +1100211 struct node *target = get_node_by_ref($1, $2);
212
213 if (target)
214 merge_nodes(target, $3);
Pantelis Antoniou737b2df2017-06-14 17:53:05 +0300215 else
216 ERROR(&@2, "Label or path %s not found", $2);
217 }
David Gibson8773e122010-09-20 16:33:34 -0600218 $$ = $1;
219 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200220 | devicetree DT_LABEL_REF nodedef
David Gibsonfc14dad2005-06-08 17:18:34 +1000221 {
222 struct node *target = get_node_by_ref($1, $2);
223
Pantelis Antoniouec291732016-12-07 12:48:22 +0800224 if (target) {
David Gibsonfc14dad2005-06-08 17:18:34 +1000225 merge_nodes(target, $3);
Pantelis Antoniouec291732016-12-07 12:48:22 +0800226 } else {
227 /*
228 * We rely on the rule being always:
229 * versioninfo plugindecl memreserves devicetree
230 * so $-1 is what we want (plugindecl)
231 */
232 if ($<flags>-1 & DTSF_PLUGIN)
233 add_orphan_node($1, $3, $2);
234 else
235 ERROR(&@2, "Label or path %s not found", $2);
236 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000237 $$ = $1;
238 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200239 | devicetree DT_DEL_NODE dt_ref ';'
Stephen Warren45013d82012-08-07 22:50:15 -0600240 {
241 struct node *target = get_node_by_ref($1, $3);
242
David Gibsonfa3f3f02014-01-03 23:57:39 +1100243 if (target)
Stephen Warren45013d82012-08-07 22:50:15 -0600244 delete_node(target);
David Gibsonfa3f3f02014-01-03 23:57:39 +1100245 else
246 ERROR(&@3, "Label or path %s not found", $3);
247
Stephen Warren45013d82012-08-07 22:50:15 -0600248
249 $$ = $1;
250 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200251 | devicetree DT_OMIT_NO_REF dt_ref ';'
Maxime Ripard4038fd92018-05-03 22:27:26 +0200252 {
253 struct node *target = get_node_by_ref($1, $3);
254
255 if (target)
256 omit_node_if_unused(target);
257 else
258 ERROR(&@3, "Label or path %s not found", $3);
259
260
261 $$ = $1;
262 }
Pantelis Antoniouec291732016-12-07 12:48:22 +0800263 | /* empty */
264 {
265 /* build empty node */
Steve Muckleb734cfd2020-07-08 17:22:37 -0700266 $$ = name_node(build_node(NULL, NULL, NULL), "");
Pantelis Antoniouec291732016-12-07 12:48:22 +0800267 }
David Gibson81f2e892005-06-16 17:04:00 +1000268 ;
269
270nodedef:
David Gibsonfc14dad2005-06-08 17:18:34 +1000271 '{' proplist subnodes '}' ';'
272 {
Julia Lawall8e20ccf2018-11-16 17:29:59 +0100273 $$ = build_node($2, $3, &@$);
David Gibsonfc14dad2005-06-08 17:18:34 +1000274 }
275 ;
276
Jon Loeliger30807ca2007-10-18 09:42:16 -0500277proplist:
Jon Loeliger56412892007-10-23 09:28:54 -0500278 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500279 {
David Gibsonfc14dad2005-06-08 17:18:34 +1000280 $$ = NULL;
281 }
Jon Loeliger7b3fb782007-10-22 16:09:56 -0500282 | proplist propdef
Jon Loeliger56412892007-10-23 09:28:54 -0500283 {
Jon Loeliger7b3fb782007-10-22 16:09:56 -0500284 $$ = chain_property($2, $1);
Jon Loeliger56412892007-10-23 09:28:54 -0500285 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000286 ;
287
Jon Loeliger30807ca2007-10-18 09:42:16 -0500288propdef:
David Gibson05898c62010-02-24 18:22:17 +1100289 DT_PROPNODENAME '=' propdata ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500290 {
Julia Lawall8e20ccf2018-11-16 17:29:59 +0100291 $$ = build_property($1, $3, &@$);
David Gibsonfc14dad2005-06-08 17:18:34 +1000292 }
David Gibson05898c62010-02-24 18:22:17 +1100293 | DT_PROPNODENAME ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500294 {
Julia Lawall8e20ccf2018-11-16 17:29:59 +0100295 $$ = build_property($1, empty_data, &@$);
David Gibson05898c62010-02-24 18:22:17 +1100296 }
Stephen Warren45013d82012-08-07 22:50:15 -0600297 | DT_DEL_PROP DT_PROPNODENAME ';'
298 {
299 $$ = build_property_delete($2);
300 }
David Gibson05898c62010-02-24 18:22:17 +1100301 | DT_LABEL propdef
302 {
303 add_label(&$2->labels, $1);
304 $$ = $2;
David Gibsonfc14dad2005-06-08 17:18:34 +1000305 }
306 ;
307
Jon Loeliger30807ca2007-10-18 09:42:16 -0500308propdata:
309 propdataprefix DT_STRING
310 {
311 $$ = data_merge($1, $2);
David Gibson32da4752007-02-07 16:37:50 +1100312 }
Anton Staaf033089f2011-10-11 10:22:29 -0700313 | propdataprefix arrayprefix '>'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500314 {
Anton Staaf033089f2011-10-11 10:22:29 -0700315 $$ = data_merge($1, $2.data);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500316 }
317 | propdataprefix '[' bytestring ']'
318 {
319 $$ = data_merge($1, $3);
320 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200321 | propdataprefix dt_ref
David Gibsonefbbef82007-12-05 10:43:50 +1100322 {
Rob Herringac68ff92018-07-30 21:57:35 -0600323 $1 = data_add_marker($1, TYPE_STRING, $2);
David Gibsonefbbef82007-12-05 10:43:50 +1100324 $$ = data_add_marker($1, REF_PATH, $2);
325 }
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600326 | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
David Gibsone37ec7d2008-06-11 11:58:39 +1000327 {
David Gibsond68cb362009-12-08 14:24:42 +1100328 FILE *f = srcfile_relative_open($4.val, NULL);
329 struct data d;
David Gibsone37ec7d2008-06-11 11:58:39 +1000330
331 if ($6 != 0)
David Gibsond68cb362009-12-08 14:24:42 +1100332 if (fseek(f, $6, SEEK_SET) != 0)
David Gibson6a15eb22014-01-04 10:04:19 +1100333 die("Couldn't seek to offset %llu in \"%s\": %s",
334 (unsigned long long)$6, $4.val,
335 strerror(errno));
David Gibsone37ec7d2008-06-11 11:58:39 +1000336
David Gibsond68cb362009-12-08 14:24:42 +1100337 d = data_copy_file(f, $8);
David Gibsone37ec7d2008-06-11 11:58:39 +1000338
339 $$ = data_merge($1, d);
David Gibsond68cb362009-12-08 14:24:42 +1100340 fclose(f);
David Gibsone37ec7d2008-06-11 11:58:39 +1000341 }
342 | propdataprefix DT_INCBIN '(' DT_STRING ')'
343 {
David Gibsond68cb362009-12-08 14:24:42 +1100344 FILE *f = srcfile_relative_open($4.val, NULL);
David Gibsone37ec7d2008-06-11 11:58:39 +1000345 struct data d = empty_data;
346
David Gibsond68cb362009-12-08 14:24:42 +1100347 d = data_copy_file(f, -1);
David Gibsone37ec7d2008-06-11 11:58:39 +1000348
349 $$ = data_merge($1, d);
David Gibsond68cb362009-12-08 14:24:42 +1100350 fclose(f);
David Gibsone37ec7d2008-06-11 11:58:39 +1000351 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500352 | propdata DT_LABEL
353 {
David Gibsondc941772007-11-22 14:39:23 +1100354 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500355 }
David Gibson32da4752007-02-07 16:37:50 +1100356 ;
357
Jon Loeliger30807ca2007-10-18 09:42:16 -0500358propdataprefix:
Jon Loeliger56412892007-10-23 09:28:54 -0500359 /* empty */
360 {
361 $$ = empty_data;
362 }
363 | propdata ','
Jon Loeliger30807ca2007-10-18 09:42:16 -0500364 {
365 $$ = $1;
366 }
367 | propdataprefix DT_LABEL
368 {
David Gibsondc941772007-11-22 14:39:23 +1100369 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500370 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000371 ;
372
Anton Staaf033089f2011-10-11 10:22:29 -0700373arrayprefix:
374 DT_BITS DT_LITERAL '<'
Jon Loeliger56412892007-10-23 09:28:54 -0500375 {
David Gibsonb82b9772014-01-03 20:00:01 +1100376 unsigned long long bits;
Grant Likely44d3efe2018-05-15 17:42:54 -0500377 enum markertype type = TYPE_UINT32;
David Gibsonfc14dad2005-06-08 17:18:34 +1000378
David Gibsonb82b9772014-01-03 20:00:01 +1100379 bits = $2;
380
Grant Likely44d3efe2018-05-15 17:42:54 -0500381 switch (bits) {
382 case 8: type = TYPE_UINT8; break;
383 case 16: type = TYPE_UINT16; break;
384 case 32: type = TYPE_UINT32; break;
385 case 64: type = TYPE_UINT64; break;
386 default:
David Gibsonfa3f3f02014-01-03 23:57:39 +1100387 ERROR(&@2, "Array elements must be"
388 " 8, 16, 32 or 64-bits");
David Gibsonb82b9772014-01-03 20:00:01 +1100389 bits = 32;
Anton Staaf033089f2011-10-11 10:22:29 -0700390 }
David Gibsonb82b9772014-01-03 20:00:01 +1100391
Grant Likely44d3efe2018-05-15 17:42:54 -0500392 $$.data = data_add_marker(empty_data, type, NULL);
David Gibsonb82b9772014-01-03 20:00:01 +1100393 $$.bits = bits;
David Gibson9138db52007-11-07 11:17:17 +1100394 }
Anton Staaf033089f2011-10-11 10:22:29 -0700395 | '<'
Anton Staafa4ea2fa2011-09-09 12:16:30 -0700396 {
Grant Likely44d3efe2018-05-15 17:42:54 -0500397 $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
Anton Staaf033089f2011-10-11 10:22:29 -0700398 $$.bits = 32;
399 }
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600400 | arrayprefix integer_prim
Anton Staaf033089f2011-10-11 10:22:29 -0700401 {
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600402 if ($1.bits < 64) {
403 uint64_t mask = (1ULL << $1.bits) - 1;
404 /*
405 * Bits above mask must either be all zero
406 * (positive within range of mask) or all one
407 * (negative and sign-extended). The second
408 * condition is true if when we set all bits
409 * within the mask to one (i.e. | in the
410 * mask), all bits are one.
411 */
412 if (($2 > mask) && (($2 | mask) != -1ULL))
David Gibsonfa3f3f02014-01-03 23:57:39 +1100413 ERROR(&@2, "Value out of range for"
414 " %d-bit array element", $1.bits);
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600415 }
Anton Staaf033089f2011-10-11 10:22:29 -0700416
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600417 $$.data = data_append_integer($1.data, $2, $1.bits);
Anton Staaf033089f2011-10-11 10:22:29 -0700418 }
Fredrik Markstrom0fcffda2018-09-24 13:27:27 +0200419 | arrayprefix dt_ref
Anton Staaf033089f2011-10-11 10:22:29 -0700420 {
421 uint64_t val = ~0ULL >> (64 - $1.bits);
422
423 if ($1.bits == 32)
424 $1.data = data_add_marker($1.data,
425 REF_PHANDLE,
426 $2);
427 else
David Gibsonfa3f3f02014-01-03 23:57:39 +1100428 ERROR(&@2, "References are only allowed in "
Anton Staaf033089f2011-10-11 10:22:29 -0700429 "arrays with 32-bit elements.");
430
431 $$.data = data_append_integer($1.data, val, $1.bits);
432 }
433 | arrayprefix DT_LABEL
434 {
435 $$.data = data_add_marker($1.data, LABEL, $2);
Anton Staafa4ea2fa2011-09-09 12:16:30 -0700436 }
David Gibson9ed27a22007-11-07 11:16:19 +1100437 ;
438
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600439integer_prim:
440 DT_LITERAL
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600441 | DT_CHAR_LITERAL
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600442 | '(' integer_expr ')'
443 {
444 $$ = $2;
445 }
446 ;
447
448integer_expr:
449 integer_trinary
450 ;
451
452integer_trinary:
453 integer_or
454 | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
455 ;
456
457integer_or:
458 integer_and
459 | integer_or DT_OR integer_and { $$ = $1 || $3; }
460 ;
461
462integer_and:
463 integer_bitor
464 | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
465 ;
466
467integer_bitor:
468 integer_bitxor
469 | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
470 ;
471
472integer_bitxor:
473 integer_bitand
474 | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
475 ;
476
477integer_bitand:
478 integer_eq
479 | integer_bitand '&' integer_eq { $$ = $1 & $3; }
480 ;
481
482integer_eq:
483 integer_rela
484 | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
485 | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
486 ;
487
488integer_rela:
489 integer_shift
490 | integer_rela '<' integer_shift { $$ = $1 < $3; }
491 | integer_rela '>' integer_shift { $$ = $1 > $3; }
492 | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
493 | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
494 ;
495
496integer_shift:
Pierre-Clément Tosief1978a2022-05-30 20:57:34 +0100497 integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
498 | integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600499 | integer_add
500 ;
501
502integer_add:
503 integer_add '+' integer_mul { $$ = $1 + $3; }
504 | integer_add '-' integer_mul { $$ = $1 - $3; }
505 | integer_mul
506 ;
507
508integer_mul:
509 integer_mul '*' integer_unary { $$ = $1 * $3; }
David Gibson19370952016-01-03 22:27:32 +1100510 | integer_mul '/' integer_unary
511 {
512 if ($3 != 0) {
513 $$ = $1 / $3;
514 } else {
515 ERROR(&@$, "Division by zero");
516 $$ = 0;
517 }
518 }
David Gibsonb06e55c2016-01-12 19:27:25 +1100519 | integer_mul '%' integer_unary
520 {
521 if ($3 != 0) {
522 $$ = $1 % $3;
523 } else {
524 ERROR(&@$, "Division by zero");
525 $$ = 0;
526 }
527 }
Stephen Warren5f0c3b22012-04-03 20:56:00 -0600528 | integer_unary
529 ;
530
531integer_unary:
532 integer_prim
533 | '-' integer_unary { $$ = -$2; }
534 | '~' integer_unary { $$ = ~$2; }
535 | '!' integer_unary { $$ = !$2; }
536 ;
537
Jon Loeliger30807ca2007-10-18 09:42:16 -0500538bytestring:
Jon Loeliger56412892007-10-23 09:28:54 -0500539 /* empty */
540 {
Grant Likely44d3efe2018-05-15 17:42:54 -0500541 $$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
Jon Loeliger56412892007-10-23 09:28:54 -0500542 }
543 | bytestring DT_BYTE
Jon Loeliger30807ca2007-10-18 09:42:16 -0500544 {
545 $$ = data_append_byte($1, $2);
546 }
547 | bytestring DT_LABEL
548 {
David Gibsondc941772007-11-22 14:39:23 +1100549 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500550 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000551 ;
552
Jon Loeliger30807ca2007-10-18 09:42:16 -0500553subnodes:
Jon Loeliger56412892007-10-23 09:28:54 -0500554 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500555 {
556 $$ = NULL;
557 }
David Gibson05898c62010-02-24 18:22:17 +1100558 | subnode subnodes
Jon Loeliger56412892007-10-23 09:28:54 -0500559 {
560 $$ = chain_node($1, $2);
561 }
David Gibsonc0481022007-12-05 10:27:04 +1100562 | subnode propdef
563 {
David Gibsonfa3f3f02014-01-03 23:57:39 +1100564 ERROR(&@2, "Properties must precede subnodes");
David Gibsonc0481022007-12-05 10:27:04 +1100565 YYERROR;
566 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000567 ;
568
Jon Loeliger30807ca2007-10-18 09:42:16 -0500569subnode:
David Gibson05898c62010-02-24 18:22:17 +1100570 DT_PROPNODENAME nodedef
Jon Loeliger30807ca2007-10-18 09:42:16 -0500571 {
David Gibson05898c62010-02-24 18:22:17 +1100572 $$ = name_node($2, $1);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500573 }
Stephen Warren45013d82012-08-07 22:50:15 -0600574 | DT_DEL_NODE DT_PROPNODENAME ';'
575 {
Julia Lawall8e20ccf2018-11-16 17:29:59 +0100576 $$ = name_node(build_node_delete(&@$), $2);
Stephen Warren45013d82012-08-07 22:50:15 -0600577 }
Maxime Ripard4038fd92018-05-03 22:27:26 +0200578 | DT_OMIT_NO_REF subnode
579 {
580 $$ = omit_node_if_unused($2);
John Bonesioc0fa2e62010-10-20 14:44:58 -0700581 }
582 | DT_LABEL subnode
583 {
584 add_label(&$2->labels, $1);
David Gibson6b8e0562008-03-05 11:47:54 +1100585 $$ = $2;
Jon Loeliger39488492007-02-16 09:33:54 -0600586 }
David Gibson9ed27a22007-11-07 11:16:19 +1100587 ;
Milton Miller85ab5cc2007-07-07 01:18:48 -0500588
Jon Loeliger39488492007-02-16 09:33:54 -0600589%%
David Gibson9ed27a22007-11-07 11:16:19 +1100590
David Gibsonc8544342014-01-03 23:23:23 +1100591void yyerror(char const *s)
592{
David Gibsonfa3f3f02014-01-03 23:57:39 +1100593 ERROR(&yylloc, "%s", s);
Jon Loeliger39488492007-02-16 09:33:54 -0600594}