1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * (C) Copyright David Gibson <dwg@au1.ibm.com> 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 4 */ 19 */ >> 20 5 %locations 21 %locations 6 22 7 %{ 23 %{ 8 #include <stdio.h> 24 #include <stdio.h> 9 #include <inttypes.h> << 10 25 11 #include "dtc.h" 26 #include "dtc.h" 12 #include "srcpos.h" 27 #include "srcpos.h" 13 28 14 extern int yylex(void); 29 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 30 24 extern struct dt_info *parser_output; !! 31 extern struct boot_info *the_boot_info; 25 extern bool treesource_error; !! 32 extern int treesource_error; 26 << 27 static bool is_ref_relative(const char *ref) << 28 { << 29 return ref[0] != '/' && strchr(&ref[1] << 30 } << 31 33 >> 34 static unsigned long long eval_literal(const char *s, int base, int bits); 32 %} 35 %} 33 36 34 %union { 37 %union { 35 char *propnodename; 38 char *propnodename; >> 39 char *literal; 36 char *labelref; 40 char *labelref; >> 41 unsigned int cbase; 37 uint8_t byte; 42 uint8_t byte; 38 struct data data; 43 struct data data; 39 44 40 struct { !! 45 uint64_t addr; 41 struct data data; !! 46 cell_t cell; 42 int bits; << 43 } array; << 44 << 45 struct property *prop; 47 struct property *prop; 46 struct property *proplist; 48 struct property *proplist; 47 struct node *node; 49 struct node *node; 48 struct node *nodelist; 50 struct node *nodelist; 49 struct reserve_info *re; 51 struct reserve_info *re; 50 uint64_t integer; << 51 unsigned int flags; << 52 } 52 } 53 53 54 %token DT_V1 54 %token DT_V1 55 %token DT_PLUGIN << 56 %token DT_MEMRESERVE 55 %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 56 %token <propnodename> DT_PROPNODENAME 63 %token <integer> DT_LITERAL !! 57 %token <literal> DT_LITERAL 64 %token <integer> DT_CHAR_LITERAL !! 58 %token <literal> DT_LEGACYLITERAL >> 59 %token <cbase> DT_BASE 65 %token <byte> DT_BYTE 60 %token <byte> DT_BYTE 66 %token <data> DT_STRING 61 %token <data> DT_STRING 67 %token <labelref> DT_LABEL 62 %token <labelref> DT_LABEL 68 %token <labelref> DT_LABEL_REF !! 63 %token <labelref> DT_REF 69 %token <labelref> DT_PATH_REF << 70 %token DT_INCBIN 64 %token DT_INCBIN 71 65 72 %type <data> propdata 66 %type <data> propdata 73 %type <data> propdataprefix 67 %type <data> propdataprefix 74 %type <flags> header << 75 %type <flags> headers << 76 %type <re> memreserve 68 %type <re> memreserve 77 %type <re> memreserves 69 %type <re> memreserves 78 %type <array> arrayprefix !! 70 %type <re> v0_memreserve >> 71 %type <re> v0_memreserves >> 72 %type <addr> addr >> 73 %type <data> celllist >> 74 %type <cbase> cellbase >> 75 %type <cell> cellval 79 %type <data> bytestring 76 %type <data> bytestring 80 %type <prop> propdef 77 %type <prop> propdef 81 %type <proplist> proplist 78 %type <proplist> proplist 82 %type <labelref> dt_ref << 83 79 84 %type <node> devicetree 80 %type <node> devicetree 85 %type <node> nodedef 81 %type <node> nodedef 86 %type <node> subnode 82 %type <node> subnode 87 %type <nodelist> subnodes 83 %type <nodelist> subnodes 88 !! 84 %type <labelref> label 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 85 104 %% 86 %% 105 87 106 sourcefile: 88 sourcefile: 107 headers memreserves devicetree !! 89 DT_V1 ';' 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 { 90 { 121 $$ = DTSF_V1 | DTSF_PL !! 91 the_boot_info = build_boot_info($3, $4, 0); 122 } 92 } 123 ; !! 93 | v0_memreserves devicetree 124 << 125 headers: << 126 header << 127 | header headers << 128 { 94 { 129 if ($2 != $1) !! 95 the_boot_info = build_boot_info($1, $2, 0); 130 ERROR(&@2, "He << 131 $$ = $1; << 132 } 96 } 133 ; 97 ; 134 98 135 memreserves: 99 memreserves: 136 /* empty */ 100 /* empty */ 137 { 101 { 138 $$ = NULL; 102 $$ = NULL; 139 } 103 } 140 | memreserve memreserves 104 | memreserve memreserves 141 { 105 { 142 $$ = chain_reserve_ent 106 $$ = chain_reserve_entry($1, $2); 143 } 107 } 144 ; 108 ; 145 109 146 memreserve: 110 memreserve: 147 DT_MEMRESERVE integer_prim integer_p !! 111 label DT_MEMRESERVE addr addr ';' 148 { 112 { 149 $$ = build_reserve_ent !! 113 $$ = build_reserve_entry($3, $4, $1); 150 } << 151 | DT_LABEL memreserve << 152 { << 153 add_label(&$2->labels, << 154 $$ = $2; << 155 } 114 } 156 ; 115 ; 157 116 158 dt_ref: DT_LABEL_REF | DT_PATH_REF; !! 117 v0_memreserves: 159 !! 118 /* empty */ 160 devicetree: << 161 '/' nodedef << 162 { 119 { 163 $$ = name_node($2, "") !! 120 $$ = NULL; 164 } 121 } 165 | devicetree '/' nodedef !! 122 | v0_memreserve v0_memreserves 166 { 123 { 167 $$ = merge_nodes($1, $ !! 124 $$ = chain_reserve_entry($1, $2); 168 } !! 125 }; 169 | dt_ref nodedef !! 126 ; >> 127 >> 128 v0_memreserve: >> 129 memreserve 170 { 130 { 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; 131 $$ = $1; 198 } 132 } 199 | devicetree DT_PATH_REF nodedef !! 133 | label DT_MEMRESERVE addr '-' addr ';' 200 { 134 { 201 /* !! 135 $$ = build_reserve_entry($3, $5 - $3 + 1, $1); 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 } 136 } 220 | devicetree DT_LABEL_REF nodedef !! 137 ; 221 { << 222 struct node *target = << 223 138 224 if (target) { !! 139 addr: 225 merge_nodes(ta !! 140 DT_LITERAL 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 { 141 { 241 struct node *target = !! 142 $$ = eval_literal($1, 0, 64); 242 << 243 if (target) << 244 delete_node(ta << 245 else << 246 ERROR(&@3, "La << 247 << 248 << 249 $$ = $1; << 250 } 143 } 251 | devicetree DT_OMIT_NO_REF dt_ref ';' !! 144 | DT_LEGACYLITERAL 252 { 145 { 253 struct node *target = !! 146 $$ = eval_literal($1, 16, 64); 254 !! 147 } 255 if (target) !! 148 ; 256 omit_node_if_u << 257 else << 258 ERROR(&@3, "La << 259 << 260 149 261 $$ = $1; !! 150 devicetree: >> 151 '/' nodedef >> 152 { >> 153 $$ = name_node($2, "", NULL); 262 } 154 } 263 ; 155 ; 264 156 265 nodedef: 157 nodedef: 266 '{' proplist subnodes '}' ';' 158 '{' proplist subnodes '}' ';' 267 { 159 { 268 $$ = build_node($2, $3 !! 160 $$ = build_node($2, $3); 269 } 161 } 270 ; 162 ; 271 163 272 proplist: 164 proplist: 273 /* empty */ 165 /* empty */ 274 { 166 { 275 $$ = NULL; 167 $$ = NULL; 276 } 168 } 277 | proplist propdef 169 | proplist propdef 278 { 170 { 279 $$ = chain_property($2 171 $$ = chain_property($2, $1); 280 } 172 } 281 ; 173 ; 282 174 283 propdef: 175 propdef: 284 DT_PROPNODENAME '=' propdata ';' !! 176 label 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 { 177 { 296 $$ = build_property_de !! 178 $$ = build_property($2, $4, $1); 297 free($2); << 298 } 179 } 299 | DT_LABEL propdef !! 180 | label DT_PROPNODENAME ';' 300 { 181 { 301 add_label(&$2->labels, !! 182 $$ = build_property($2, empty_data, $1); 302 $$ = $2; << 303 } 183 } 304 ; 184 ; 305 185 306 propdata: 186 propdata: 307 propdataprefix DT_STRING 187 propdataprefix DT_STRING 308 { 188 { 309 $$ = data_merge($1, $2 189 $$ = data_merge($1, $2); 310 } 190 } 311 | propdataprefix arrayprefix '>' !! 191 | propdataprefix '<' celllist '>' 312 { 192 { 313 $$ = data_merge($1, $2 !! 193 $$ = data_merge($1, $3); 314 } 194 } 315 | propdataprefix '[' bytestring ']' 195 | propdataprefix '[' bytestring ']' 316 { 196 { 317 $$ = data_merge($1, $3 197 $$ = data_merge($1, $3); 318 } 198 } 319 | propdataprefix dt_ref !! 199 | propdataprefix DT_REF 320 { 200 { 321 $1 = data_add_marker($ << 322 $$ = data_add_marker($ 201 $$ = data_add_marker($1, REF_PATH, $2); 323 } 202 } 324 | propdataprefix DT_INCBIN '(' DT_STRI !! 203 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' 325 { 204 { 326 FILE *f = srcfile_rela !! 205 struct search_path path = { srcpos_file->dir, NULL, NULL }; 327 struct data d; !! 206 struct dtc_file *file = dtc_open_file($4.val, &path); >> 207 struct data d = empty_data; 328 208 329 if ($6 != 0) 209 if ($6 != 0) 330 if (fseek(f, $ !! 210 if (fseek(file->file, $6, SEEK_SET) != 0) 331 die("C !! 211 yyerrorf("Couldn't seek to offset %llu in \"%s\": %s", 332 (u !! 212 (unsigned long long)$6, 333 st !! 213 $4.val, strerror(errno)); 334 214 335 d = data_copy_file(f, !! 215 d = data_copy_file(file->file, $8); 336 216 337 $$ = data_merge($1, d) 217 $$ = data_merge($1, d); 338 fclose(f); !! 218 dtc_close_file(file); 339 } 219 } 340 | propdataprefix DT_INCBIN '(' DT_STRI 220 | propdataprefix DT_INCBIN '(' DT_STRING ')' 341 { 221 { 342 FILE *f = srcfile_rela !! 222 struct search_path path = { srcpos_file->dir, NULL, NULL }; >> 223 struct dtc_file *file = dtc_open_file($4.val, &path); 343 struct data d = empty_ 224 struct data d = empty_data; 344 225 345 d = data_copy_file(f, !! 226 d = data_copy_file(file->file, -1); 346 227 347 $$ = data_merge($1, d) 228 $$ = data_merge($1, d); 348 fclose(f); !! 229 dtc_close_file(file); 349 } 230 } 350 | propdata DT_LABEL 231 | propdata DT_LABEL 351 { 232 { 352 $$ = data_add_marker($ 233 $$ = data_add_marker($1, LABEL, $2); 353 } 234 } 354 ; 235 ; 355 236 356 propdataprefix: 237 propdataprefix: 357 /* empty */ 238 /* empty */ 358 { 239 { 359 $$ = empty_data; 240 $$ = empty_data; 360 } 241 } 361 | propdata ',' 242 | propdata ',' 362 { 243 { 363 $$ = $1; 244 $$ = $1; 364 } 245 } 365 | propdataprefix DT_LABEL 246 | propdataprefix DT_LABEL 366 { 247 { 367 $$ = data_add_marker($ 248 $$ = data_add_marker($1, LABEL, $2); 368 } 249 } 369 ; 250 ; 370 251 371 arrayprefix: !! 252 celllist: 372 DT_BITS DT_LITERAL '<' !! 253 /* empty */ 373 { 254 { 374 unsigned long long bit !! 255 $$ = empty_data; 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 } 256 } 436 | arrayprefix DT_LABEL !! 257 | celllist cellval 437 { 258 { 438 $$.data = data_add_mar !! 259 $$ = data_append_cell($1, $2); 439 } 260 } 440 ; !! 261 | celllist DT_REF 441 << 442 integer_prim: << 443 DT_LITERAL << 444 | DT_CHAR_LITERAL << 445 | '(' integer_expr ')' << 446 { 262 { 447 $$ = $2; !! 263 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, >> 264 $2), -1); >> 265 } >> 266 | celllist DT_LABEL >> 267 { >> 268 $$ = data_add_marker($1, LABEL, $2); 448 } 269 } 449 ; 270 ; 450 271 451 integer_expr: !! 272 cellbase: 452 integer_trinary !! 273 /* empty */ 453 ; !! 274 { 454 !! 275 $$ = 16; 455 integer_trinary: !! 276 } 456 integer_or !! 277 | DT_BASE 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 ; 278 ; 510 279 511 integer_mul: !! 280 cellval: 512 integer_mul '*' integer_unary { $$ = !! 281 DT_LITERAL 513 | integer_mul '/' integer_unary << 514 { 282 { 515 if ($3 != 0) { !! 283 $$ = eval_literal($1, 0, 32); 516 $$ = $1 / $3; << 517 } else { << 518 ERROR(&@$, "Di << 519 $$ = 0; << 520 } << 521 } 284 } 522 | integer_mul '%' integer_unary !! 285 | cellbase DT_LEGACYLITERAL 523 { 286 { 524 if ($3 != 0) { !! 287 $$ = eval_literal($2, $1, 32); 525 $$ = $1 % $3; << 526 } else { << 527 ERROR(&@$, "Di << 528 $$ = 0; << 529 } << 530 } 288 } 531 | integer_unary << 532 ; << 533 << 534 integer_unary: << 535 integer_prim << 536 | '-' integer_unary { $$ = -$2; } << 537 | '~' integer_unary { $$ = ~$2; } << 538 | '!' integer_unary { $$ = !$2; } << 539 ; 289 ; 540 290 541 bytestring: 291 bytestring: 542 /* empty */ 292 /* empty */ 543 { 293 { 544 $$ = data_add_marker(e !! 294 $$ = empty_data; 545 } 295 } 546 | bytestring DT_BYTE 296 | bytestring DT_BYTE 547 { 297 { 548 $$ = data_append_byte( 298 $$ = data_append_byte($1, $2); 549 } 299 } 550 | bytestring DT_LABEL 300 | bytestring DT_LABEL 551 { 301 { 552 $$ = data_add_marker($ 302 $$ = data_add_marker($1, LABEL, $2); 553 } 303 } 554 ; 304 ; 555 305 556 subnodes: 306 subnodes: 557 /* empty */ 307 /* empty */ 558 { 308 { 559 $$ = NULL; 309 $$ = NULL; 560 } 310 } 561 | subnode subnodes !! 311 | subnode subnodes 562 { 312 { 563 $$ = chain_node($1, $2 313 $$ = chain_node($1, $2); 564 } 314 } 565 | subnode propdef 315 | subnode propdef 566 { 316 { 567 ERROR(&@2, "Properties !! 317 yyerror("syntax error: properties must precede subnodes"); 568 YYERROR; 318 YYERROR; 569 } 319 } 570 ; 320 ; 571 321 572 subnode: 322 subnode: 573 DT_PROPNODENAME nodedef !! 323 label DT_PROPNODENAME nodedef 574 { 324 { 575 $$ = name_node($2, $1) !! 325 $$ = name_node($3, $2, $1); 576 free($1); << 577 } 326 } 578 | DT_DEL_NODE DT_PROPNODENAME ';' !! 327 ; 579 { !! 328 580 $$ = name_node(build_n !! 329 label: 581 free($2); !! 330 /* empty */ 582 } << 583 | DT_OMIT_NO_REF subnode << 584 { 331 { 585 $$ = omit_node_if_unus !! 332 $$ = NULL; 586 } 333 } 587 | DT_LABEL subnode !! 334 | DT_LABEL 588 { 335 { 589 add_label(&$2->labels, !! 336 $$ = $1; 590 $$ = $2; << 591 } 337 } 592 ; 338 ; 593 339 594 %% 340 %% 595 341 596 void yyerror(char const *s) !! 342 void yyerrorf(char const *s, ...) >> 343 { >> 344 const char *fname = srcpos_file ? srcpos_file->name : "<no-file>"; >> 345 va_list va; >> 346 va_start(va, s); >> 347 >> 348 if (strcmp(fname, "-") == 0) >> 349 fname = "stdin"; >> 350 >> 351 fprintf(stderr, "%s:%d ", fname, yylloc.first_line); >> 352 vfprintf(stderr, s, va); >> 353 fprintf(stderr, "\n"); >> 354 >> 355 treesource_error = 1; >> 356 va_end(va); >> 357 } >> 358 >> 359 void yyerror (char const *s) >> 360 { >> 361 yyerrorf("%s", s); >> 362 } >> 363 >> 364 static unsigned long long eval_literal(const char *s, int base, int bits) 597 { 365 { 598 ERROR(&yylloc, "%s", s); !! 366 unsigned long long val; >> 367 char *e; >> 368 >> 369 errno = 0; >> 370 val = strtoull(s, &e, base); >> 371 if (*e) >> 372 yyerror("bad characters in literal"); >> 373 else if ((errno == ERANGE) >> 374 || ((bits < 64) && (val >= (1ULL << bits)))) >> 375 yyerror("literal out of range"); >> 376 else if (errno != 0) >> 377 yyerror("bad literal"); >> 378 return val; 599 } 379 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.