dtc-parser.y revision 302408
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 27YYLTYPE yylloc; 28 29extern int yylex(void); 30extern void print_error(char const *fmt, ...); 31extern void yyerror(char const *s); 32 33extern struct boot_info *the_boot_info; 34extern bool treesource_error; 35%} 36 37%union { 38 char *propnodename; 39 char *labelref; 40 unsigned int cbase; 41 uint8_t byte; 42 struct data data; 43 44 struct { 45 struct data data; 46 int bits; 47 } array; 48 49 struct property *prop; 50 struct property *proplist; 51 struct node *node; 52 struct node *nodelist; 53 struct reserve_info *re; 54 uint64_t integer; 55} 56 57%token DT_V1 58%token DT_MEMRESERVE 59%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR 60%token DT_BITS 61%token DT_DEL_PROP 62%token DT_DEL_NODE 63%token <propnodename> DT_PROPNODENAME 64%token <integer> DT_LITERAL 65%token <integer> DT_CHAR_LITERAL 66%token <cbase> DT_BASE 67%token <byte> DT_BYTE 68%token <data> DT_STRING 69%token <labelref> DT_LABEL 70%token <labelref> DT_REF 71%token DT_INCBIN 72 73%type <data> propdata 74%type <data> propdataprefix 75%type <re> memreserve 76%type <re> memreserves 77%type <array> arrayprefix 78%type <data> bytestring 79%type <prop> propdef 80%type <proplist> proplist 81 82%type <node> devicetree 83%type <node> nodedef 84%type <node> subnode 85%type <nodelist> subnodes 86 87%type <integer> integer_prim 88%type <integer> integer_unary 89%type <integer> integer_mul 90%type <integer> integer_add 91%type <integer> integer_shift 92%type <integer> integer_rela 93%type <integer> integer_eq 94%type <integer> integer_bitand 95%type <integer> integer_bitxor 96%type <integer> integer_bitor 97%type <integer> integer_and 98%type <integer> integer_or 99%type <integer> integer_trinary 100%type <integer> integer_expr 101 102%% 103 104sourcefile: 105 DT_V1 ';' memreserves devicetree 106 { 107 the_boot_info = build_boot_info($3, $4, 108 guess_boot_cpuid($4)); 109 } 110 ; 111 112memreserves: 113 /* empty */ 114 { 115 $$ = NULL; 116 } 117 | memreserve memreserves 118 { 119 $$ = chain_reserve_entry($1, $2); 120 } 121 ; 122 123memreserve: 124 DT_MEMRESERVE integer_prim integer_prim ';' 125 { 126 $$ = build_reserve_entry($2, $3); 127 } 128 | DT_LABEL memreserve 129 { 130 add_label(&$2->labels, $1); 131 $$ = $2; 132 } 133 ; 134 135devicetree: 136 '/' nodedef 137 { 138 $$ = name_node($2, ""); 139 } 140 | devicetree '/' nodedef 141 { 142 $$ = merge_nodes($1, $3); 143 } 144 | devicetree DT_REF nodedef 145 { 146 struct node *target = get_node_by_ref($1, $2); 147 148 if (target) 149 merge_nodes(target, $3); 150 else 151 print_error("label or path, '%s', not found", $2); 152 $$ = $1; 153 } 154 | devicetree DT_DEL_NODE DT_REF ';' 155 { 156 struct node *target = get_node_by_ref($1, $3); 157 158 if (!target) 159 print_error("label or path, '%s', not found", $3); 160 else 161 delete_node(target); 162 163 $$ = $1; 164 } 165 ; 166 167nodedef: 168 '{' proplist subnodes '}' ';' 169 { 170 $$ = build_node($2, $3); 171 } 172 ; 173 174proplist: 175 /* empty */ 176 { 177 $$ = NULL; 178 } 179 | proplist propdef 180 { 181 $$ = chain_property($2, $1); 182 } 183 ; 184 185propdef: 186 DT_PROPNODENAME '=' propdata ';' 187 { 188 $$ = build_property($1, $3); 189 } 190 | DT_PROPNODENAME ';' 191 { 192 $$ = build_property($1, empty_data); 193 } 194 | DT_DEL_PROP DT_PROPNODENAME ';' 195 { 196 $$ = build_property_delete($2); 197 } 198 | DT_LABEL propdef 199 { 200 add_label(&$2->labels, $1); 201 $$ = $2; 202 } 203 ; 204 205propdata: 206 propdataprefix DT_STRING 207 { 208 $$ = data_merge($1, $2); 209 } 210 | propdataprefix arrayprefix '>' 211 { 212 $$ = data_merge($1, $2.data); 213 } 214 | propdataprefix '[' bytestring ']' 215 { 216 $$ = data_merge($1, $3); 217 } 218 | propdataprefix DT_REF 219 { 220 $$ = data_add_marker($1, REF_PATH, $2); 221 } 222 | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' 223 { 224 FILE *f = srcfile_relative_open($4.val, NULL); 225 struct data d; 226 227 if ($6 != 0) 228 if (fseek(f, $6, SEEK_SET) != 0) 229 die("Couldn't seek to offset %llu in \"%s\": %s", 230 (unsigned long long)$6, $4.val, 231 strerror(errno)); 232 233 d = data_copy_file(f, $8); 234 235 $$ = data_merge($1, d); 236 fclose(f); 237 } 238 | propdataprefix DT_INCBIN '(' DT_STRING ')' 239 { 240 FILE *f = srcfile_relative_open($4.val, NULL); 241 struct data d = empty_data; 242 243 d = data_copy_file(f, -1); 244 245 $$ = data_merge($1, d); 246 fclose(f); 247 } 248 | propdata DT_LABEL 249 { 250 $$ = data_add_marker($1, LABEL, $2); 251 } 252 ; 253 254propdataprefix: 255 /* empty */ 256 { 257 $$ = empty_data; 258 } 259 | propdata ',' 260 { 261 $$ = $1; 262 } 263 | propdataprefix DT_LABEL 264 { 265 $$ = data_add_marker($1, LABEL, $2); 266 } 267 ; 268 269arrayprefix: 270 DT_BITS DT_LITERAL '<' 271 { 272 unsigned long long bits; 273 274 bits = $2; 275 276 if ((bits != 8) && (bits != 16) && 277 (bits != 32) && (bits != 64)) 278 { 279 print_error("Only 8, 16, 32 and 64-bit elements" 280 " are currently supported"); 281 bits = 32; 282 } 283 284 $$.data = empty_data; 285 $$.bits = bits; 286 } 287 | '<' 288 { 289 $$.data = empty_data; 290 $$.bits = 32; 291 } 292 | arrayprefix integer_prim 293 { 294 if ($1.bits < 64) { 295 uint64_t mask = (1ULL << $1.bits) - 1; 296 /* 297 * Bits above mask must either be all zero 298 * (positive within range of mask) or all one 299 * (negative and sign-extended). The second 300 * condition is true if when we set all bits 301 * within the mask to one (i.e. | in the 302 * mask), all bits are one. 303 */ 304 if (($2 > mask) && (($2 | mask) != -1ULL)) 305 print_error( 306 "integer value out of range " 307 "%016lx (%d bits)", $1.bits); 308 } 309 310 $$.data = data_append_integer($1.data, $2, $1.bits); 311 } 312 | arrayprefix DT_REF 313 { 314 uint64_t val = ~0ULL >> (64 - $1.bits); 315 316 if ($1.bits == 32) 317 $1.data = data_add_marker($1.data, 318 REF_PHANDLE, 319 $2); 320 else 321 print_error("References are only allowed in " 322 "arrays with 32-bit elements."); 323 324 $$.data = data_append_integer($1.data, val, $1.bits); 325 } 326 | arrayprefix DT_LABEL 327 { 328 $$.data = data_add_marker($1.data, LABEL, $2); 329 } 330 ; 331 332integer_prim: 333 DT_LITERAL 334 | DT_CHAR_LITERAL 335 | '(' integer_expr ')' 336 { 337 $$ = $2; 338 } 339 ; 340 341integer_expr: 342 integer_trinary 343 ; 344 345integer_trinary: 346 integer_or 347 | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } 348 ; 349 350integer_or: 351 integer_and 352 | integer_or DT_OR integer_and { $$ = $1 || $3; } 353 ; 354 355integer_and: 356 integer_bitor 357 | integer_and DT_AND integer_bitor { $$ = $1 && $3; } 358 ; 359 360integer_bitor: 361 integer_bitxor 362 | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } 363 ; 364 365integer_bitxor: 366 integer_bitand 367 | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } 368 ; 369 370integer_bitand: 371 integer_eq 372 | integer_bitand '&' integer_eq { $$ = $1 & $3; } 373 ; 374 375integer_eq: 376 integer_rela 377 | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } 378 | integer_eq DT_NE integer_rela { $$ = $1 != $3; } 379 ; 380 381integer_rela: 382 integer_shift 383 | integer_rela '<' integer_shift { $$ = $1 < $3; } 384 | integer_rela '>' integer_shift { $$ = $1 > $3; } 385 | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } 386 | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } 387 ; 388 389integer_shift: 390 integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } 391 | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } 392 | integer_add 393 ; 394 395integer_add: 396 integer_add '+' integer_mul { $$ = $1 + $3; } 397 | integer_add '-' integer_mul { $$ = $1 - $3; } 398 | integer_mul 399 ; 400 401integer_mul: 402 integer_mul '*' integer_unary { $$ = $1 * $3; } 403 | integer_mul '/' integer_unary { $$ = $1 / $3; } 404 | integer_mul '%' integer_unary { $$ = $1 % $3; } 405 | integer_unary 406 ; 407 408integer_unary: 409 integer_prim 410 | '-' integer_unary { $$ = -$2; } 411 | '~' integer_unary { $$ = ~$2; } 412 | '!' integer_unary { $$ = !$2; } 413 ; 414 415bytestring: 416 /* empty */ 417 { 418 $$ = empty_data; 419 } 420 | bytestring DT_BYTE 421 { 422 $$ = data_append_byte($1, $2); 423 } 424 | bytestring DT_LABEL 425 { 426 $$ = data_add_marker($1, LABEL, $2); 427 } 428 ; 429 430subnodes: 431 /* empty */ 432 { 433 $$ = NULL; 434 } 435 | subnode subnodes 436 { 437 $$ = chain_node($1, $2); 438 } 439 | subnode propdef 440 { 441 print_error("syntax error: properties must precede subnodes"); 442 YYERROR; 443 } 444 ; 445 446subnode: 447 DT_PROPNODENAME nodedef 448 { 449 $$ = name_node($2, $1); 450 } 451 | DT_DEL_NODE DT_PROPNODENAME ';' 452 { 453 $$ = name_node(build_node_delete(), $2); 454 } 455 | DT_LABEL subnode 456 { 457 add_label(&$2->labels, $1); 458 $$ = $2; 459 } 460 ; 461 462%% 463 464void print_error(char const *fmt, ...) 465{ 466 va_list va; 467 468 va_start(va, fmt); 469 srcpos_verror(&yylloc, "Error", fmt, va); 470 va_end(va); 471 472 treesource_error = true; 473} 474 475void yyerror(char const *s) { 476 print_error("%s", s); 477} 478