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