blob: 554f11a9169344f5e5c3158649797525848b7dbc [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
21%{
David Gibsone37ec7d2008-06-11 11:58:39 +100022#include <stdio.h>
23
David Gibsonfc14dad2005-06-08 17:18:34 +100024#include "dtc.h"
Jon Loeligere45e6fd2007-03-23 15:18:41 -050025#include "srcpos.h"
David Gibsonfc14dad2005-06-08 17:18:34 +100026
Lukasz Wojcik5c8d2e22010-01-29 17:31:51 +010027YYLTYPE yylloc;
28
David Gibson6b8e0562008-03-05 11:47:54 +110029extern int yylex(void);
John Bonesioc0fa2e62010-10-20 14:44:58 -070030extern void print_error(char const *fmt, ...);
Jon Loeligere5c8e1d2008-09-12 13:39:49 -050031extern void yyerror(char const *s);
David Gibsonfc14dad2005-06-08 17:18:34 +100032
David Gibsonf0517db2005-07-15 17:14:24 +100033extern struct boot_info *the_boot_info;
Scott Woodad4f54a2008-01-03 17:43:33 -060034extern int treesource_error;
David Gibsonfc14dad2005-06-08 17:18:34 +100035
David Gibson6b8e0562008-03-05 11:47:54 +110036static unsigned long long eval_literal(const char *s, int base, int bits);
Anton Staafa4ea2fa2011-09-09 12:16:30 -070037static unsigned char eval_char_literal(const char *s);
David Gibsonfc14dad2005-06-08 17:18:34 +100038%}
39
40%union {
David Gibson9ed27a22007-11-07 11:16:19 +110041 char *propnodename;
42 char *literal;
43 char *labelref;
Jon Loeligeraf0278a2007-02-15 10:59:27 -060044 unsigned int cbase;
David Gibson53359012008-06-25 13:53:07 +100045 uint8_t byte;
David Gibsonfc14dad2005-06-08 17:18:34 +100046 struct data data;
David Gibson9ed27a22007-11-07 11:16:19 +110047
David Gibson53359012008-06-25 13:53:07 +100048 uint64_t addr;
David Gibson9ed27a22007-11-07 11:16:19 +110049 cell_t cell;
David Gibsonfc14dad2005-06-08 17:18:34 +100050 struct property *prop;
51 struct property *proplist;
52 struct node *node;
53 struct node *nodelist;
David Gibsonf040d952005-10-24 18:18:38 +100054 struct reserve_info *re;
David Gibsonfc14dad2005-06-08 17:18:34 +100055}
56
David Gibson9138db52007-11-07 11:17:17 +110057%token DT_V1
David Gibsonf0517db2005-07-15 17:14:24 +100058%token DT_MEMRESERVE
David Gibson9ed27a22007-11-07 11:16:19 +110059%token <propnodename> DT_PROPNODENAME
60%token <literal> DT_LITERAL
Anton Staafa4ea2fa2011-09-09 12:16:30 -070061%token <literal> DT_CHAR_LITERAL
Jon Loeligeraf0278a2007-02-15 10:59:27 -060062%token <cbase> DT_BASE
David Gibsonfc14dad2005-06-08 17:18:34 +100063%token <byte> DT_BYTE
64%token <data> DT_STRING
David Gibson9ed27a22007-11-07 11:16:19 +110065%token <labelref> DT_LABEL
66%token <labelref> DT_REF
David Gibsone37ec7d2008-06-11 11:58:39 +100067%token DT_INCBIN
David Gibsonfc14dad2005-06-08 17:18:34 +100068
69%type <data> propdata
David Gibson32da4752007-02-07 16:37:50 +110070%type <data> propdataprefix
David Gibsonf0517db2005-07-15 17:14:24 +100071%type <re> memreserve
David Gibsonf040d952005-10-24 18:18:38 +100072%type <re> memreserves
David Gibson9ed27a22007-11-07 11:16:19 +110073%type <addr> addr
David Gibsonfc14dad2005-06-08 17:18:34 +100074%type <data> celllist
David Gibson9ed27a22007-11-07 11:16:19 +110075%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 Gibson4102d842005-06-16 14:36:37 +100084
David Gibsonfc14dad2005-06-08 17:18:34 +100085%%
86
Jon Loeliger30807ca2007-10-18 09:42:16 -050087sourcefile:
David Gibson8773e122010-09-20 16:33:34 -060088 DT_V1 ';' memreserves devicetree
David Gibson9138db52007-11-07 11:17:17 +110089 {
David Gibson15ad6d82010-02-19 15:50:50 +110090 the_boot_info = build_boot_info($3, $4,
91 guess_boot_cpuid($4));
David Gibson9138db52007-11-07 11:17:17 +110092 }
David Gibsonf0517db2005-07-15 17:14:24 +100093 ;
94
Jon Loeliger30807ca2007-10-18 09:42:16 -050095memreserves:
Jon Loeliger56412892007-10-23 09:28:54 -050096 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -050097 {
David Gibsonf040d952005-10-24 18:18:38 +100098 $$ = NULL;
David Gibsonf0517db2005-07-15 17:14:24 +100099 }
Jon Loeliger56412892007-10-23 09:28:54 -0500100 | memreserve memreserves
101 {
102 $$ = chain_reserve_entry($1, $2);
103 }
David Gibsonf0517db2005-07-15 17:14:24 +1000104 ;
105
Jon Loeliger30807ca2007-10-18 09:42:16 -0500106memreserve:
David Gibson05898c62010-02-24 18:22:17 +1100107 DT_MEMRESERVE addr addr ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500108 {
David Gibson05898c62010-02-24 18:22:17 +1100109 $$ = build_reserve_entry($2, $3);
110 }
111 | DT_LABEL memreserve
112 {
113 add_label(&$2->labels, $1);
114 $$ = $2;
David Gibsonf0517db2005-07-15 17:14:24 +1000115 }
David Gibson9138db52007-11-07 11:17:17 +1100116 ;
117
David Gibson9ed27a22007-11-07 11:16:19 +1100118addr:
119 DT_LITERAL
120 {
David Gibson9138db52007-11-07 11:17:17 +1100121 $$ = eval_literal($1, 0, 64);
122 }
David Gibson9ed27a22007-11-07 11:16:19 +1100123 ;
124
Jon Loeliger30807ca2007-10-18 09:42:16 -0500125devicetree:
126 '/' nodedef
127 {
David Gibson05898c62010-02-24 18:22:17 +1100128 $$ = name_node($2, "");
David Gibsonf0517db2005-07-15 17:14:24 +1000129 }
David Gibson8773e122010-09-20 16:33:34 -0600130 | devicetree '/' nodedef
131 {
132 $$ = merge_nodes($1, $3);
133 }
134 | devicetree DT_REF nodedef
135 {
John Bonesio73ae43e2010-11-02 15:55:04 -0700136 struct node *target = get_node_by_ref($1, $2);
David Gibson8773e122010-09-20 16:33:34 -0600137
David Gibson8773e122010-09-20 16:33:34 -0600138 if (target)
139 merge_nodes(target, $3);
140 else
John Bonesio73ae43e2010-11-02 15:55:04 -0700141 print_error("label or path, '%s', not found", $2);
David Gibson8773e122010-09-20 16:33:34 -0600142 $$ = $1;
143 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000144 ;
145
Jon Loeliger30807ca2007-10-18 09:42:16 -0500146nodedef:
147 '{' proplist subnodes '}' ';'
148 {
David Gibsonfc14dad2005-06-08 17:18:34 +1000149 $$ = build_node($2, $3);
150 }
151 ;
152
Jon Loeliger30807ca2007-10-18 09:42:16 -0500153proplist:
Jon Loeliger56412892007-10-23 09:28:54 -0500154 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500155 {
David Gibsonfc14dad2005-06-08 17:18:34 +1000156 $$ = NULL;
157 }
Jon Loeliger7b3fb782007-10-22 16:09:56 -0500158 | proplist propdef
Jon Loeliger56412892007-10-23 09:28:54 -0500159 {
Jon Loeliger7b3fb782007-10-22 16:09:56 -0500160 $$ = chain_property($2, $1);
Jon Loeliger56412892007-10-23 09:28:54 -0500161 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000162 ;
163
Jon Loeliger30807ca2007-10-18 09:42:16 -0500164propdef:
David Gibson05898c62010-02-24 18:22:17 +1100165 DT_PROPNODENAME '=' propdata ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500166 {
David Gibson05898c62010-02-24 18:22:17 +1100167 $$ = build_property($1, $3);
David Gibsonfc14dad2005-06-08 17:18:34 +1000168 }
David Gibson05898c62010-02-24 18:22:17 +1100169 | DT_PROPNODENAME ';'
Jon Loeliger30807ca2007-10-18 09:42:16 -0500170 {
David Gibson05898c62010-02-24 18:22:17 +1100171 $$ = build_property($1, empty_data);
172 }
173 | DT_LABEL propdef
174 {
175 add_label(&$2->labels, $1);
176 $$ = $2;
David Gibsonfc14dad2005-06-08 17:18:34 +1000177 }
178 ;
179
Jon Loeliger30807ca2007-10-18 09:42:16 -0500180propdata:
181 propdataprefix DT_STRING
182 {
183 $$ = data_merge($1, $2);
David Gibson32da4752007-02-07 16:37:50 +1100184 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500185 | propdataprefix '<' celllist '>'
186 {
David Gibsonf7497dc2007-11-02 16:54:26 +1100187 $$ = data_merge($1, $3);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500188 }
189 | propdataprefix '[' bytestring ']'
190 {
191 $$ = data_merge($1, $3);
192 }
David Gibsonefbbef82007-12-05 10:43:50 +1100193 | propdataprefix DT_REF
194 {
195 $$ = data_add_marker($1, REF_PATH, $2);
196 }
David Gibsone37ec7d2008-06-11 11:58:39 +1000197 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
198 {
David Gibsond68cb362009-12-08 14:24:42 +1100199 FILE *f = srcfile_relative_open($4.val, NULL);
200 struct data d;
David Gibsone37ec7d2008-06-11 11:58:39 +1000201
202 if ($6 != 0)
David Gibsond68cb362009-12-08 14:24:42 +1100203 if (fseek(f, $6, SEEK_SET) != 0)
John Bonesioc0fa2e62010-10-20 14:44:58 -0700204 print_error("Couldn't seek to offset %llu in \"%s\": %s",
Jon Loeligere5c8e1d2008-09-12 13:39:49 -0500205 (unsigned long long)$6,
206 $4.val,
207 strerror(errno));
David Gibsone37ec7d2008-06-11 11:58:39 +1000208
David Gibsond68cb362009-12-08 14:24:42 +1100209 d = data_copy_file(f, $8);
David Gibsone37ec7d2008-06-11 11:58:39 +1000210
211 $$ = data_merge($1, d);
David Gibsond68cb362009-12-08 14:24:42 +1100212 fclose(f);
David Gibsone37ec7d2008-06-11 11:58:39 +1000213 }
214 | propdataprefix DT_INCBIN '(' DT_STRING ')'
215 {
David Gibsond68cb362009-12-08 14:24:42 +1100216 FILE *f = srcfile_relative_open($4.val, NULL);
David Gibsone37ec7d2008-06-11 11:58:39 +1000217 struct data d = empty_data;
218
David Gibsond68cb362009-12-08 14:24:42 +1100219 d = data_copy_file(f, -1);
David Gibsone37ec7d2008-06-11 11:58:39 +1000220
221 $$ = data_merge($1, d);
David Gibsond68cb362009-12-08 14:24:42 +1100222 fclose(f);
David Gibsone37ec7d2008-06-11 11:58:39 +1000223 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500224 | propdata DT_LABEL
225 {
David Gibsondc941772007-11-22 14:39:23 +1100226 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500227 }
David Gibson32da4752007-02-07 16:37:50 +1100228 ;
229
Jon Loeliger30807ca2007-10-18 09:42:16 -0500230propdataprefix:
Jon Loeliger56412892007-10-23 09:28:54 -0500231 /* empty */
232 {
233 $$ = empty_data;
234 }
235 | propdata ','
Jon Loeliger30807ca2007-10-18 09:42:16 -0500236 {
237 $$ = $1;
238 }
239 | propdataprefix DT_LABEL
240 {
David Gibsondc941772007-11-22 14:39:23 +1100241 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500242 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000243 ;
244
Jon Loeliger30807ca2007-10-18 09:42:16 -0500245celllist:
Jon Loeliger56412892007-10-23 09:28:54 -0500246 /* empty */
247 {
248 $$ = empty_data;
249 }
David Gibson9ed27a22007-11-07 11:16:19 +1100250 | celllist cellval
Jon Loeliger30807ca2007-10-18 09:42:16 -0500251 {
David Gibson9ed27a22007-11-07 11:16:19 +1100252 $$ = data_append_cell($1, $2);
Jon Loeligeraf0278a2007-02-15 10:59:27 -0600253 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500254 | celllist DT_REF
255 {
David Gibsondc941772007-11-22 14:39:23 +1100256 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
257 $2), -1);
David Gibson81f2e892005-06-16 17:04:00 +1000258 }
Jon Loeliger30807ca2007-10-18 09:42:16 -0500259 | celllist DT_LABEL
260 {
David Gibsondc941772007-11-22 14:39:23 +1100261 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500262 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000263 ;
264
David Gibson9ed27a22007-11-07 11:16:19 +1100265cellval:
David Gibson9138db52007-11-07 11:17:17 +1100266 DT_LITERAL
267 {
268 $$ = eval_literal($1, 0, 32);
269 }
Anton Staafa4ea2fa2011-09-09 12:16:30 -0700270 | DT_CHAR_LITERAL
271 {
272 $$ = eval_char_literal($1);
273 }
David Gibson9ed27a22007-11-07 11:16:19 +1100274 ;
275
Jon Loeliger30807ca2007-10-18 09:42:16 -0500276bytestring:
Jon Loeliger56412892007-10-23 09:28:54 -0500277 /* empty */
278 {
279 $$ = empty_data;
280 }
281 | bytestring DT_BYTE
Jon Loeliger30807ca2007-10-18 09:42:16 -0500282 {
283 $$ = data_append_byte($1, $2);
284 }
285 | bytestring DT_LABEL
286 {
David Gibsondc941772007-11-22 14:39:23 +1100287 $$ = data_add_marker($1, LABEL, $2);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500288 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000289 ;
290
Jon Loeliger30807ca2007-10-18 09:42:16 -0500291subnodes:
Jon Loeliger56412892007-10-23 09:28:54 -0500292 /* empty */
Jon Loeliger30807ca2007-10-18 09:42:16 -0500293 {
294 $$ = NULL;
295 }
David Gibson05898c62010-02-24 18:22:17 +1100296 | subnode subnodes
Jon Loeliger56412892007-10-23 09:28:54 -0500297 {
298 $$ = chain_node($1, $2);
299 }
David Gibsonc0481022007-12-05 10:27:04 +1100300 | subnode propdef
301 {
John Bonesioc0fa2e62010-10-20 14:44:58 -0700302 print_error("syntax error: properties must precede subnodes");
David Gibsonc0481022007-12-05 10:27:04 +1100303 YYERROR;
304 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000305 ;
306
Jon Loeliger30807ca2007-10-18 09:42:16 -0500307subnode:
David Gibson05898c62010-02-24 18:22:17 +1100308 DT_PROPNODENAME nodedef
Jon Loeliger30807ca2007-10-18 09:42:16 -0500309 {
David Gibson05898c62010-02-24 18:22:17 +1100310 $$ = name_node($2, $1);
Jon Loeliger30807ca2007-10-18 09:42:16 -0500311 }
David Gibson05898c62010-02-24 18:22:17 +1100312 | DT_LABEL subnode
Jon Loeliger30807ca2007-10-18 09:42:16 -0500313 {
David Gibson05898c62010-02-24 18:22:17 +1100314 add_label(&$2->labels, $1);
315 $$ = $2;
Jon Loeliger56412892007-10-23 09:28:54 -0500316 }
David Gibsonfc14dad2005-06-08 17:18:34 +1000317 ;
318
319%%
320
John Bonesioc0fa2e62010-10-20 14:44:58 -0700321void print_error(char const *fmt, ...)
David Gibsonfc14dad2005-06-08 17:18:34 +1000322{
John Bonesioc0fa2e62010-10-20 14:44:58 -0700323 va_list va;
324
325 va_start(va, fmt);
326 srcpos_verror(&yylloc, fmt, va);
327 va_end(va);
328
Scott Woodad4f54a2008-01-03 17:43:33 -0600329 treesource_error = 1;
David Gibsonfc14dad2005-06-08 17:18:34 +1000330}
Jon Loeliger39488492007-02-16 09:33:54 -0600331
John Bonesioc0fa2e62010-10-20 14:44:58 -0700332void yyerror(char const *s) {
333 print_error("%s", s);
334}
335
David Gibson6b8e0562008-03-05 11:47:54 +1100336static unsigned long long eval_literal(const char *s, int base, int bits)
Jon Loeliger39488492007-02-16 09:33:54 -0600337{
David Gibson9ed27a22007-11-07 11:16:19 +1100338 unsigned long long val;
Milton Miller85ab5cc2007-07-07 01:18:48 -0500339 char *e;
Jon Loeliger39488492007-02-16 09:33:54 -0600340
David Gibson9ed27a22007-11-07 11:16:19 +1100341 errno = 0;
342 val = strtoull(s, &e, base);
343 if (*e)
John Bonesioc0fa2e62010-10-20 14:44:58 -0700344 print_error("bad characters in literal");
David Gibson9ed27a22007-11-07 11:16:19 +1100345 else if ((errno == ERANGE)
346 || ((bits < 64) && (val >= (1ULL << bits))))
John Bonesioc0fa2e62010-10-20 14:44:58 -0700347 print_error("literal out of range");
David Gibson9ed27a22007-11-07 11:16:19 +1100348 else if (errno != 0)
John Bonesioc0fa2e62010-10-20 14:44:58 -0700349 print_error("bad literal");
David Gibson9ed27a22007-11-07 11:16:19 +1100350 return val;
Jon Loeliger39488492007-02-16 09:33:54 -0600351}
Anton Staafa4ea2fa2011-09-09 12:16:30 -0700352
353static unsigned char eval_char_literal(const char *s)
354{
355 int i = 1;
356 char c = s[0];
357
358 if (c == '\0')
359 {
360 print_error("empty character literal");
361 return 0;
362 }
363
364 /*
365 * If the first character in the character literal is a \ then process
366 * the remaining characters as an escape encoding. If the first
367 * character is neither an escape or a terminator it should be the only
368 * character in the literal and will be returned.
369 */
370 if (c == '\\')
371 c = get_escape_char(s, &i);
372
373 if (s[i] != '\0')
374 print_error("malformed character literal");
375
376 return c;
377}