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