dtc-parser.y revision 238742
1204431Sraj/*
2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3204431Sraj *
4204431Sraj *
5204431Sraj * This program is free software; you can redistribute it and/or
6204431Sraj * modify it under the terms of the GNU General Public License as
7204431Sraj * published by the Free Software Foundation; either version 2 of the
8204431Sraj * License, or (at your option) any later version.
9204431Sraj *
10204431Sraj *  This program is distributed in the hope that it will be useful,
11204431Sraj *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12204431Sraj *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13204431Sraj *  General Public License for more details.
14204431Sraj *
15204431Sraj *  You should have received a copy of the GNU General Public License
16204431Sraj *  along with this program; if not, write to the Free Software
17204431Sraj *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18204431Sraj *                                                                   USA
19204431Sraj */
20204431Sraj
21204431Sraj%{
22204431Sraj#include <stdio.h>
23204431Sraj
24204431Sraj#include "dtc.h"
25204431Sraj#include "srcpos.h"
26204431Sraj
27204489SrajYYLTYPE yylloc;
28204489Sraj
29204431Srajextern int yylex(void);
30238742Simpextern void print_error(char const *fmt, ...);
31204433Srajextern void yyerror(char const *s);
32204431Sraj
33204431Srajextern struct boot_info *the_boot_info;
34204431Srajextern int treesource_error;
35204431Sraj
36204431Srajstatic unsigned long long eval_literal(const char *s, int base, int bits);
37238742Simpstatic unsigned char eval_char_literal(const char *s);
38204431Sraj%}
39204431Sraj
40204431Sraj%union {
41204431Sraj	char *propnodename;
42204431Sraj	char *literal;
43204431Sraj	char *labelref;
44204431Sraj	unsigned int cbase;
45204431Sraj	uint8_t byte;
46204431Sraj	struct data data;
47204431Sraj
48238742Simp	struct {
49238742Simp		struct data	data;
50238742Simp		int		bits;
51238742Simp	} array;
52238742Simp
53204431Sraj	struct property *prop;
54204431Sraj	struct property *proplist;
55204431Sraj	struct node *node;
56204431Sraj	struct node *nodelist;
57204431Sraj	struct reserve_info *re;
58238742Simp	uint64_t integer;
59204431Sraj}
60204431Sraj
61204431Sraj%token DT_V1
62204431Sraj%token DT_MEMRESERVE
63238742Simp%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
64238742Simp%token DT_BITS
65204431Sraj%token <propnodename> DT_PROPNODENAME
66204431Sraj%token <literal> DT_LITERAL
67238742Simp%token <literal> DT_CHAR_LITERAL
68204431Sraj%token <cbase> DT_BASE
69204431Sraj%token <byte> DT_BYTE
70204431Sraj%token <data> DT_STRING
71204431Sraj%token <labelref> DT_LABEL
72204431Sraj%token <labelref> DT_REF
73204431Sraj%token DT_INCBIN
74204431Sraj
75204431Sraj%type <data> propdata
76204431Sraj%type <data> propdataprefix
77204431Sraj%type <re> memreserve
78204431Sraj%type <re> memreserves
79238742Simp%type <array> arrayprefix
80204431Sraj%type <data> bytestring
81204431Sraj%type <prop> propdef
82204431Sraj%type <proplist> proplist
83204431Sraj
84204431Sraj%type <node> devicetree
85204431Sraj%type <node> nodedef
86204431Sraj%type <node> subnode
87204431Sraj%type <nodelist> subnodes
88204431Sraj
89238742Simp%type <integer> integer_prim
90238742Simp%type <integer> integer_unary
91238742Simp%type <integer> integer_mul
92238742Simp%type <integer> integer_add
93238742Simp%type <integer> integer_shift
94238742Simp%type <integer> integer_rela
95238742Simp%type <integer> integer_eq
96238742Simp%type <integer> integer_bitand
97238742Simp%type <integer> integer_bitxor
98238742Simp%type <integer> integer_bitor
99238742Simp%type <integer> integer_and
100238742Simp%type <integer> integer_or
101238742Simp%type <integer> integer_trinary
102238742Simp%type <integer> integer_expr
103238742Simp
104204431Sraj%%
105204431Sraj
106204431Srajsourcefile:
107204431Sraj	  DT_V1 ';' memreserves devicetree
108204431Sraj		{
109238742Simp			the_boot_info = build_boot_info($3, $4,
110238742Simp							guess_boot_cpuid($4));
111204431Sraj		}
112204431Sraj	;
113204431Sraj
114204431Srajmemreserves:
115204431Sraj	  /* empty */
116204431Sraj		{
117204431Sraj			$$ = NULL;
118204431Sraj		}
119204431Sraj	| memreserve memreserves
120204431Sraj		{
121204431Sraj			$$ = chain_reserve_entry($1, $2);
122204431Sraj		}
123204431Sraj	;
124204431Sraj
125204431Srajmemreserve:
126238742Simp	  DT_MEMRESERVE integer_prim integer_prim ';'
127204431Sraj		{
128238742Simp			$$ = build_reserve_entry($2, $3);
129204431Sraj		}
130238742Simp	| DT_LABEL memreserve
131204431Sraj		{
132238742Simp			add_label(&$2->labels, $1);
133238742Simp			$$ = $2;
134204431Sraj		}
135238742Simp	;
136204431Sraj
137204431Srajdevicetree:
138204431Sraj	  '/' nodedef
139204431Sraj		{
140238742Simp			$$ = name_node($2, "");
141204431Sraj		}
142238742Simp	| devicetree '/' nodedef
143238742Simp		{
144238742Simp			$$ = merge_nodes($1, $3);
145238742Simp		}
146238742Simp	| devicetree DT_REF nodedef
147238742Simp		{
148238742Simp			struct node *target = get_node_by_ref($1, $2);
149238742Simp
150238742Simp			if (target)
151238742Simp				merge_nodes(target, $3);
152238742Simp			else
153238742Simp				print_error("label or path, '%s', not found", $2);
154238742Simp			$$ = $1;
155238742Simp		}
156204431Sraj	;
157204431Sraj
158204431Srajnodedef:
159204431Sraj	  '{' proplist subnodes '}' ';'
160204431Sraj		{
161204431Sraj			$$ = build_node($2, $3);
162204431Sraj		}
163204431Sraj	;
164204431Sraj
165204431Srajproplist:
166204431Sraj	  /* empty */
167204431Sraj		{
168204431Sraj			$$ = NULL;
169204431Sraj		}
170204431Sraj	| proplist propdef
171204431Sraj		{
172204431Sraj			$$ = chain_property($2, $1);
173204431Sraj		}
174204431Sraj	;
175204431Sraj
176204431Srajpropdef:
177238742Simp	  DT_PROPNODENAME '=' propdata ';'
178204431Sraj		{
179238742Simp			$$ = build_property($1, $3);
180204431Sraj		}
181238742Simp	| DT_PROPNODENAME ';'
182204431Sraj		{
183238742Simp			$$ = build_property($1, empty_data);
184204431Sraj		}
185238742Simp	| DT_LABEL propdef
186238742Simp		{
187238742Simp			add_label(&$2->labels, $1);
188238742Simp			$$ = $2;
189238742Simp		}
190204431Sraj	;
191204431Sraj
192204431Srajpropdata:
193204431Sraj	  propdataprefix DT_STRING
194204431Sraj		{
195204431Sraj			$$ = data_merge($1, $2);
196204431Sraj		}
197238742Simp	| propdataprefix arrayprefix '>'
198204431Sraj		{
199238742Simp			$$ = data_merge($1, $2.data);
200204431Sraj		}
201204431Sraj	| propdataprefix '[' bytestring ']'
202204431Sraj		{
203204431Sraj			$$ = data_merge($1, $3);
204204431Sraj		}
205204431Sraj	| propdataprefix DT_REF
206204431Sraj		{
207204431Sraj			$$ = data_add_marker($1, REF_PATH, $2);
208204431Sraj		}
209238742Simp	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
210204431Sraj		{
211238742Simp			FILE *f = srcfile_relative_open($4.val, NULL);
212238742Simp			struct data d;
213204431Sraj
214204431Sraj			if ($6 != 0)
215238742Simp				if (fseek(f, $6, SEEK_SET) != 0)
216238742Simp					print_error("Couldn't seek to offset %llu in \"%s\": %s",
217204433Sraj						     (unsigned long long)$6,
218204433Sraj						     $4.val,
219204433Sraj						     strerror(errno));
220204431Sraj
221238742Simp			d = data_copy_file(f, $8);
222204431Sraj
223204431Sraj			$$ = data_merge($1, d);
224238742Simp			fclose(f);
225204431Sraj		}
226204431Sraj	| propdataprefix DT_INCBIN '(' DT_STRING ')'
227204431Sraj		{
228238742Simp			FILE *f = srcfile_relative_open($4.val, NULL);
229204431Sraj			struct data d = empty_data;
230204431Sraj
231238742Simp			d = data_copy_file(f, -1);
232204431Sraj
233204431Sraj			$$ = data_merge($1, d);
234238742Simp			fclose(f);
235204431Sraj		}
236204431Sraj	| propdata DT_LABEL
237204431Sraj		{
238204431Sraj			$$ = data_add_marker($1, LABEL, $2);
239204431Sraj		}
240204431Sraj	;
241204431Sraj
242204431Srajpropdataprefix:
243204431Sraj	  /* empty */
244204431Sraj		{
245204431Sraj			$$ = empty_data;
246204431Sraj		}
247204431Sraj	| propdata ','
248204431Sraj		{
249204431Sraj			$$ = $1;
250204431Sraj		}
251204431Sraj	| propdataprefix DT_LABEL
252204431Sraj		{
253204431Sraj			$$ = data_add_marker($1, LABEL, $2);
254204431Sraj		}
255204431Sraj	;
256204431Sraj
257238742Simparrayprefix:
258238742Simp	DT_BITS DT_LITERAL '<'
259204431Sraj		{
260238742Simp			$$.data = empty_data;
261238742Simp			$$.bits = eval_literal($2, 0, 7);
262238742Simp
263238742Simp			if (($$.bits !=  8) &&
264238742Simp			    ($$.bits != 16) &&
265238742Simp			    ($$.bits != 32) &&
266238742Simp			    ($$.bits != 64))
267238742Simp			{
268238742Simp				print_error("Only 8, 16, 32 and 64-bit elements"
269238742Simp					    " are currently supported");
270238742Simp				$$.bits = 32;
271238742Simp			}
272204431Sraj		}
273238742Simp	| '<'
274204431Sraj		{
275238742Simp			$$.data = empty_data;
276238742Simp			$$.bits = 32;
277204431Sraj		}
278238742Simp	| arrayprefix integer_prim
279204431Sraj		{
280238742Simp			if ($1.bits < 64) {
281238742Simp				uint64_t mask = (1ULL << $1.bits) - 1;
282238742Simp				/*
283238742Simp				 * Bits above mask must either be all zero
284238742Simp				 * (positive within range of mask) or all one
285238742Simp				 * (negative and sign-extended). The second
286238742Simp				 * condition is true if when we set all bits
287238742Simp				 * within the mask to one (i.e. | in the
288238742Simp				 * mask), all bits are one.
289238742Simp				 */
290238742Simp				if (($2 > mask) && (($2 | mask) != -1ULL))
291238742Simp					print_error(
292238742Simp						"integer value out of range "
293238742Simp						"%016lx (%d bits)", $1.bits);
294238742Simp			}
295238742Simp
296238742Simp			$$.data = data_append_integer($1.data, $2, $1.bits);
297204431Sraj		}
298238742Simp	| arrayprefix DT_REF
299204431Sraj		{
300238742Simp			uint64_t val = ~0ULL >> (64 - $1.bits);
301238742Simp
302238742Simp			if ($1.bits == 32)
303238742Simp				$1.data = data_add_marker($1.data,
304238742Simp							  REF_PHANDLE,
305238742Simp							  $2);
306238742Simp			else
307238742Simp				print_error("References are only allowed in "
308238742Simp					    "arrays with 32-bit elements.");
309238742Simp
310238742Simp			$$.data = data_append_integer($1.data, val, $1.bits);
311204431Sraj		}
312238742Simp	| arrayprefix DT_LABEL
313238742Simp		{
314238742Simp			$$.data = data_add_marker($1.data, LABEL, $2);
315238742Simp		}
316204431Sraj	;
317204431Sraj
318238742Simpinteger_prim:
319204431Sraj	  DT_LITERAL
320204431Sraj		{
321238742Simp			$$ = eval_literal($1, 0, 64);
322204431Sraj		}
323238742Simp	| DT_CHAR_LITERAL
324238742Simp		{
325238742Simp			$$ = eval_char_literal($1);
326238742Simp		}
327238742Simp	| '(' integer_expr ')'
328238742Simp		{
329238742Simp			$$ = $2;
330238742Simp		}
331204431Sraj	;
332204431Sraj
333238742Simpinteger_expr:
334238742Simp	integer_trinary
335238742Simp	;
336238742Simp
337238742Simpinteger_trinary:
338238742Simp	  integer_or
339238742Simp	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
340238742Simp	;
341238742Simp
342238742Simpinteger_or:
343238742Simp	  integer_and
344238742Simp	| integer_or DT_OR integer_and { $$ = $1 || $3; }
345238742Simp	;
346238742Simp
347238742Simpinteger_and:
348238742Simp	  integer_bitor
349238742Simp	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
350238742Simp	;
351238742Simp
352238742Simpinteger_bitor:
353238742Simp	  integer_bitxor
354238742Simp	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
355238742Simp	;
356238742Simp
357238742Simpinteger_bitxor:
358238742Simp	  integer_bitand
359238742Simp	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
360238742Simp	;
361238742Simp
362238742Simpinteger_bitand:
363238742Simp	  integer_eq
364238742Simp	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
365238742Simp	;
366238742Simp
367238742Simpinteger_eq:
368238742Simp	  integer_rela
369238742Simp	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
370238742Simp	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
371238742Simp	;
372238742Simp
373238742Simpinteger_rela:
374238742Simp	  integer_shift
375238742Simp	| integer_rela '<' integer_shift { $$ = $1 < $3; }
376238742Simp	| integer_rela '>' integer_shift { $$ = $1 > $3; }
377238742Simp	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
378238742Simp	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
379238742Simp	;
380238742Simp
381238742Simpinteger_shift:
382238742Simp	  integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
383238742Simp	| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
384238742Simp	| integer_add
385238742Simp	;
386238742Simp
387238742Simpinteger_add:
388238742Simp	  integer_add '+' integer_mul { $$ = $1 + $3; }
389238742Simp	| integer_add '-' integer_mul { $$ = $1 - $3; }
390238742Simp	| integer_mul
391238742Simp	;
392238742Simp
393238742Simpinteger_mul:
394238742Simp	  integer_mul '*' integer_unary { $$ = $1 * $3; }
395238742Simp	| integer_mul '/' integer_unary { $$ = $1 / $3; }
396238742Simp	| integer_mul '%' integer_unary { $$ = $1 % $3; }
397238742Simp	| integer_unary
398238742Simp	;
399238742Simp
400238742Simpinteger_unary:
401238742Simp	  integer_prim
402238742Simp	| '-' integer_unary { $$ = -$2; }
403238742Simp	| '~' integer_unary { $$ = ~$2; }
404238742Simp	| '!' integer_unary { $$ = !$2; }
405238742Simp	;
406238742Simp
407204431Srajbytestring:
408204431Sraj	  /* empty */
409204431Sraj		{
410204431Sraj			$$ = empty_data;
411204431Sraj		}
412204431Sraj	| bytestring DT_BYTE
413204431Sraj		{
414204431Sraj			$$ = data_append_byte($1, $2);
415204431Sraj		}
416204431Sraj	| bytestring DT_LABEL
417204431Sraj		{
418204431Sraj			$$ = data_add_marker($1, LABEL, $2);
419204431Sraj		}
420204431Sraj	;
421204431Sraj
422204431Srajsubnodes:
423204431Sraj	  /* empty */
424204431Sraj		{
425204431Sraj			$$ = NULL;
426204431Sraj		}
427238742Simp	| subnode subnodes
428204431Sraj		{
429204431Sraj			$$ = chain_node($1, $2);
430204431Sraj		}
431204431Sraj	| subnode propdef
432204431Sraj		{
433238742Simp			print_error("syntax error: properties must precede subnodes");
434204431Sraj			YYERROR;
435204431Sraj		}
436204431Sraj	;
437204431Sraj
438204431Srajsubnode:
439238742Simp	  DT_PROPNODENAME nodedef
440204431Sraj		{
441238742Simp			$$ = name_node($2, $1);
442204431Sraj		}
443238742Simp	| DT_LABEL subnode
444204431Sraj		{
445238742Simp			add_label(&$2->labels, $1);
446238742Simp			$$ = $2;
447204431Sraj		}
448204431Sraj	;
449204431Sraj
450204431Sraj%%
451204431Sraj
452238742Simpvoid print_error(char const *fmt, ...)
453204431Sraj{
454238742Simp	va_list va;
455238742Simp
456238742Simp	va_start(va, fmt);
457238742Simp	srcpos_verror(&yylloc, fmt, va);
458238742Simp	va_end(va);
459238742Simp
460204431Sraj	treesource_error = 1;
461204431Sraj}
462204431Sraj
463238742Simpvoid yyerror(char const *s) {
464238742Simp	print_error("%s", s);
465238742Simp}
466238742Simp
467204431Srajstatic unsigned long long eval_literal(const char *s, int base, int bits)
468204431Sraj{
469204431Sraj	unsigned long long val;
470204431Sraj	char *e;
471204431Sraj
472204431Sraj	errno = 0;
473204431Sraj	val = strtoull(s, &e, base);
474238742Simp	if (*e) {
475238742Simp		size_t uls = strspn(e, "UL");
476238742Simp		if (e[uls])
477238742Simp			print_error("bad characters in literal");
478238742Simp	}
479238742Simp	if ((errno == ERANGE)
480204431Sraj		 || ((bits < 64) && (val >= (1ULL << bits))))
481238742Simp		print_error("literal out of range");
482204431Sraj	else if (errno != 0)
483238742Simp		print_error("bad literal");
484204431Sraj	return val;
485204431Sraj}
486238742Simp
487238742Simpstatic unsigned char eval_char_literal(const char *s)
488238742Simp{
489238742Simp	int i = 1;
490238742Simp	char c = s[0];
491238742Simp
492238742Simp	if (c == '\0')
493238742Simp	{
494238742Simp		print_error("empty character literal");
495238742Simp		return 0;
496238742Simp	}
497238742Simp
498238742Simp	/*
499238742Simp	 * If the first character in the character literal is a \ then process
500238742Simp	 * the remaining characters as an escape encoding. If the first
501238742Simp	 * character is neither an escape or a terminator it should be the only
502238742Simp	 * character in the literal and will be returned.
503238742Simp	 */
504238742Simp	if (c == '\\')
505238742Simp		c = get_escape_char(s, &i);
506238742Simp
507238742Simp	if (s[i] != '\0')
508238742Simp		print_error("malformed character literal");
509238742Simp
510238742Simp	return c;
511238742Simp}
512