blob: 5e84a67fc1d2bf110d0d33040d9d3178f5bbddb6 [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
David Gibsona4da2e32007-12-18 15:06:42 +110021%{
David Gibsoned95d742008-08-07 12:24:17 +100022#include <stdio.h>
23
David Gibsona4da2e32007-12-18 15:06:42 +110024#include "dtc.h"
25#include "srcpos.h"
26
John Bonesio658f29a2010-11-17 15:28:20 -080027YYLTYPE yylloc;
28
David Gibsoned95d742008-08-07 12:24:17 +100029extern int yylex(void);
John Bonesio658f29a2010-11-17 15:28:20 -080030extern void print_error(char const *fmt, ...);
31extern void yyerror(char const *s);
David Gibsona4da2e32007-12-18 15:06:42 +110032
33extern struct boot_info *the_boot_info;
David Gibsoned95d742008-08-07 12:24:17 +100034extern int treesource_error;
David Gibsona4da2e32007-12-18 15:06:42 +110035
David Gibsoned95d742008-08-07 12:24:17 +100036static unsigned long long eval_literal(const char *s, int base, int bits);
David Gibsona4da2e32007-12-18 15:06:42 +110037%}
38
39%union {
40 char *propnodename;
41 char *literal;
42 char *labelref;
43 unsigned int cbase;
David Gibsoned95d742008-08-07 12:24:17 +100044 uint8_t byte;
David Gibsona4da2e32007-12-18 15:06:42 +110045 struct data data;
46
David Gibsoned95d742008-08-07 12:24:17 +100047 uint64_t addr;
David Gibsona4da2e32007-12-18 15:06:42 +110048 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
David Gibsona4da2e32007-12-18 15:06:42 +110060%token <cbase> DT_BASE
61%token <byte> DT_BYTE
62%token <data> DT_STRING
63%token <labelref> DT_LABEL
64%token <labelref> DT_REF
David Gibsoned95d742008-08-07 12:24:17 +100065%token DT_INCBIN
David Gibsona4da2e32007-12-18 15:06:42 +110066
67%type <data> propdata
68%type <data> propdataprefix
69%type <re> memreserve
70%type <re> memreserves
David Gibsona4da2e32007-12-18 15:06:42 +110071%type <addr> addr
72%type <data> celllist
David Gibsona4da2e32007-12-18 15:06:42 +110073%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
David Gibsona4da2e32007-12-18 15:06:42 +110082
83%%
84
85sourcefile:
86 DT_V1 ';' memreserves devicetree
87 {
John Bonesio658f29a2010-11-17 15:28:20 -080088 the_boot_info = build_boot_info($3, $4,
89 guess_boot_cpuid($4));
David Gibsona4da2e32007-12-18 15:06:42 +110090 }
91 ;
92
93memreserves:
94 /* empty */
95 {
96 $$ = NULL;
97 }
98 | memreserve memreserves
99 {
100 $$ = chain_reserve_entry($1, $2);
101 }
102 ;
103
104memreserve:
John Bonesio658f29a2010-11-17 15:28:20 -0800105 DT_MEMRESERVE addr addr ';'
David Gibsona4da2e32007-12-18 15:06:42 +1100106 {
John Bonesio658f29a2010-11-17 15:28:20 -0800107 $$ = build_reserve_entry($2, $3);
David Gibsona4da2e32007-12-18 15:06:42 +1100108 }
John Bonesio658f29a2010-11-17 15:28:20 -0800109 | DT_LABEL memreserve
David Gibsona4da2e32007-12-18 15:06:42 +1100110 {
John Bonesio658f29a2010-11-17 15:28:20 -0800111 add_label(&$2->labels, $1);
112 $$ = $2;
David Gibsona4da2e32007-12-18 15:06:42 +1100113 }
114 ;
115
116addr:
117 DT_LITERAL
118 {
119 $$ = eval_literal($1, 0, 64);
120 }
David Gibsona4da2e32007-12-18 15:06:42 +1100121 ;
122
123devicetree:
124 '/' nodedef
125 {
John Bonesio658f29a2010-11-17 15:28:20 -0800126 $$ = name_node($2, "");
127 }
128 | devicetree '/' nodedef
129 {
130 $$ = merge_nodes($1, $3);
131 }
132 | devicetree DT_REF nodedef
133 {
134 struct node *target = get_node_by_ref($1, $2);
135
136 if (target)
137 merge_nodes(target, $3);
138 else
139 print_error("label or path, '%s', not found", $2);
140 $$ = $1;
David Gibsona4da2e32007-12-18 15:06:42 +1100141 }
142 ;
143
144nodedef:
145 '{' proplist subnodes '}' ';'
146 {
147 $$ = build_node($2, $3);
148 }
149 ;
150
151proplist:
152 /* empty */
153 {
154 $$ = NULL;
155 }
156 | proplist propdef
157 {
158 $$ = chain_property($2, $1);
159 }
160 ;
161
162propdef:
John Bonesio658f29a2010-11-17 15:28:20 -0800163 DT_PROPNODENAME '=' propdata ';'
David Gibsona4da2e32007-12-18 15:06:42 +1100164 {
John Bonesio658f29a2010-11-17 15:28:20 -0800165 $$ = build_property($1, $3);
David Gibsona4da2e32007-12-18 15:06:42 +1100166 }
John Bonesio658f29a2010-11-17 15:28:20 -0800167 | DT_PROPNODENAME ';'
David Gibsona4da2e32007-12-18 15:06:42 +1100168 {
John Bonesio658f29a2010-11-17 15:28:20 -0800169 $$ = build_property($1, empty_data);
170 }
171 | DT_LABEL propdef
172 {
173 add_label(&$2->labels, $1);
174 $$ = $2;
David Gibsona4da2e32007-12-18 15:06:42 +1100175 }
176 ;
177
178propdata:
179 propdataprefix DT_STRING
180 {
181 $$ = data_merge($1, $2);
182 }
183 | propdataprefix '<' celllist '>'
184 {
185 $$ = data_merge($1, $3);
186 }
187 | propdataprefix '[' bytestring ']'
188 {
189 $$ = data_merge($1, $3);
190 }
191 | propdataprefix DT_REF
192 {
193 $$ = data_add_marker($1, REF_PATH, $2);
194 }
David Gibsoned95d742008-08-07 12:24:17 +1000195 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
196 {
John Bonesio658f29a2010-11-17 15:28:20 -0800197 FILE *f = srcfile_relative_open($4.val, NULL);
198 struct data d;
David Gibsoned95d742008-08-07 12:24:17 +1000199
200 if ($6 != 0)
John Bonesio658f29a2010-11-17 15:28:20 -0800201 if (fseek(f, $6, SEEK_SET) != 0)
202 print_error("Couldn't seek to offset %llu in \"%s\": %s",
203 (unsigned long long)$6,
204 $4.val,
205 strerror(errno));
David Gibsoned95d742008-08-07 12:24:17 +1000206
John Bonesio658f29a2010-11-17 15:28:20 -0800207 d = data_copy_file(f, $8);
David Gibsoned95d742008-08-07 12:24:17 +1000208
209 $$ = data_merge($1, d);
John Bonesio658f29a2010-11-17 15:28:20 -0800210 fclose(f);
David Gibsoned95d742008-08-07 12:24:17 +1000211 }
212 | propdataprefix DT_INCBIN '(' DT_STRING ')'
213 {
John Bonesio658f29a2010-11-17 15:28:20 -0800214 FILE *f = srcfile_relative_open($4.val, NULL);
David Gibsoned95d742008-08-07 12:24:17 +1000215 struct data d = empty_data;
216
John Bonesio658f29a2010-11-17 15:28:20 -0800217 d = data_copy_file(f, -1);
David Gibsoned95d742008-08-07 12:24:17 +1000218
219 $$ = data_merge($1, d);
John Bonesio658f29a2010-11-17 15:28:20 -0800220 fclose(f);
David Gibsoned95d742008-08-07 12:24:17 +1000221 }
David Gibsona4da2e32007-12-18 15:06:42 +1100222 | propdata DT_LABEL
223 {
224 $$ = data_add_marker($1, LABEL, $2);
225 }
226 ;
227
228propdataprefix:
229 /* empty */
230 {
231 $$ = empty_data;
232 }
233 | propdata ','
234 {
235 $$ = $1;
236 }
237 | propdataprefix DT_LABEL
238 {
239 $$ = data_add_marker($1, LABEL, $2);
240 }
241 ;
242
243celllist:
244 /* empty */
245 {
246 $$ = empty_data;
247 }
248 | celllist cellval
249 {
250 $$ = data_append_cell($1, $2);
251 }
252 | celllist DT_REF
253 {
254 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
255 $2), -1);
256 }
257 | celllist DT_LABEL
258 {
259 $$ = data_add_marker($1, LABEL, $2);
260 }
261 ;
262
David Gibsona4da2e32007-12-18 15:06:42 +1100263cellval:
264 DT_LITERAL
265 {
266 $$ = eval_literal($1, 0, 32);
267 }
David Gibsona4da2e32007-12-18 15:06:42 +1100268 ;
269
270bytestring:
271 /* empty */
272 {
273 $$ = empty_data;
274 }
275 | bytestring DT_BYTE
276 {
277 $$ = data_append_byte($1, $2);
278 }
279 | bytestring DT_LABEL
280 {
281 $$ = data_add_marker($1, LABEL, $2);
282 }
283 ;
284
285subnodes:
286 /* empty */
287 {
288 $$ = NULL;
289 }
John Bonesio658f29a2010-11-17 15:28:20 -0800290 | subnode subnodes
David Gibsona4da2e32007-12-18 15:06:42 +1100291 {
292 $$ = chain_node($1, $2);
293 }
294 | subnode propdef
295 {
John Bonesio658f29a2010-11-17 15:28:20 -0800296 print_error("syntax error: properties must precede subnodes");
David Gibsona4da2e32007-12-18 15:06:42 +1100297 YYERROR;
298 }
299 ;
300
301subnode:
John Bonesio658f29a2010-11-17 15:28:20 -0800302 DT_PROPNODENAME nodedef
David Gibsona4da2e32007-12-18 15:06:42 +1100303 {
John Bonesio658f29a2010-11-17 15:28:20 -0800304 $$ = name_node($2, $1);
David Gibsona4da2e32007-12-18 15:06:42 +1100305 }
John Bonesio658f29a2010-11-17 15:28:20 -0800306 | DT_LABEL subnode
David Gibsona4da2e32007-12-18 15:06:42 +1100307 {
John Bonesio658f29a2010-11-17 15:28:20 -0800308 add_label(&$2->labels, $1);
309 $$ = $2;
David Gibsona4da2e32007-12-18 15:06:42 +1100310 }
311 ;
312
313%%
314
John Bonesio658f29a2010-11-17 15:28:20 -0800315void print_error(char const *fmt, ...)
David Gibsona4da2e32007-12-18 15:06:42 +1100316{
David Gibsoned95d742008-08-07 12:24:17 +1000317 va_list va;
David Gibsona4da2e32007-12-18 15:06:42 +1100318
John Bonesio658f29a2010-11-17 15:28:20 -0800319 va_start(va, fmt);
320 srcpos_verror(&yylloc, fmt, va);
321 va_end(va);
David Gibsoned95d742008-08-07 12:24:17 +1000322
323 treesource_error = 1;
David Gibsona4da2e32007-12-18 15:06:42 +1100324}
325
John Bonesio658f29a2010-11-17 15:28:20 -0800326void yyerror(char const *s) {
327 print_error("%s", s);
David Gibsoned95d742008-08-07 12:24:17 +1000328}
329
330static unsigned long long eval_literal(const char *s, int base, int bits)
David Gibsona4da2e32007-12-18 15:06:42 +1100331{
332 unsigned long long val;
333 char *e;
334
335 errno = 0;
336 val = strtoull(s, &e, base);
337 if (*e)
John Bonesio658f29a2010-11-17 15:28:20 -0800338 print_error("bad characters in literal");
David Gibsona4da2e32007-12-18 15:06:42 +1100339 else if ((errno == ERANGE)
340 || ((bits < 64) && (val >= (1ULL << bits))))
John Bonesio658f29a2010-11-17 15:28:20 -0800341 print_error("literal out of range");
David Gibsona4da2e32007-12-18 15:06:42 +1100342 else if (errno != 0)
John Bonesio658f29a2010-11-17 15:28:20 -0800343 print_error("bad literal");
David Gibsona4da2e32007-12-18 15:06:42 +1100344 return val;
345}