dtc-parser.y revision 204489
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
22%{
23#include <stdio.h>
24
25#include "dtc.h"
26#include "srcpos.h"
27
28YYLTYPE yylloc;
29
30extern int yylex(void);
31extern void yyerror(char const *s);
32
33extern struct boot_info *the_boot_info;
34extern int treesource_error;
35
36static unsigned long long eval_literal(const char *s, int base, int bits);
37%}
38
39%union {
40	char *propnodename;
41	char *literal;
42	char *labelref;
43	unsigned int cbase;
44	uint8_t byte;
45	struct data data;
46
47	uint64_t addr;
48	cell_t cell;
49	struct property *prop;
50	struct property *proplist;
51	struct node *node;
52	struct node *nodelist;
53	struct reserve_info *re;
54}
55
56%token DT_V1
57%token DT_MEMRESERVE
58%token <propnodename> DT_PROPNODENAME
59%token <literal> DT_LITERAL
60%token <cbase> DT_BASE
61%token <byte> DT_BYTE
62%token <data> DT_STRING
63%token <labelref> DT_LABEL
64%token <labelref> DT_REF
65%token DT_INCBIN
66
67%type <data> propdata
68%type <data> propdataprefix
69%type <re> memreserve
70%type <re> memreserves
71%type <addr> addr
72%type <data> celllist
73%type <cell> cellval
74%type <data> bytestring
75%type <prop> propdef
76%type <proplist> proplist
77
78%type <node> devicetree
79%type <node> nodedef
80%type <node> subnode
81%type <nodelist> subnodes
82%type <labelref> label
83
84%%
85
86sourcefile:
87	  DT_V1 ';' memreserves devicetree
88		{
89			the_boot_info = build_boot_info($3, $4, 0);
90		}
91	;
92
93memreserves:
94	  /* empty */
95		{
96			$$ = NULL;
97		}
98	| memreserve memreserves
99		{
100			$$ = chain_reserve_entry($1, $2);
101		}
102	;
103
104memreserve:
105	  label DT_MEMRESERVE addr addr ';'
106		{
107			$$ = build_reserve_entry($3, $4, $1);
108		}
109	;
110
111addr:
112	  DT_LITERAL
113		{
114			$$ = eval_literal($1, 0, 64);
115		}
116	  ;
117
118devicetree:
119	  '/' nodedef
120		{
121			$$ = name_node($2, "", NULL);
122		}
123	;
124
125nodedef:
126	  '{' proplist subnodes '}' ';'
127		{
128			$$ = build_node($2, $3);
129		}
130	;
131
132proplist:
133	  /* empty */
134		{
135			$$ = NULL;
136		}
137	| proplist propdef
138		{
139			$$ = chain_property($2, $1);
140		}
141	;
142
143propdef:
144	  label DT_PROPNODENAME '=' propdata ';'
145		{
146			$$ = build_property($2, $4, $1);
147		}
148	| label DT_PROPNODENAME ';'
149		{
150			$$ = build_property($2, empty_data, $1);
151		}
152	;
153
154propdata:
155	  propdataprefix DT_STRING
156		{
157			$$ = data_merge($1, $2);
158		}
159	| propdataprefix '<' celllist '>'
160		{
161			$$ = data_merge($1, $3);
162		}
163	| propdataprefix '[' bytestring ']'
164		{
165			$$ = data_merge($1, $3);
166		}
167	| propdataprefix DT_REF
168		{
169			$$ = data_add_marker($1, REF_PATH, $2);
170		}
171	| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
172		{
173			struct search_path path = { srcpos_file->dir, NULL, NULL };
174			struct dtc_file *file = dtc_open_file($4.val, &path);
175			struct data d = empty_data;
176
177			if ($6 != 0)
178				if (fseek(file->file, $6, SEEK_SET) != 0)
179					srcpos_error(&yylloc,
180						     "Couldn't seek to offset %llu in \"%s\": %s",
181						     (unsigned long long)$6,
182						     $4.val,
183						     strerror(errno));
184
185			d = data_copy_file(file->file, $8);
186
187			$$ = data_merge($1, d);
188			dtc_close_file(file);
189		}
190	| propdataprefix DT_INCBIN '(' DT_STRING ')'
191		{
192			struct search_path path = { srcpos_file->dir, NULL, NULL };
193			struct dtc_file *file = dtc_open_file($4.val, &path);
194			struct data d = empty_data;
195
196			d = data_copy_file(file->file, -1);
197
198			$$ = data_merge($1, d);
199			dtc_close_file(file);
200		}
201	| propdata DT_LABEL
202		{
203			$$ = data_add_marker($1, LABEL, $2);
204		}
205	;
206
207propdataprefix:
208	  /* empty */
209		{
210			$$ = empty_data;
211		}
212	| propdata ','
213		{
214			$$ = $1;
215		}
216	| propdataprefix DT_LABEL
217		{
218			$$ = data_add_marker($1, LABEL, $2);
219		}
220	;
221
222celllist:
223	  /* empty */
224		{
225			$$ = empty_data;
226		}
227	| celllist cellval
228		{
229			$$ = data_append_cell($1, $2);
230		}
231	| celllist DT_REF
232		{
233			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
234							      $2), -1);
235		}
236	| celllist DT_LABEL
237		{
238			$$ = data_add_marker($1, LABEL, $2);
239		}
240	;
241
242cellval:
243	  DT_LITERAL
244		{
245			$$ = eval_literal($1, 0, 32);
246		}
247	;
248
249bytestring:
250	  /* empty */
251		{
252			$$ = empty_data;
253		}
254	| bytestring DT_BYTE
255		{
256			$$ = data_append_byte($1, $2);
257		}
258	| bytestring DT_LABEL
259		{
260			$$ = data_add_marker($1, LABEL, $2);
261		}
262	;
263
264subnodes:
265	  /* empty */
266		{
267			$$ = NULL;
268		}
269	|  subnode subnodes
270		{
271			$$ = chain_node($1, $2);
272		}
273	| subnode propdef
274		{
275			yyerror("syntax error: properties must precede subnodes");
276			YYERROR;
277		}
278	;
279
280subnode:
281	  label DT_PROPNODENAME nodedef
282		{
283			$$ = name_node($3, $2, $1);
284		}
285	;
286
287label:
288	  /* empty */
289		{
290			$$ = NULL;
291		}
292	| DT_LABEL
293		{
294			$$ = $1;
295		}
296	;
297
298%%
299
300void yyerror(char const *s)
301{
302	srcpos_error(&yylloc, "%s", s);
303	treesource_error = 1;
304}
305
306static unsigned long long eval_literal(const char *s, int base, int bits)
307{
308	unsigned long long val;
309	char *e;
310
311	errno = 0;
312	val = strtoull(s, &e, base);
313	if (*e)
314		yyerror("bad characters in literal");
315	else if ((errno == ERANGE)
316		 || ((bits < 64) && (val >= (1ULL << bits))))
317		yyerror("literal out of range");
318	else if (errno != 0)
319		yyerror("bad literal");
320	return val;
321}
322