1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 4 */ 5 %locations 6 7 %{ 8 #include <stdio.h> 9 #include <inttypes.h> 10 11 #include "dtc.h" 12 #include "srcpos.h" 13 14 extern int yylex(void); 15 extern void yyerror(char const *s); 16 #define ERROR(loc, ...) \ 17 do { \ 18 srcpos_error((loc), "Error", __VA_ARGS__); \ 19 treesource_error = true; \ 20 } while (0) 21 22 #define YYERROR_CALL(msg) yyerror(msg) 23 24 extern struct dt_info *parser_output; 25 extern bool treesource_error; 26 %} 27 28 %union { 29 char *propnodename; 30 char *labelref; 31 uint8_t byte; 32 struct data data; 33 34 struct { 35 struct data data; 36 int bits; 37 } array; 38 39 struct property *prop; 40 struct property *proplist; 41 struct node *node; 42 struct node *nodelist; 43 struct reserve_info *re; 44 uint64_t integer; 45 unsigned int flags; 46 } 47 48 %token DT_V1 49 %token DT_PLUGIN 50 %token DT_MEMRESERVE 51 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR 52 %token DT_BITS 53 %token DT_DEL_PROP 54 %token DT_DEL_NODE 55 %token DT_OMIT_NO_REF 56 %token <propnodename> DT_PROPNODENAME 57 %token <integer> DT_LITERAL 58 %token <integer> DT_CHAR_LITERAL 59 %token <byte> DT_BYTE 60 %token <data> DT_STRING 61 %token <labelref> DT_LABEL 62 %token <labelref> DT_LABEL_REF 63 %token <labelref> DT_PATH_REF 64 %token DT_INCBIN 65 66 %type <data> propdata 67 %type <data> propdataprefix 68 %type <flags> header 69 %type <flags> headers 70 %type <re> memreserve 71 %type <re> memreserves 72 %type <array> arrayprefix 73 %type <data> bytestring 74 %type <prop> propdef 75 %type <proplist> proplist 76 %type <labelref> dt_ref 77 78 %type <node> devicetree 79 %type <node> nodedef 80 %type <node> subnode 81 %type <nodelist> subnodes 82 83 %type <integer> integer_prim 84 %type <integer> integer_unary 85 %type <integer> integer_mul 86 %type <integer> integer_add 87 %type <integer> integer_shift 88 %type <integer> integer_rela 89 %type <integer> integer_eq 90 %type <integer> integer_bitand 91 %type <integer> integer_bitxor 92 %type <integer> integer_bitor 93 %type <integer> integer_and 94 %type <integer> integer_or 95 %type <integer> integer_trinary 96 %type <integer> integer_expr 97 98 %% 99 100 sourcefile: 101 headers memreserves devicetree 102 { 103 parser_output = build_dt_info($1, $2, $3, 104 guess_boot_cpuid($3)); 105 } 106 ; 107 108 header: 109 DT_V1 ';' 110 { 111 $$ = DTSF_V1; 112 } 113 | DT_V1 ';' DT_PLUGIN ';' 114 { 115 $$ = DTSF_V1 | DTSF_PLUGIN; 116 } 117 ; 118 119 headers: 120 header 121 | header headers 122 { 123 if ($2 != $1) 124 ERROR(&@2, "Header flags don't match earlier ones"); 125 $$ = $1; 126 } 127 ; 128 129 memreserves: 130 /* empty */ 131 { 132 $$ = NULL; 133 } 134 | memreserve memreserves 135 { 136 $$ = chain_reserve_entry($1, $2); 137 } 138 ; 139 140 memreserve: 141 DT_MEMRESERVE integer_prim integer_prim ';' 142 { 143 $$ = build_reserve_entry($2, $3); 144 } 145 | DT_LABEL memreserve 146 { 147 add_label(&$2->labels, $1); 148 $$ = $2; 149 } 150 ; 151 152 dt_ref: DT_LABEL_REF | DT_PATH_REF; 153 154 devicetree: 155 '/' nodedef 156 { 157 $$ = name_node($2, ""); 158 } 159 | devicetree '/' nodedef 160 { 161 $$ = merge_nodes($1, $3); 162 } 163 | dt_ref nodedef 164 { 165 /* 166 * We rely on the rule being always: 167 * versioninfo plugindecl memreserves devicetree 168 * so $-1 is what we want (plugindecl) 169 */ 170 if (!($<flags>-1 & DTSF_PLUGIN)) 171 ERROR(&@2, "Label or path %s not found", $1); 172 $$ = add_orphan_node( 173 name_node(build_node(NULL, NULL, NULL), 174 ""), 175 $2, $1); 176 } 177 | devicetree DT_LABEL dt_ref nodedef 178 { 179 struct node *target = get_node_by_ref($1, $3); 180 181 if (target) { 182 add_label(&target->labels, $2); 183 merge_nodes(target, $4); 184 } else 185 ERROR(&@3, "Label or path %s not found", $3); 186 $$ = $1; 187 } 188 | devicetree DT_PATH_REF nodedef 189 { 190 /* 191 * We rely on the rule being always: 192 * versioninfo plugindecl memreserves devicetree 193 * so $-1 is what we want (plugindecl) 194 */ 195 if ($<flags>-1 & DTSF_PLUGIN) { 196 add_orphan_node($1, $3, $2); 197 } else { 198 struct node *target = get_node_by_ref($1, $2); 199 200 if (target) 201 merge_nodes(target, $3); 202 else 203 ERROR(&@2, "Label or path %s not found", $2); 204 } 205 $$ = $1; 206 } 207 | devicetree DT_LABEL_REF nodedef 208 { 209 struct node *target = get_node_by_ref($1, $2); 210 211 if (target) { 212 merge_nodes(target, $3); 213 } else { 214 /* 215 * We rely on the rule being always: 216 * versioninfo plugindecl memreserves devicetree 217 * so $-1 is what we want (plugindecl) 218 */ 219 if ($<flags>-1 & DTSF_PLUGIN) 220 add_orphan_node($1, $3, $2); 221 else 222 ERROR(&@2, "Label or path %s not found", $2); 223 } 224 $$ = $1; 225 } 226 | devicetree DT_DEL_NODE dt_ref ';' 227 { 228 struct node *target = get_node_by_ref($1, $3); 229 230 if (target) 231 delete_node(target); 232 else 233 ERROR(&@3, "Label or path %s not found", $3); 234 235 236 $$ = $1; 237 } 238 | devicetree DT_OMIT_NO_REF dt_ref ';' 239 { 240 struct node *target = get_node_by_ref($1, $3); 241 242 if (target) 243 omit_node_if_unused(target); 244 else 245 ERROR(&@3, "Label or path %s not found", $3); 246 247 248 $$ = $1; 249 } 250 ; 251 252 nodedef: 253 '{' proplist subnodes '}' ';' 254 { 255 $$ = build_node($2, $3, &@$); 256 } 257 ; 258 259 proplist: 260 /* empty */ 261 { 262 $$ = NULL; 263 } 264 | proplist propdef 265 { 266 $$ = chain_property($2, $1); 267 } 268 ; 269 270 propdef: 271 DT_PROPNODENAME '=' propdata ';' 272 { 273 $$ = build_property($1, $3, &@$); 274 } 275 | DT_PROPNODENAME ';' 276 { 277 $$ = build_property($1, empty_data, &@$); 278 } 279 | DT_DEL_PROP DT_PROPNODENAME ';' 280 { 281 $$ = build_property_delete($2); 282 } 283 | DT_LABEL propdef 284 { 285 add_label(&$2->labels, $1); 286 $$ = $2; 287 } 288 ; 289 290 propdata: 291 propdataprefix DT_STRING 292 { 293 $$ = data_merge($1, $2); 294 } 295 | propdataprefix arrayprefix '>' 296 { 297 $$ = data_merge($1, $2.data); 298 } 299 | propdataprefix '[' bytestring ']' 300 { 301 $$ = data_merge($1, $3); 302 } 303 | propdataprefix dt_ref 304 { 305 $1 = data_add_marker($1, TYPE_STRING, $2); 306 $$ = data_add_marker($1, REF_PATH, $2); 307 } 308 | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' 309 { 310 FILE *f = srcfile_relative_open($4.val, NULL); 311 struct data d; 312 313 if ($6 != 0) 314 if (fseek(f, $6, SEEK_SET) != 0) 315 die("Couldn't seek to offset %llu in \"%s\": %s", 316 (unsigned long long)$6, $4.val, 317 strerror(errno)); 318 319 d = data_copy_file(f, $8); 320 321 $$ = data_merge($1, d); 322 fclose(f); 323 } 324 | propdataprefix DT_INCBIN '(' DT_STRING ')' 325 { 326 FILE *f = srcfile_relative_open($4.val, NULL); 327 struct data d = empty_data; 328 329 d = data_copy_file(f, -1); 330 331 $$ = data_merge($1, d); 332 fclose(f); 333 } 334 | propdata DT_LABEL 335 { 336 $$ = data_add_marker($1, LABEL, $2); 337 } 338 ; 339 340 propdataprefix: 341 /* empty */ 342 { 343 $$ = empty_data; 344 } 345 | propdata ',' 346 { 347 $$ = $1; 348 } 349 | propdataprefix DT_LABEL 350 { 351 $$ = data_add_marker($1, LABEL, $2); 352 } 353 ; 354 355 arrayprefix: 356 DT_BITS DT_LITERAL '<' 357 { 358 unsigned long long bits; 359 enum markertype type = TYPE_UINT32; 360 361 bits = $2; 362 363 switch (bits) { 364 case 8: type = TYPE_UINT8; break; 365 case 16: type = TYPE_UINT16; break; 366 case 32: type = TYPE_UINT32; break; 367 case 64: type = TYPE_UINT64; break; 368 default: 369 ERROR(&@2, "Array elements must be" 370 " 8, 16, 32 or 64-bits"); 371 bits = 32; 372 } 373 374 $$.data = data_add_marker(empty_data, type, NULL); 375 $$.bits = bits; 376 } 377 | '<' 378 { 379 $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL); 380 $$.bits = 32; 381 } 382 | arrayprefix integer_prim 383 { 384 if ($1.bits < 64) { 385 uint64_t mask = (1ULL << $1.bits) - 1; 386 /* 387 * Bits above mask must either be all zero 388 * (positive within range of mask) or all one 389 * (negative and sign-extended). The second 390 * condition is true if when we set all bits 391 * within the mask to one (i.e. | in the 392 * mask), all bits are one. 393 */ 394 if (($2 > mask) && (($2 | mask) != -1ULL)) 395 ERROR(&@2, "Value out of range for" 396 " %d-bit array element", $1.bits); 397 } 398 399 $$.data = data_append_integer($1.data, $2, $1.bits); 400 } 401 | arrayprefix dt_ref 402 { 403 uint64_t val = ~0ULL >> (64 - $1.bits); 404 405 if ($1.bits == 32) 406 $1.data = data_add_marker($1.data, 407 REF_PHANDLE, 408 $2); 409 else 410 ERROR(&@2, "References are only allowed in " 411 "arrays with 32-bit elements."); 412 413 $$.data = data_append_integer($1.data, val, $1.bits); 414 } 415 | arrayprefix DT_LABEL 416 { 417 $$.data = data_add_marker($1.data, LABEL, $2); 418 } 419 ; 420 421 integer_prim: 422 DT_LITERAL 423 | DT_CHAR_LITERAL 424 | '(' integer_expr ')' 425 { 426 $$ = $2; 427 } 428 ; 429 430 integer_expr: 431 integer_trinary 432 ; 433 434 integer_trinary: 435 integer_or 436 | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } 437 ; 438 439 integer_or: 440 integer_and 441 | integer_or DT_OR integer_and { $$ = $1 || $3; } 442 ; 443 444 integer_and: 445 integer_bitor 446 | integer_and DT_AND integer_bitor { $$ = $1 && $3; } 447 ; 448 449 integer_bitor: 450 integer_bitxor 451 | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } 452 ; 453 454 integer_bitxor: 455 integer_bitand 456 | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } 457 ; 458 459 integer_bitand: 460 integer_eq 461 | integer_bitand '&' integer_eq { $$ = $1 & $3; } 462 ; 463 464 integer_eq: 465 integer_rela 466 | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } 467 | integer_eq DT_NE integer_rela { $$ = $1 != $3; } 468 ; 469 470 integer_rela: 471 integer_shift 472 | integer_rela '<' integer_shift { $$ = $1 < $3; } 473 | integer_rela '>' integer_shift { $$ = $1 > $3; } 474 | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } 475 | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } 476 ; 477 478 integer_shift: 479 integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } 480 | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } 481 | integer_add 482 ; 483 484 integer_add: 485 integer_add '+' integer_mul { $$ = $1 + $3; } 486 | integer_add '-' integer_mul { $$ = $1 - $3; } 487 | integer_mul 488 ; 489 490 integer_mul: 491 integer_mul '*' integer_unary { $$ = $1 * $3; } 492 | integer_mul '/' integer_unary 493 { 494 if ($3 != 0) { 495 $$ = $1 / $3; 496 } else { 497 ERROR(&@$, "Division by zero"); 498 $$ = 0; 499 } 500 } 501 | integer_mul '%' integer_unary 502 { 503 if ($3 != 0) { 504 $$ = $1 % $3; 505 } else { 506 ERROR(&@$, "Division by zero"); 507 $$ = 0; 508 } 509 } 510 | integer_unary 511 ; 512 513 integer_unary: 514 integer_prim 515 | '-' integer_unary { $$ = -$2; } 516 | '~' integer_unary { $$ = ~$2; } 517 | '!' integer_unary { $$ = !$2; } 518 ; 519 520 bytestring: 521 /* empty */ 522 { 523 $$ = data_add_marker(empty_data, TYPE_UINT8, NULL); 524 } 525 | bytestring DT_BYTE 526 { 527 $$ = data_append_byte($1, $2); 528 } 529 | bytestring DT_LABEL 530 { 531 $$ = data_add_marker($1, LABEL, $2); 532 } 533 ; 534 535 subnodes: 536 /* empty */ 537 { 538 $$ = NULL; 539 } 540 | subnode subnodes 541 { 542 $$ = chain_node($1, $2); 543 } 544 | subnode propdef 545 { 546 ERROR(&@2, "Properties must precede subnodes"); 547 YYERROR; 548 } 549 ; 550 551 subnode: 552 DT_PROPNODENAME nodedef 553 { 554 $$ = name_node($2, $1); 555 } 556 | DT_DEL_NODE DT_PROPNODENAME ';' 557 { 558 $$ = name_node(build_node_delete(&@$), $2); 559 } 560 | DT_OMIT_NO_REF subnode 561 { 562 $$ = omit_node_if_unused($2); 563 } 564 | DT_LABEL subnode 565 { 566 add_label(&$2->labels, $1); 567 $$ = $2; 568 } 569 ; 570 571 %% 572 573 void yyerror(char const *s) 574 { 575 ERROR(&yylloc, "%s", s); 576 } 577