dtc-parser.y revision 204489
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%{
23204431Sraj#include <stdio.h>
24204431Sraj
25204431Sraj#include "dtc.h"
26204431Sraj#include "srcpos.h"
27204431Sraj
28204489SrajYYLTYPE yylloc;
29204489Sraj
30204431Srajextern int yylex(void);
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);
37204431Sraj%}
38204431Sraj
39204431Sraj%union {
40204431Sraj	char *propnodename;
41204431Sraj	char *literal;
42204431Sraj	char *labelref;
43204431Sraj	unsigned int cbase;
44204431Sraj	uint8_t byte;
45204431Sraj	struct data data;
46204431Sraj
47204431Sraj	uint64_t addr;
48204431Sraj	cell_t cell;
49204431Sraj	struct property *prop;
50204431Sraj	struct property *proplist;
51204431Sraj	struct node *node;
52204431Sraj	struct node *nodelist;
53204431Sraj	struct reserve_info *re;
54204431Sraj}
55204431Sraj
56204431Sraj%token DT_V1
57204431Sraj%token DT_MEMRESERVE
58204431Sraj%token <propnodename> DT_PROPNODENAME
59204431Sraj%token <literal> DT_LITERAL
60204431Sraj%token <cbase> DT_BASE
61204431Sraj%token <byte> DT_BYTE
62204431Sraj%token <data> DT_STRING
63204431Sraj%token <labelref> DT_LABEL
64204431Sraj%token <labelref> DT_REF
65204431Sraj%token DT_INCBIN
66204431Sraj
67204431Sraj%type <data> propdata
68204431Sraj%type <data> propdataprefix
69204431Sraj%type <re> memreserve
70204431Sraj%type <re> memreserves
71204431Sraj%type <addr> addr
72204431Sraj%type <data> celllist
73204431Sraj%type <cell> cellval
74204431Sraj%type <data> bytestring
75204431Sraj%type <prop> propdef
76204431Sraj%type <proplist> proplist
77204431Sraj
78204431Sraj%type <node> devicetree
79204431Sraj%type <node> nodedef
80204431Sraj%type <node> subnode
81204431Sraj%type <nodelist> subnodes
82204431Sraj%type <labelref> label
83204431Sraj
84204431Sraj%%
85204431Sraj
86204431Srajsourcefile:
87204431Sraj	  DT_V1 ';' memreserves devicetree
88204431Sraj		{
89204431Sraj			the_boot_info = build_boot_info($3, $4, 0);
90204431Sraj		}
91204431Sraj	;
92204431Sraj
93204431Srajmemreserves:
94204431Sraj	  /* empty */
95204431Sraj		{
96204431Sraj			$$ = NULL;
97204431Sraj		}
98204431Sraj	| memreserve memreserves
99204431Sraj		{
100204431Sraj			$$ = chain_reserve_entry($1, $2);
101204431Sraj		}
102204431Sraj	;
103204431Sraj
104204431Srajmemreserve:
105204431Sraj	  label DT_MEMRESERVE addr addr ';'
106204431Sraj		{
107204431Sraj			$$ = build_reserve_entry($3, $4, $1);
108204431Sraj		}
109204431Sraj	;
110204431Sraj
111204431Srajaddr:
112204431Sraj	  DT_LITERAL
113204431Sraj		{
114204431Sraj			$$ = eval_literal($1, 0, 64);
115204431Sraj		}
116204431Sraj	  ;
117204431Sraj
118204431Srajdevicetree:
119204431Sraj	  '/' nodedef
120204431Sraj		{
121204431Sraj			$$ = name_node($2, "", NULL);
122204431Sraj		}
123204431Sraj	;
124204431Sraj
125204431Srajnodedef:
126204431Sraj	  '{' proplist subnodes '}' ';'
127204431Sraj		{
128204431Sraj			$$ = build_node($2, $3);
129204431Sraj		}
130204431Sraj	;
131204431Sraj
132204431Srajproplist:
133204431Sraj	  /* empty */
134204431Sraj		{
135204431Sraj			$$ = NULL;
136204431Sraj		}
137204431Sraj	| proplist propdef
138204431Sraj		{
139204431Sraj			$$ = chain_property($2, $1);
140204431Sraj		}
141204431Sraj	;
142204431Sraj
143204431Srajpropdef:
144204431Sraj	  label DT_PROPNODENAME '=' propdata ';'
145204431Sraj		{
146204431Sraj			$$ = build_property($2, $4, $1);
147204431Sraj		}
148204431Sraj	| label DT_PROPNODENAME ';'
149204431Sraj		{
150204431Sraj			$$ = build_property($2, empty_data, $1);
151204431Sraj		}
152204431Sraj	;
153204431Sraj
154204431Srajpropdata:
155204431Sraj	  propdataprefix DT_STRING
156204431Sraj		{
157204431Sraj			$$ = data_merge($1, $2);
158204431Sraj		}
159204431Sraj	| propdataprefix '<' celllist '>'
160204431Sraj		{
161204431Sraj			$$ = data_merge($1, $3);
162204431Sraj		}
163204431Sraj	| propdataprefix '[' bytestring ']'
164204431Sraj		{
165204431Sraj			$$ = data_merge($1, $3);
166204431Sraj		}
167204431Sraj	| propdataprefix DT_REF
168204431Sraj		{
169204431Sraj			$$ = data_add_marker($1, REF_PATH, $2);
170204431Sraj		}
171204431Sraj	| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
172204431Sraj		{
173204431Sraj			struct search_path path = { srcpos_file->dir, NULL, NULL };
174204431Sraj			struct dtc_file *file = dtc_open_file($4.val, &path);
175204431Sraj			struct data d = empty_data;
176204431Sraj
177204431Sraj			if ($6 != 0)
178204431Sraj				if (fseek(file->file, $6, SEEK_SET) != 0)
179204433Sraj					srcpos_error(&yylloc,
180204433Sraj						     "Couldn't seek to offset %llu in \"%s\": %s",
181204433Sraj						     (unsigned long long)$6,
182204433Sraj						     $4.val,
183204433Sraj						     strerror(errno));
184204431Sraj
185204431Sraj			d = data_copy_file(file->file, $8);
186204431Sraj
187204431Sraj			$$ = data_merge($1, d);
188204431Sraj			dtc_close_file(file);
189204431Sraj		}
190204431Sraj	| propdataprefix DT_INCBIN '(' DT_STRING ')'
191204431Sraj		{
192204431Sraj			struct search_path path = { srcpos_file->dir, NULL, NULL };
193204431Sraj			struct dtc_file *file = dtc_open_file($4.val, &path);
194204431Sraj			struct data d = empty_data;
195204431Sraj
196204431Sraj			d = data_copy_file(file->file, -1);
197204431Sraj
198204431Sraj			$$ = data_merge($1, d);
199204431Sraj			dtc_close_file(file);
200204431Sraj		}
201204431Sraj	| propdata DT_LABEL
202204431Sraj		{
203204431Sraj			$$ = data_add_marker($1, LABEL, $2);
204204431Sraj		}
205204431Sraj	;
206204431Sraj
207204431Srajpropdataprefix:
208204431Sraj	  /* empty */
209204431Sraj		{
210204431Sraj			$$ = empty_data;
211204431Sraj		}
212204431Sraj	| propdata ','
213204431Sraj		{
214204431Sraj			$$ = $1;
215204431Sraj		}
216204431Sraj	| propdataprefix DT_LABEL
217204431Sraj		{
218204431Sraj			$$ = data_add_marker($1, LABEL, $2);
219204431Sraj		}
220204431Sraj	;
221204431Sraj
222204431Srajcelllist:
223204431Sraj	  /* empty */
224204431Sraj		{
225204431Sraj			$$ = empty_data;
226204431Sraj		}
227204431Sraj	| celllist cellval
228204431Sraj		{
229204431Sraj			$$ = data_append_cell($1, $2);
230204431Sraj		}
231204431Sraj	| celllist DT_REF
232204431Sraj		{
233204431Sraj			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
234204431Sraj							      $2), -1);
235204431Sraj		}
236204431Sraj	| celllist DT_LABEL
237204431Sraj		{
238204431Sraj			$$ = data_add_marker($1, LABEL, $2);
239204431Sraj		}
240204431Sraj	;
241204431Sraj
242204431Srajcellval:
243204431Sraj	  DT_LITERAL
244204431Sraj		{
245204431Sraj			$$ = eval_literal($1, 0, 32);
246204431Sraj		}
247204431Sraj	;
248204431Sraj
249204431Srajbytestring:
250204431Sraj	  /* empty */
251204431Sraj		{
252204431Sraj			$$ = empty_data;
253204431Sraj		}
254204431Sraj	| bytestring DT_BYTE
255204431Sraj		{
256204431Sraj			$$ = data_append_byte($1, $2);
257204431Sraj		}
258204431Sraj	| bytestring DT_LABEL
259204431Sraj		{
260204431Sraj			$$ = data_add_marker($1, LABEL, $2);
261204431Sraj		}
262204431Sraj	;
263204431Sraj
264204431Srajsubnodes:
265204431Sraj	  /* empty */
266204431Sraj		{
267204431Sraj			$$ = NULL;
268204431Sraj		}
269204431Sraj	|  subnode subnodes
270204431Sraj		{
271204431Sraj			$$ = chain_node($1, $2);
272204431Sraj		}
273204431Sraj	| subnode propdef
274204431Sraj		{
275204431Sraj			yyerror("syntax error: properties must precede subnodes");
276204431Sraj			YYERROR;
277204431Sraj		}
278204431Sraj	;
279204431Sraj
280204431Srajsubnode:
281204431Sraj	  label DT_PROPNODENAME nodedef
282204431Sraj		{
283204431Sraj			$$ = name_node($3, $2, $1);
284204431Sraj		}
285204431Sraj	;
286204431Sraj
287204431Srajlabel:
288204431Sraj	  /* empty */
289204431Sraj		{
290204431Sraj			$$ = NULL;
291204431Sraj		}
292204431Sraj	| DT_LABEL
293204431Sraj		{
294204431Sraj			$$ = $1;
295204431Sraj		}
296204431Sraj	;
297204431Sraj
298204431Sraj%%
299204431Sraj
300204433Srajvoid yyerror(char const *s)
301204431Sraj{
302204433Sraj	srcpos_error(&yylloc, "%s", s);
303204431Sraj	treesource_error = 1;
304204431Sraj}
305204431Sraj
306204431Srajstatic unsigned long long eval_literal(const char *s, int base, int bits)
307204431Sraj{
308204431Sraj	unsigned long long val;
309204431Sraj	char *e;
310204431Sraj
311204431Sraj	errno = 0;
312204431Sraj	val = strtoull(s, &e, base);
313204431Sraj	if (*e)
314204431Sraj		yyerror("bad characters in literal");
315204431Sraj	else if ((errno == ERANGE)
316204431Sraj		 || ((bits < 64) && (val >= (1ULL << bits))))
317204431Sraj		yyerror("literal out of range");
318204431Sraj	else if (errno != 0)
319204431Sraj		yyerror("bad literal");
320204431Sraj	return val;
321204431Sraj}
322