Merge branch 'common/intc-extension' into sh-latest
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / scripts / dtc / dtc-parser.y
1 /*
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 %{
22 #include <stdio.h>
23
24 #include "dtc.h"
25 #include "srcpos.h"
26
27 YYLTYPE yylloc;
28
29 extern int yylex(void);
30 extern void print_error(char const *fmt, ...);
31 extern void yyerror(char const *s);
32
33 extern struct boot_info *the_boot_info;
34 extern int treesource_error;
35
36 static unsigned long long eval_literal(const char *s, int base, int bits);
37 %}
38
39 %union {
40 char *propnodename;
41 char *literal;
42 char *labelref;
43 unsigned int cbase;
44 uint8_t byte;
45 struct data data;
46
47 uint64_t addr;
48 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
60 %token <cbase> DT_BASE
61 %token <byte> DT_BYTE
62 %token <data> DT_STRING
63 %token <labelref> DT_LABEL
64 %token <labelref> DT_REF
65 %token DT_INCBIN
66
67 %type <data> propdata
68 %type <data> propdataprefix
69 %type <re> memreserve
70 %type <re> memreserves
71 %type <addr> addr
72 %type <data> celllist
73 %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
82
83 %%
84
85 sourcefile:
86 DT_V1 ';' memreserves devicetree
87 {
88 the_boot_info = build_boot_info($3, $4,
89 guess_boot_cpuid($4));
90 }
91 ;
92
93 memreserves:
94 /* empty */
95 {
96 $$ = NULL;
97 }
98 | memreserve memreserves
99 {
100 $$ = chain_reserve_entry($1, $2);
101 }
102 ;
103
104 memreserve:
105 DT_MEMRESERVE addr addr ';'
106 {
107 $$ = build_reserve_entry($2, $3);
108 }
109 | DT_LABEL memreserve
110 {
111 add_label(&$2->labels, $1);
112 $$ = $2;
113 }
114 ;
115
116 addr:
117 DT_LITERAL
118 {
119 $$ = eval_literal($1, 0, 64);
120 }
121 ;
122
123 devicetree:
124 '/' nodedef
125 {
126 $$ = 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;
141 }
142 ;
143
144 nodedef:
145 '{' proplist subnodes '}' ';'
146 {
147 $$ = build_node($2, $3);
148 }
149 ;
150
151 proplist:
152 /* empty */
153 {
154 $$ = NULL;
155 }
156 | proplist propdef
157 {
158 $$ = chain_property($2, $1);
159 }
160 ;
161
162 propdef:
163 DT_PROPNODENAME '=' propdata ';'
164 {
165 $$ = build_property($1, $3);
166 }
167 | DT_PROPNODENAME ';'
168 {
169 $$ = build_property($1, empty_data);
170 }
171 | DT_LABEL propdef
172 {
173 add_label(&$2->labels, $1);
174 $$ = $2;
175 }
176 ;
177
178 propdata:
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 }
195 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
196 {
197 FILE *f = srcfile_relative_open($4.val, NULL);
198 struct data d;
199
200 if ($6 != 0)
201 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));
206
207 d = data_copy_file(f, $8);
208
209 $$ = data_merge($1, d);
210 fclose(f);
211 }
212 | propdataprefix DT_INCBIN '(' DT_STRING ')'
213 {
214 FILE *f = srcfile_relative_open($4.val, NULL);
215 struct data d = empty_data;
216
217 d = data_copy_file(f, -1);
218
219 $$ = data_merge($1, d);
220 fclose(f);
221 }
222 | propdata DT_LABEL
223 {
224 $$ = data_add_marker($1, LABEL, $2);
225 }
226 ;
227
228 propdataprefix:
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
243 celllist:
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
263 cellval:
264 DT_LITERAL
265 {
266 $$ = eval_literal($1, 0, 32);
267 }
268 ;
269
270 bytestring:
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
285 subnodes:
286 /* empty */
287 {
288 $$ = NULL;
289 }
290 | subnode subnodes
291 {
292 $$ = chain_node($1, $2);
293 }
294 | subnode propdef
295 {
296 print_error("syntax error: properties must precede subnodes");
297 YYERROR;
298 }
299 ;
300
301 subnode:
302 DT_PROPNODENAME nodedef
303 {
304 $$ = name_node($2, $1);
305 }
306 | DT_LABEL subnode
307 {
308 add_label(&$2->labels, $1);
309 $$ = $2;
310 }
311 ;
312
313 %%
314
315 void print_error(char const *fmt, ...)
316 {
317 va_list va;
318
319 va_start(va, fmt);
320 srcpos_verror(&yylloc, fmt, va);
321 va_end(va);
322
323 treesource_error = 1;
324 }
325
326 void yyerror(char const *s) {
327 print_error("%s", s);
328 }
329
330 static unsigned long long eval_literal(const char *s, int base, int bits)
331 {
332 unsigned long long val;
333 char *e;
334
335 errno = 0;
336 val = strtoull(s, &e, base);
337 if (*e)
338 print_error("bad characters in literal");
339 else if ((errno == ERANGE)
340 || ((bits < 64) && (val >= (1ULL << bits))))
341 print_error("literal out of range");
342 else if (errno != 0)
343 print_error("bad literal");
344 return val;
345 }