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