blob: b2ab562420ead9815ac83adf4372bece16e10f23 [file] [log] [blame]
David Gibsonfc14dad2005-06-08 17:18:34 +10001/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
David Gibson63dc9c72007-09-18 11:44:04 +10004 *
David Gibsonfc14dad2005-06-08 17:18:34 +10005 * 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.
David Gibson63dc9c72007-09-18 11:44:04 +100014 *
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
David Gibsonfc14dad2005-06-08 17:18:34 +100019 */
20
David Gibson86dbcbd2005-10-19 16:00:31 +100021%locations
22
David Gibsonfc14dad2005-06-08 17:18:34 +100023%{
David Gibsone37ec7d2008-06-11 11:58:39 +100024#include <stdio.h>
25
David Gibsonfc14dad2005-06-08 17:18:34 +100026#include "dtc.h"
Jon Loeligere45e6fd2007-03-23 15:18:41 -050027#include "srcpos.h"
David Gibsonfc14dad2005-06-08 17:18:34 +100028
David Gibson6b8e0562008-03-05 11:47:54 +110029extern int yylex(void);
David Gibsonfc14dad2005-06-08 17:18:34 +100030
David Gibsonf0517db2005-07-15 17:14:24 +100031extern struct boot_info *the_boot_info;
Scott Woodad4f54a2008-01-03 17:43:33 -060032extern int treesource_error;
David Gibsonfc14dad2005-06-08 17:18:34 +100033
David Gibson6b8e0562008-03-05 11:47:54 +110034static unsigned long long eval_literal(const char *s, int base, int bits);
David Gibsonfc14dad2005-06-08 17:18:34 +100035%}
36
37%union {
David Gibson9ed27a22007-11-07 11:16:19 +110038 char *propnodename;
39 char *literal;
40 char *labelref;
Jon Loeligeraf0278a2007-02-15 10:59:27 -060041 unsigned int cbase;
David Gibson53359012008-06-25 13:53:07 +100042 uint8_t byte;
David Gibsonfc14dad2005-06-08 17:18:34 +100043 struct data data;
David Gibson9ed27a22007-11-07 11:16:19 +110044
David Gibson53359012008-06-25 13:53:07 +100045 uint64_t addr;
David Gibson9ed27a22007-11-07 11:16:19 +110046 cell_t cell;
David Gibsonfc14dad2005-06-08 17:18:34 +100047 struct property *prop;
48 struct property *proplist;
49 struct node *node;
50 struct node *nodelist;
David Gibsonf040d952005-10-24 18:18:38 +100051 struct reserve_info *re;
David Gibsonfc14dad2005-06-08 17:18:34 +100052}
53
David Gibson9138db52007-11-07 11:17:17 +110054%token DT_V1
David Gibsonf0517db2005-07-15 17:14:24 +100055%token DT_MEMRESERVE
David Gibson9ed27a22007-11-07 11:16:19 +110056%token <propnodename> DT_PROPNODENAME
57%token <literal> DT_LITERAL
David Gibson9138db52007-11-07 11:17:17 +110058%token <literal> DT_LEGACYLITERAL
Jon Loeligeraf0278a2007-02-15 10:59:27 -060059%token <cbase> DT_BASE
David Gibsonfc14dad2005-06-08 17:18:34 +100060%token <byte> DT_BYTE
61%token <data> DT_STRING
David Gibson9ed27a22007-11-07 11:16:19 +110062%token <labelref> DT_LABEL
63%token <labelref> DT_REF
David Gibsone37ec7d2008-06-11 11:58:39 +100064%token DT_INCBIN
David Gibsonfc14dad2005-06-08 17:18:34 +100065
66%type <data> propdata
David Gibson32da4752007-02-07 16:37:50 +110067%type <data> propdataprefix
David Gibsonf0517db2005-07-15 17:14:24 +100068%type <re> memreserve
David Gibsonf040d952005-10-24 18:18:38 +100069%type <re> memreserves
David Gibson9138db52007-11-07 11:17:17 +110070%type <re> v0_memreserve
71%type <re> v0_memreserves
David Gibson9ed27a22007-11-07 11:16:19 +110072%type <addr> addr
David Gibsonfc14dad2005-06-08 17:18:34 +100073%type <data> celllist
David Gibson9ed27a22007-11-07 11:16:19 +110074%type <cbase> cellbase
75%type <cell> cellval
David Gibsonfc14dad2005-06-08 17:18:34 +100076%type <data> bytestring
77%type <prop> propdef
78%type <proplist> proplist
79
David Gibsonf0517db2005-07-15 17:14:24 +100080%type <node> devicetree
David Gibsonfc14dad2005-06-08 17:18:34 +100081%type <node> nodedef
82%type <node> subnode
83%type <nodelist> subnodes
David Gibson9ed27a22007-11-07 11:16:19 +110084%type <labelref> label
David Gibson4102d842005-06-16 14:36:37 +100085
David Gibsonfc14dad2005-06-08 17:18:34 +100086%%
87
Jon Loeliger30807ca2007-10-18 09:42:16 -050088sourcefile:
David Gibson9138db52007-11-07 11:17:17 +110089 DT_V1 ';' memreserves devicetree
90 {
David Gibson548767f2008-05-16 13:22:57 +100091 the_boot_info = build_boot_info($3, $4, 0);
David Gibson9138db52007-11-07 11:17:17 +110092 }
93 | v0_memreserves devicetree
Jon Loeliger30807ca2007-10-18 09:42:16 -050094 {
David Gibson548767f2008-05-16 13:22:57 +100095 the_boot_info = build_boot_info($1, $2, 0);
David Gibsonf0517db2005-07-15 17:14:24 +100096 }
97 ;
98
Jon Loeliger30807ca2007-10-18 09:42:16 -050099memreserves:
Jon Loeliger56412892007-10-23 09:28:54 -0500100 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500101 {
David Gibsonf040d952005-10-24 18:18:38 +1000102 $$ = NULL;
David Gibsonf0517db2005-07-15 17:14:24 +1000103 }
Jon Loeliger56412892007-10-23 09:28:54 -0500104 | memreserve memreserves
105 {
106 $$ = chain_reserve_entry($1, $2);
107 }
David Gibsonf0517db2005-07-15 17:14:24 +1000108 ;
109
Jon Loeliger30807ca2007-10-18 09:42:16 -0500110memreserve:
David Gibson9ed27a22007-11-07 11:16:19 +1100111 label DT_MEMRESERVE addr addr ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500112 {
Milton Millerd4290332007-07-07 01:18:49 -0500113 $$ = build_reserve_entry($3, $4, $1);
David Gibsonf0517db2005-07-15 17:14:24 +1000114 }
David Gibson9138db52007-11-07 11:17:17 +1100115 ;
116
117v0_memreserves:
118 /* empty */
119 {
120 $$ = NULL;
121 }
122 | v0_memreserve v0_memreserves
123 {
124 $$ = chain_reserve_entry($1, $2);
125 };
126 ;
127
128v0_memreserve:
129 memreserve
130 {
131 $$ = $1;
132 }
David Gibson9ed27a22007-11-07 11:16:19 +1100133 | label DT_MEMRESERVE addr '-' addr ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500134 {
Milton Millerd4290332007-07-07 01:18:49 -0500135 $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
David Gibsonf0517db2005-07-15 17:14:24 +1000136 }
137 ;
138
David Gibson9ed27a22007-11-07 11:16:19 +1100139addr:
140 DT_LITERAL
141 {
David Gibson9138db52007-11-07 11:17:17 +1100142 $$ = eval_literal($1, 0, 64);
143 }
144 | DT_LEGACYLITERAL
145 {
David Gibson9ed27a22007-11-07 11:16:19 +1100146 $$ = eval_literal($1, 16, 64);
147 }
148 ;
149
Jon Loeliger30807ca2007-10-18 09:42:16 -0500150devicetree:
151 '/' nodedef
152 {
David Gibsonf0517db2005-07-15 17:14:24 +1000153 $$ = name_node($2, "", NULL);
154 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000155 ;
156
Jon Loeliger30807ca2007-10-18 09:42:16 -0500157nodedef:
158 '{' proplist subnodes '}' ';'
159 {
David Gibsonfc14dad2005-06-08 17:18:34 +1000160 $$ = build_node($2, $3);
161 }
162 ;
163
Jon Loeliger30807ca2007-10-18 09:42:16 -0500164proplist:
Jon Loeliger56412892007-10-23 09:28:54 -0500165 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500166 {
David Gibsonfc14dad2005-06-08 17:18:34 +1000167 $$ = NULL;
168 }
Jon Loeliger7b3fb782007-10-22 16:09:56 -0500169 | proplist propdef
Jon Loeliger56412892007-10-23 09:28:54 -0500170 {
Jon Loeliger7b3fb782007-10-22 16:09:56 -0500171 $$ = chain_property($2, $1);
Jon Loeliger56412892007-10-23 09:28:54 -0500172 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000173 ;
174
Jon Loeliger30807ca2007-10-18 09:42:16 -0500175propdef:
David Gibson9ed27a22007-11-07 11:16:19 +1100176 label DT_PROPNODENAME '=' propdata ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500177 {
David Gibson4102d842005-06-16 14:36:37 +1000178 $$ = build_property($2, $4, $1);
David Gibsonfc14dad2005-06-08 17:18:34 +1000179 }
David Gibson9ed27a22007-11-07 11:16:19 +1100180 | label DT_PROPNODENAME ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500181 {
David Gibson9ad45872005-06-17 14:32:32 +1000182 $$ = build_property($2, empty_data, $1);
David Gibsonfc14dad2005-06-08 17:18:34 +1000183 }
184 ;
185
Jon Loeliger30807ca2007-10-18 09:42:16 -0500186propdata:
187 propdataprefix DT_STRING
188 {
189 $$ = data_merge($1, $2);
David Gibson32da4752007-02-07 16:37:50 +1100190 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500191 | propdataprefix '<' celllist '>'
192 {
David Gibsonf7497dc2007-11-02 16:54:26 +1100193 $$ = data_merge($1, $3);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500194 }
195 | propdataprefix '[' bytestring ']'
196 {
197 $$ = data_merge($1, $3);
198 }
David Gibsonefbbef82007-12-05 10:43:50 +1100199 | propdataprefix DT_REF
200 {
201 $$ = data_add_marker($1, REF_PATH, $2);
202 }
David Gibsone37ec7d2008-06-11 11:58:39 +1000203 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
204 {
205 struct search_path path = { srcpos_file->dir, NULL, NULL };
206 struct dtc_file *file = dtc_open_file($4.val, &path);
207 struct data d = empty_data;
208
209 if ($6 != 0)
210 if (fseek(file->file, $6, SEEK_SET) != 0)
211 yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
212 (unsigned long long)$6,
213 $4.val, strerror(errno));
214
215 d = data_copy_file(file->file, $8);
216
217 $$ = data_merge($1, d);
218 dtc_close_file(file);
219 }
220 | propdataprefix DT_INCBIN '(' DT_STRING ')'
221 {
222 struct search_path path = { srcpos_file->dir, NULL, NULL };
223 struct dtc_file *file = dtc_open_file($4.val, &path);
224 struct data d = empty_data;
225
226 d = data_copy_file(file->file, -1);
227
228 $$ = data_merge($1, d);
229 dtc_close_file(file);
230 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500231 | propdata DT_LABEL
232 {
David Gibsondc941772007-11-22 14:39:23 +1100233 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500234 }
David Gibson32da4752007-02-07 16:37:50 +1100235 ;
236
Jon Loeliger30807ca2007-10-18 09:42:16 -0500237propdataprefix:
Jon Loeliger56412892007-10-23 09:28:54 -0500238 /* empty */
239 {
240 $$ = empty_data;
241 }
242 | propdata ','
Jon Loeliger30807ca2007-10-18 09:42:16 -0500243 {
244 $$ = $1;
245 }
246 | propdataprefix DT_LABEL
247 {
David Gibsondc941772007-11-22 14:39:23 +1100248 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500249 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000250 ;
251
Jon Loeliger30807ca2007-10-18 09:42:16 -0500252celllist:
Jon Loeliger56412892007-10-23 09:28:54 -0500253 /* empty */
254 {
255 $$ = empty_data;
256 }
David Gibson9ed27a22007-11-07 11:16:19 +1100257 | celllist cellval
Jon Loeliger30807ca2007-10-18 09:42:16 -0500258 {
David Gibson9ed27a22007-11-07 11:16:19 +1100259 $$ = data_append_cell($1, $2);
Jon Loeligeraf0278a2007-02-15 10:59:27 -0600260 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500261 | celllist DT_REF
262 {
David Gibsondc941772007-11-22 14:39:23 +1100263 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
264 $2), -1);
David Gibson81f2e892005-06-16 17:04:00 +1000265 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500266 | celllist DT_LABEL
267 {
David Gibsondc941772007-11-22 14:39:23 +1100268 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500269 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000270 ;
271
David Gibson9ed27a22007-11-07 11:16:19 +1100272cellbase:
273 /* empty */
274 {
275 $$ = 16;
276 }
277 | DT_BASE
278 ;
279
280cellval:
David Gibson9138db52007-11-07 11:17:17 +1100281 DT_LITERAL
282 {
283 $$ = eval_literal($1, 0, 32);
284 }
285 | cellbase DT_LEGACYLITERAL
David Gibson9ed27a22007-11-07 11:16:19 +1100286 {
287 $$ = eval_literal($2, $1, 32);
288 }
289 ;
290
Jon Loeliger30807ca2007-10-18 09:42:16 -0500291bytestring:
Jon Loeliger56412892007-10-23 09:28:54 -0500292 /* empty */
293 {
294 $$ = empty_data;
295 }
296 | bytestring DT_BYTE
Jon Loeliger30807ca2007-10-18 09:42:16 -0500297 {
298 $$ = data_append_byte($1, $2);
299 }
300 | bytestring DT_LABEL
301 {
David Gibsondc941772007-11-22 14:39:23 +1100302 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500303 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000304 ;
305
Jon Loeliger30807ca2007-10-18 09:42:16 -0500306subnodes:
Jon Loeliger56412892007-10-23 09:28:54 -0500307 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500308 {
309 $$ = NULL;
310 }
Jon Loeliger56412892007-10-23 09:28:54 -0500311 | subnode subnodes
312 {
313 $$ = chain_node($1, $2);
314 }
David Gibsonc0481022007-12-05 10:27:04 +1100315 | subnode propdef
316 {
Scott Wood3c3ecaa2008-01-04 15:10:47 -0600317 yyerror("syntax error: properties must precede subnodes");
David Gibsonc0481022007-12-05 10:27:04 +1100318 YYERROR;
319 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000320 ;
321
Jon Loeliger30807ca2007-10-18 09:42:16 -0500322subnode:
David Gibson9ed27a22007-11-07 11:16:19 +1100323 label DT_PROPNODENAME nodedef
Jon Loeliger30807ca2007-10-18 09:42:16 -0500324 {
325 $$ = name_node($3, $2, $1);
326 }
David Gibson4102d842005-06-16 14:36:37 +1000327 ;
328
Jon Loeliger30807ca2007-10-18 09:42:16 -0500329label:
Jon Loeliger56412892007-10-23 09:28:54 -0500330 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500331 {
332 $$ = NULL;
333 }
Jon Loeliger56412892007-10-23 09:28:54 -0500334 | DT_LABEL
335 {
336 $$ = $1;
337 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000338 ;
339
340%%
341
Scott Woodf77fe6a2008-01-03 17:43:29 -0600342void yyerrorf(char const *s, ...)
David Gibsonfc14dad2005-06-08 17:18:34 +1000343{
Scott Wood910efac2008-01-03 17:43:31 -0600344 const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
Scott Woodf77fe6a2008-01-03 17:43:29 -0600345 va_list va;
346 va_start(va, s);
Jon Loeligere45e6fd2007-03-23 15:18:41 -0500347
348 if (strcmp(fname, "-") == 0)
349 fname = "stdin";
350
Scott Woodf77fe6a2008-01-03 17:43:29 -0600351 fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
352 vfprintf(stderr, s, va);
353 fprintf(stderr, "\n");
354
Scott Woodad4f54a2008-01-03 17:43:33 -0600355 treesource_error = 1;
Scott Woodf77fe6a2008-01-03 17:43:29 -0600356 va_end(va);
357}
358
359void yyerror (char const *s)
360{
361 yyerrorf("%s", s);
David Gibsonfc14dad2005-06-08 17:18:34 +1000362}
Jon Loeliger39488492007-02-16 09:33:54 -0600363
David Gibson6b8e0562008-03-05 11:47:54 +1100364static unsigned long long eval_literal(const char *s, int base, int bits)
Jon Loeliger39488492007-02-16 09:33:54 -0600365{
David Gibson9ed27a22007-11-07 11:16:19 +1100366 unsigned long long val;
Milton Miller85ab5cc2007-07-07 01:18:48 -0500367 char *e;
Jon Loeliger39488492007-02-16 09:33:54 -0600368
David Gibson9ed27a22007-11-07 11:16:19 +1100369 errno = 0;
370 val = strtoull(s, &e, base);
371 if (*e)
372 yyerror("bad characters in literal");
373 else if ((errno == ERANGE)
374 || ((bits < 64) && (val >= (1ULL << bits))))
375 yyerror("literal out of range");
376 else if (errno != 0)
377 yyerror("bad literal");
378 return val;
Jon Loeliger39488492007-02-16 09:33:54 -0600379}