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