1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (C) Copyright David Gibson <dwg@au1.ibm.com> 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", _ 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 static bool is_ref_relative(const char *ref) 28 { 29 return ref[0] != '/' && strchr(&ref[1] 30 } 31 32 %} 33 34 %union { 35 char *propnodename; 36 char *labelref; 37 uint8_t byte; 38 struct data data; 39 40 struct { 41 struct data data; 42 int bits; 43 } array; 44 45 struct property *prop; 46 struct property *proplist; 47 struct node *node; 48 struct node *nodelist; 49 struct reserve_info *re; 50 uint64_t integer; 51 unsigned int flags; 52 } 53 54 %token DT_V1 55 %token DT_PLUGIN 56 %token DT_MEMRESERVE 57 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ D 58 %token DT_BITS 59 %token DT_DEL_PROP 60 %token DT_DEL_NODE 61 %token DT_OMIT_NO_REF 62 %token <propnodename> DT_PROPNODENAME 63 %token <integer> DT_LITERAL 64 %token <integer> DT_CHAR_LITERAL 65 %token <byte> DT_BYTE 66 %token <data> DT_STRING 67 %token <labelref> DT_LABEL 68 %token <labelref> DT_LABEL_REF 69 %token <labelref> DT_PATH_REF 70 %token DT_INCBIN 71 72 %type <data> propdata 73 %type <data> propdataprefix 74 %type <flags> header 75 %type <flags> headers 76 %type <re> memreserve 77 %type <re> memreserves 78 %type <array> arrayprefix 79 %type <data> bytestring 80 %type <prop> propdef 81 %type <proplist> proplist 82 %type <labelref> dt_ref 83 84 %type <node> devicetree 85 %type <node> nodedef 86 %type <node> subnode 87 %type <nodelist> subnodes 88 89 %type <integer> integer_prim 90 %type <integer> integer_unary 91 %type <integer> integer_mul 92 %type <integer> integer_add 93 %type <integer> integer_shift 94 %type <integer> integer_rela 95 %type <integer> integer_eq 96 %type <integer> integer_bitand 97 %type <integer> integer_bitxor 98 %type <integer> integer_bitor 99 %type <integer> integer_and 100 %type <integer> integer_or 101 %type <integer> integer_trinary 102 %type <integer> integer_expr 103 104 %% 105 106 sourcefile: 107 headers memreserves devicetree 108 { 109 parser_output = build_ 110 111 } 112 ; 113 114 header: 115 DT_V1 ';' 116 { 117 $$ = DTSF_V1; 118 } 119 | DT_V1 ';' DT_PLUGIN ';' 120 { 121 $$ = DTSF_V1 | DTSF_PL 122 } 123 ; 124 125 headers: 126 header 127 | header headers 128 { 129 if ($2 != $1) 130 ERROR(&@2, "He 131 $$ = $1; 132 } 133 ; 134 135 memreserves: 136 /* empty */ 137 { 138 $$ = NULL; 139 } 140 | memreserve memreserves 141 { 142 $$ = chain_reserve_ent 143 } 144 ; 145 146 memreserve: 147 DT_MEMRESERVE integer_prim integer_p 148 { 149 $$ = build_reserve_ent 150 } 151 | DT_LABEL memreserve 152 { 153 add_label(&$2->labels, 154 $$ = $2; 155 } 156 ; 157 158 dt_ref: DT_LABEL_REF | DT_PATH_REF; 159 160 devicetree: 161 '/' nodedef 162 { 163 $$ = name_node($2, "") 164 } 165 | devicetree '/' nodedef 166 { 167 $$ = merge_nodes($1, $ 168 } 169 | dt_ref nodedef 170 { 171 /* 172 * We rely on the rule 173 * versioninfo plugi 174 * so $-1 is what we w 175 */ 176 if (!($<flags>-1 & DTS 177 ERROR(&@2, "La 178 else if (is_ref_relati 179 ERROR(&@2, "La 180 $$ = add_orphan_node( 181 name_n 182 183 $2, $1 184 } 185 | devicetree DT_LABEL dt_ref nodedef 186 { 187 struct node *target = 188 189 if (($<flags>-1 & DTSF 190 ERROR(&@2, "La 191 192 if (target) { 193 add_label(&tar 194 merge_nodes(ta 195 } else 196 ERROR(&@3, "La 197 $$ = $1; 198 } 199 | devicetree DT_PATH_REF nodedef 200 { 201 /* 202 * We rely on the rule 203 * versioninfo plugi 204 * so $-1 is what we w 205 */ 206 if ($<flags>-1 & DTSF_ 207 if (is_ref_rel 208 ERROR( 209 add_orphan_nod 210 } else { 211 struct node *t 212 213 if (target) 214 merge_ 215 else 216 ERROR( 217 } 218 $$ = $1; 219 } 220 | devicetree DT_LABEL_REF nodedef 221 { 222 struct node *target = 223 224 if (target) { 225 merge_nodes(ta 226 } else { 227 /* 228 * We rely on 229 * versionin 230 * so $-1 is w 231 */ 232 if ($<flags>-1 233 add_or 234 else 235 ERROR( 236 } 237 $$ = $1; 238 } 239 | devicetree DT_DEL_NODE dt_ref ';' 240 { 241 struct node *target = 242 243 if (target) 244 delete_node(ta 245 else 246 ERROR(&@3, "La 247 248 249 $$ = $1; 250 } 251 | devicetree DT_OMIT_NO_REF dt_ref ';' 252 { 253 struct node *target = 254 255 if (target) 256 omit_node_if_u 257 else 258 ERROR(&@3, "La 259 260 261 $$ = $1; 262 } 263 ; 264 265 nodedef: 266 '{' proplist subnodes '}' ';' 267 { 268 $$ = build_node($2, $3 269 } 270 ; 271 272 proplist: 273 /* empty */ 274 { 275 $$ = NULL; 276 } 277 | proplist propdef 278 { 279 $$ = chain_property($2 280 } 281 ; 282 283 propdef: 284 DT_PROPNODENAME '=' propdata ';' 285 { 286 $$ = build_property($1 287 free($1); 288 } 289 | DT_PROPNODENAME ';' 290 { 291 $$ = build_property($1 292 free($1); 293 } 294 | DT_DEL_PROP DT_PROPNODENAME ';' 295 { 296 $$ = build_property_de 297 free($2); 298 } 299 | DT_LABEL propdef 300 { 301 add_label(&$2->labels, 302 $$ = $2; 303 } 304 ; 305 306 propdata: 307 propdataprefix DT_STRING 308 { 309 $$ = data_merge($1, $2 310 } 311 | propdataprefix arrayprefix '>' 312 { 313 $$ = data_merge($1, $2 314 } 315 | propdataprefix '[' bytestring ']' 316 { 317 $$ = data_merge($1, $3 318 } 319 | propdataprefix dt_ref 320 { 321 $1 = data_add_marker($ 322 $$ = data_add_marker($ 323 } 324 | propdataprefix DT_INCBIN '(' DT_STRI 325 { 326 FILE *f = srcfile_rela 327 struct data d; 328 329 if ($6 != 0) 330 if (fseek(f, $ 331 die("C 332 (u 333 st 334 335 d = data_copy_file(f, 336 337 $$ = data_merge($1, d) 338 fclose(f); 339 } 340 | propdataprefix DT_INCBIN '(' DT_STRI 341 { 342 FILE *f = srcfile_rela 343 struct data d = empty_ 344 345 d = data_copy_file(f, 346 347 $$ = data_merge($1, d) 348 fclose(f); 349 } 350 | propdata DT_LABEL 351 { 352 $$ = data_add_marker($ 353 } 354 ; 355 356 propdataprefix: 357 /* empty */ 358 { 359 $$ = empty_data; 360 } 361 | propdata ',' 362 { 363 $$ = $1; 364 } 365 | propdataprefix DT_LABEL 366 { 367 $$ = data_add_marker($ 368 } 369 ; 370 371 arrayprefix: 372 DT_BITS DT_LITERAL '<' 373 { 374 unsigned long long bit 375 enum markertype type = 376 377 bits = $2; 378 379 switch (bits) { 380 case 8: type = TYPE_UI 381 case 16: type = TYPE_U 382 case 32: type = TYPE_U 383 case 64: type = TYPE_U 384 default: 385 ERROR(&@2, "Ar 386 " 8, 16, 387 bits = 32; 388 } 389 390 $$.data = data_add_mar 391 $$.bits = bits; 392 } 393 | '<' 394 { 395 $$.data = data_add_mar 396 $$.bits = 32; 397 } 398 | arrayprefix integer_prim 399 { 400 if ($1.bits < 64) { 401 uint64_t mask 402 /* 403 * Bits above 404 * (positive w 405 * (negative a 406 * condition i 407 * within the 408 * mask), all 409 */ 410 if (($2 > mask 411 char * 412 fprint 413 414 415 416 free(l 417 } 418 } 419 420 $$.data = data_append_ 421 } 422 | arrayprefix dt_ref 423 { 424 uint64_t val = ~0ULL > 425 426 if ($1.bits == 32) 427 $1.data = data 428 429 430 else 431 ERROR(&@2, "Re 432 "a 433 434 $$.data = data_append_ 435 } 436 | arrayprefix DT_LABEL 437 { 438 $$.data = data_add_mar 439 } 440 ; 441 442 integer_prim: 443 DT_LITERAL 444 | DT_CHAR_LITERAL 445 | '(' integer_expr ')' 446 { 447 $$ = $2; 448 } 449 ; 450 451 integer_expr: 452 integer_trinary 453 ; 454 455 integer_trinary: 456 integer_or 457 | integer_or '?' integer_expr ':' inte 458 ; 459 460 integer_or: 461 integer_and 462 | integer_or DT_OR integer_and { $$ = 463 ; 464 465 integer_and: 466 integer_bitor 467 | integer_and DT_AND integer_bitor { $ 468 ; 469 470 integer_bitor: 471 integer_bitxor 472 | integer_bitor '|' integer_bitxor { $ 473 ; 474 475 integer_bitxor: 476 integer_bitand 477 | integer_bitxor '^' integer_bitand { 478 ; 479 480 integer_bitand: 481 integer_eq 482 | integer_bitand '&' integer_eq { $$ = 483 ; 484 485 integer_eq: 486 integer_rela 487 | integer_eq DT_EQ integer_rela { $$ = 488 | integer_eq DT_NE integer_rela { $$ = 489 ; 490 491 integer_rela: 492 integer_shift 493 | integer_rela '<' integer_shift { $$ 494 | integer_rela '>' integer_shift { $$ 495 | integer_rela DT_LE integer_shift { $ 496 | integer_rela DT_GE integer_shift { $ 497 ; 498 499 integer_shift: 500 integer_shift DT_LSHIFT integer_add 501 | integer_shift DT_RSHIFT integer_add 502 | integer_add 503 ; 504 505 integer_add: 506 integer_add '+' integer_mul { $$ = $ 507 | integer_add '-' integer_mul { $$ = $ 508 | integer_mul 509 ; 510 511 integer_mul: 512 integer_mul '*' integer_unary { $$ = 513 | integer_mul '/' integer_unary 514 { 515 if ($3 != 0) { 516 $$ = $1 / $3; 517 } else { 518 ERROR(&@$, "Di 519 $$ = 0; 520 } 521 } 522 | integer_mul '%' integer_unary 523 { 524 if ($3 != 0) { 525 $$ = $1 % $3; 526 } else { 527 ERROR(&@$, "Di 528 $$ = 0; 529 } 530 } 531 | integer_unary 532 ; 533 534 integer_unary: 535 integer_prim 536 | '-' integer_unary { $$ = -$2; } 537 | '~' integer_unary { $$ = ~$2; } 538 | '!' integer_unary { $$ = !$2; } 539 ; 540 541 bytestring: 542 /* empty */ 543 { 544 $$ = data_add_marker(e 545 } 546 | bytestring DT_BYTE 547 { 548 $$ = data_append_byte( 549 } 550 | bytestring DT_LABEL 551 { 552 $$ = data_add_marker($ 553 } 554 ; 555 556 subnodes: 557 /* empty */ 558 { 559 $$ = NULL; 560 } 561 | subnode subnodes 562 { 563 $$ = chain_node($1, $2 564 } 565 | subnode propdef 566 { 567 ERROR(&@2, "Properties 568 YYERROR; 569 } 570 ; 571 572 subnode: 573 DT_PROPNODENAME nodedef 574 { 575 $$ = name_node($2, $1) 576 free($1); 577 } 578 | DT_DEL_NODE DT_PROPNODENAME ';' 579 { 580 $$ = name_node(build_n 581 free($2); 582 } 583 | DT_OMIT_NO_REF subnode 584 { 585 $$ = omit_node_if_unus 586 } 587 | DT_LABEL subnode 588 { 589 add_label(&$2->labels, 590 $$ = $2; 591 } 592 ; 593 594 %% 595 596 void yyerror(char const *s) 597 { 598 ERROR(&yylloc, "%s", s); 599 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.