dtc-parser.y revision 238742
1204431Sraj/* 2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3204431Sraj * 4204431Sraj * 5204431Sraj * This program is free software; you can redistribute it and/or 6204431Sraj * modify it under the terms of the GNU General Public License as 7204431Sraj * published by the Free Software Foundation; either version 2 of the 8204431Sraj * License, or (at your option) any later version. 9204431Sraj * 10204431Sraj * This program is distributed in the hope that it will be useful, 11204431Sraj * but WITHOUT ANY WARRANTY; without even the implied warranty of 12204431Sraj * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13204431Sraj * General Public License for more details. 14204431Sraj * 15204431Sraj * You should have received a copy of the GNU General Public License 16204431Sraj * along with this program; if not, write to the Free Software 17204431Sraj * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18204431Sraj * USA 19204431Sraj */ 20204431Sraj 21204431Sraj%{ 22204431Sraj#include <stdio.h> 23204431Sraj 24204431Sraj#include "dtc.h" 25204431Sraj#include "srcpos.h" 26204431Sraj 27204489SrajYYLTYPE yylloc; 28204489Sraj 29204431Srajextern int yylex(void); 30238742Simpextern void print_error(char const *fmt, ...); 31204433Srajextern void yyerror(char const *s); 32204431Sraj 33204431Srajextern struct boot_info *the_boot_info; 34204431Srajextern int treesource_error; 35204431Sraj 36204431Srajstatic unsigned long long eval_literal(const char *s, int base, int bits); 37238742Simpstatic unsigned char eval_char_literal(const char *s); 38204431Sraj%} 39204431Sraj 40204431Sraj%union { 41204431Sraj char *propnodename; 42204431Sraj char *literal; 43204431Sraj char *labelref; 44204431Sraj unsigned int cbase; 45204431Sraj uint8_t byte; 46204431Sraj struct data data; 47204431Sraj 48238742Simp struct { 49238742Simp struct data data; 50238742Simp int bits; 51238742Simp } array; 52238742Simp 53204431Sraj struct property *prop; 54204431Sraj struct property *proplist; 55204431Sraj struct node *node; 56204431Sraj struct node *nodelist; 57204431Sraj struct reserve_info *re; 58238742Simp uint64_t integer; 59204431Sraj} 60204431Sraj 61204431Sraj%token DT_V1 62204431Sraj%token DT_MEMRESERVE 63238742Simp%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR 64238742Simp%token DT_BITS 65204431Sraj%token <propnodename> DT_PROPNODENAME 66204431Sraj%token <literal> DT_LITERAL 67238742Simp%token <literal> DT_CHAR_LITERAL 68204431Sraj%token <cbase> DT_BASE 69204431Sraj%token <byte> DT_BYTE 70204431Sraj%token <data> DT_STRING 71204431Sraj%token <labelref> DT_LABEL 72204431Sraj%token <labelref> DT_REF 73204431Sraj%token DT_INCBIN 74204431Sraj 75204431Sraj%type <data> propdata 76204431Sraj%type <data> propdataprefix 77204431Sraj%type <re> memreserve 78204431Sraj%type <re> memreserves 79238742Simp%type <array> arrayprefix 80204431Sraj%type <data> bytestring 81204431Sraj%type <prop> propdef 82204431Sraj%type <proplist> proplist 83204431Sraj 84204431Sraj%type <node> devicetree 85204431Sraj%type <node> nodedef 86204431Sraj%type <node> subnode 87204431Sraj%type <nodelist> subnodes 88204431Sraj 89238742Simp%type <integer> integer_prim 90238742Simp%type <integer> integer_unary 91238742Simp%type <integer> integer_mul 92238742Simp%type <integer> integer_add 93238742Simp%type <integer> integer_shift 94238742Simp%type <integer> integer_rela 95238742Simp%type <integer> integer_eq 96238742Simp%type <integer> integer_bitand 97238742Simp%type <integer> integer_bitxor 98238742Simp%type <integer> integer_bitor 99238742Simp%type <integer> integer_and 100238742Simp%type <integer> integer_or 101238742Simp%type <integer> integer_trinary 102238742Simp%type <integer> integer_expr 103238742Simp 104204431Sraj%% 105204431Sraj 106204431Srajsourcefile: 107204431Sraj DT_V1 ';' memreserves devicetree 108204431Sraj { 109238742Simp the_boot_info = build_boot_info($3, $4, 110238742Simp guess_boot_cpuid($4)); 111204431Sraj } 112204431Sraj ; 113204431Sraj 114204431Srajmemreserves: 115204431Sraj /* empty */ 116204431Sraj { 117204431Sraj $$ = NULL; 118204431Sraj } 119204431Sraj | memreserve memreserves 120204431Sraj { 121204431Sraj $$ = chain_reserve_entry($1, $2); 122204431Sraj } 123204431Sraj ; 124204431Sraj 125204431Srajmemreserve: 126238742Simp DT_MEMRESERVE integer_prim integer_prim ';' 127204431Sraj { 128238742Simp $$ = build_reserve_entry($2, $3); 129204431Sraj } 130238742Simp | DT_LABEL memreserve 131204431Sraj { 132238742Simp add_label(&$2->labels, $1); 133238742Simp $$ = $2; 134204431Sraj } 135238742Simp ; 136204431Sraj 137204431Srajdevicetree: 138204431Sraj '/' nodedef 139204431Sraj { 140238742Simp $$ = name_node($2, ""); 141204431Sraj } 142238742Simp | devicetree '/' nodedef 143238742Simp { 144238742Simp $$ = merge_nodes($1, $3); 145238742Simp } 146238742Simp | devicetree DT_REF nodedef 147238742Simp { 148238742Simp struct node *target = get_node_by_ref($1, $2); 149238742Simp 150238742Simp if (target) 151238742Simp merge_nodes(target, $3); 152238742Simp else 153238742Simp print_error("label or path, '%s', not found", $2); 154238742Simp $$ = $1; 155238742Simp } 156204431Sraj ; 157204431Sraj 158204431Srajnodedef: 159204431Sraj '{' proplist subnodes '}' ';' 160204431Sraj { 161204431Sraj $$ = build_node($2, $3); 162204431Sraj } 163204431Sraj ; 164204431Sraj 165204431Srajproplist: 166204431Sraj /* empty */ 167204431Sraj { 168204431Sraj $$ = NULL; 169204431Sraj } 170204431Sraj | proplist propdef 171204431Sraj { 172204431Sraj $$ = chain_property($2, $1); 173204431Sraj } 174204431Sraj ; 175204431Sraj 176204431Srajpropdef: 177238742Simp DT_PROPNODENAME '=' propdata ';' 178204431Sraj { 179238742Simp $$ = build_property($1, $3); 180204431Sraj } 181238742Simp | DT_PROPNODENAME ';' 182204431Sraj { 183238742Simp $$ = build_property($1, empty_data); 184204431Sraj } 185238742Simp | DT_LABEL propdef 186238742Simp { 187238742Simp add_label(&$2->labels, $1); 188238742Simp $$ = $2; 189238742Simp } 190204431Sraj ; 191204431Sraj 192204431Srajpropdata: 193204431Sraj propdataprefix DT_STRING 194204431Sraj { 195204431Sraj $$ = data_merge($1, $2); 196204431Sraj } 197238742Simp | propdataprefix arrayprefix '>' 198204431Sraj { 199238742Simp $$ = data_merge($1, $2.data); 200204431Sraj } 201204431Sraj | propdataprefix '[' bytestring ']' 202204431Sraj { 203204431Sraj $$ = data_merge($1, $3); 204204431Sraj } 205204431Sraj | propdataprefix DT_REF 206204431Sraj { 207204431Sraj $$ = data_add_marker($1, REF_PATH, $2); 208204431Sraj } 209238742Simp | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' 210204431Sraj { 211238742Simp FILE *f = srcfile_relative_open($4.val, NULL); 212238742Simp struct data d; 213204431Sraj 214204431Sraj if ($6 != 0) 215238742Simp if (fseek(f, $6, SEEK_SET) != 0) 216238742Simp print_error("Couldn't seek to offset %llu in \"%s\": %s", 217204433Sraj (unsigned long long)$6, 218204433Sraj $4.val, 219204433Sraj strerror(errno)); 220204431Sraj 221238742Simp d = data_copy_file(f, $8); 222204431Sraj 223204431Sraj $$ = data_merge($1, d); 224238742Simp fclose(f); 225204431Sraj } 226204431Sraj | propdataprefix DT_INCBIN '(' DT_STRING ')' 227204431Sraj { 228238742Simp FILE *f = srcfile_relative_open($4.val, NULL); 229204431Sraj struct data d = empty_data; 230204431Sraj 231238742Simp d = data_copy_file(f, -1); 232204431Sraj 233204431Sraj $$ = data_merge($1, d); 234238742Simp fclose(f); 235204431Sraj } 236204431Sraj | propdata DT_LABEL 237204431Sraj { 238204431Sraj $$ = data_add_marker($1, LABEL, $2); 239204431Sraj } 240204431Sraj ; 241204431Sraj 242204431Srajpropdataprefix: 243204431Sraj /* empty */ 244204431Sraj { 245204431Sraj $$ = empty_data; 246204431Sraj } 247204431Sraj | propdata ',' 248204431Sraj { 249204431Sraj $$ = $1; 250204431Sraj } 251204431Sraj | propdataprefix DT_LABEL 252204431Sraj { 253204431Sraj $$ = data_add_marker($1, LABEL, $2); 254204431Sraj } 255204431Sraj ; 256204431Sraj 257238742Simparrayprefix: 258238742Simp DT_BITS DT_LITERAL '<' 259204431Sraj { 260238742Simp $$.data = empty_data; 261238742Simp $$.bits = eval_literal($2, 0, 7); 262238742Simp 263238742Simp if (($$.bits != 8) && 264238742Simp ($$.bits != 16) && 265238742Simp ($$.bits != 32) && 266238742Simp ($$.bits != 64)) 267238742Simp { 268238742Simp print_error("Only 8, 16, 32 and 64-bit elements" 269238742Simp " are currently supported"); 270238742Simp $$.bits = 32; 271238742Simp } 272204431Sraj } 273238742Simp | '<' 274204431Sraj { 275238742Simp $$.data = empty_data; 276238742Simp $$.bits = 32; 277204431Sraj } 278238742Simp | arrayprefix integer_prim 279204431Sraj { 280238742Simp if ($1.bits < 64) { 281238742Simp uint64_t mask = (1ULL << $1.bits) - 1; 282238742Simp /* 283238742Simp * Bits above mask must either be all zero 284238742Simp * (positive within range of mask) or all one 285238742Simp * (negative and sign-extended). The second 286238742Simp * condition is true if when we set all bits 287238742Simp * within the mask to one (i.e. | in the 288238742Simp * mask), all bits are one. 289238742Simp */ 290238742Simp if (($2 > mask) && (($2 | mask) != -1ULL)) 291238742Simp print_error( 292238742Simp "integer value out of range " 293238742Simp "%016lx (%d bits)", $1.bits); 294238742Simp } 295238742Simp 296238742Simp $$.data = data_append_integer($1.data, $2, $1.bits); 297204431Sraj } 298238742Simp | arrayprefix DT_REF 299204431Sraj { 300238742Simp uint64_t val = ~0ULL >> (64 - $1.bits); 301238742Simp 302238742Simp if ($1.bits == 32) 303238742Simp $1.data = data_add_marker($1.data, 304238742Simp REF_PHANDLE, 305238742Simp $2); 306238742Simp else 307238742Simp print_error("References are only allowed in " 308238742Simp "arrays with 32-bit elements."); 309238742Simp 310238742Simp $$.data = data_append_integer($1.data, val, $1.bits); 311204431Sraj } 312238742Simp | arrayprefix DT_LABEL 313238742Simp { 314238742Simp $$.data = data_add_marker($1.data, LABEL, $2); 315238742Simp } 316204431Sraj ; 317204431Sraj 318238742Simpinteger_prim: 319204431Sraj DT_LITERAL 320204431Sraj { 321238742Simp $$ = eval_literal($1, 0, 64); 322204431Sraj } 323238742Simp | DT_CHAR_LITERAL 324238742Simp { 325238742Simp $$ = eval_char_literal($1); 326238742Simp } 327238742Simp | '(' integer_expr ')' 328238742Simp { 329238742Simp $$ = $2; 330238742Simp } 331204431Sraj ; 332204431Sraj 333238742Simpinteger_expr: 334238742Simp integer_trinary 335238742Simp ; 336238742Simp 337238742Simpinteger_trinary: 338238742Simp integer_or 339238742Simp | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } 340238742Simp ; 341238742Simp 342238742Simpinteger_or: 343238742Simp integer_and 344238742Simp | integer_or DT_OR integer_and { $$ = $1 || $3; } 345238742Simp ; 346238742Simp 347238742Simpinteger_and: 348238742Simp integer_bitor 349238742Simp | integer_and DT_AND integer_bitor { $$ = $1 && $3; } 350238742Simp ; 351238742Simp 352238742Simpinteger_bitor: 353238742Simp integer_bitxor 354238742Simp | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } 355238742Simp ; 356238742Simp 357238742Simpinteger_bitxor: 358238742Simp integer_bitand 359238742Simp | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } 360238742Simp ; 361238742Simp 362238742Simpinteger_bitand: 363238742Simp integer_eq 364238742Simp | integer_bitand '&' integer_eq { $$ = $1 & $3; } 365238742Simp ; 366238742Simp 367238742Simpinteger_eq: 368238742Simp integer_rela 369238742Simp | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } 370238742Simp | integer_eq DT_NE integer_rela { $$ = $1 != $3; } 371238742Simp ; 372238742Simp 373238742Simpinteger_rela: 374238742Simp integer_shift 375238742Simp | integer_rela '<' integer_shift { $$ = $1 < $3; } 376238742Simp | integer_rela '>' integer_shift { $$ = $1 > $3; } 377238742Simp | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } 378238742Simp | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } 379238742Simp ; 380238742Simp 381238742Simpinteger_shift: 382238742Simp integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } 383238742Simp | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } 384238742Simp | integer_add 385238742Simp ; 386238742Simp 387238742Simpinteger_add: 388238742Simp integer_add '+' integer_mul { $$ = $1 + $3; } 389238742Simp | integer_add '-' integer_mul { $$ = $1 - $3; } 390238742Simp | integer_mul 391238742Simp ; 392238742Simp 393238742Simpinteger_mul: 394238742Simp integer_mul '*' integer_unary { $$ = $1 * $3; } 395238742Simp | integer_mul '/' integer_unary { $$ = $1 / $3; } 396238742Simp | integer_mul '%' integer_unary { $$ = $1 % $3; } 397238742Simp | integer_unary 398238742Simp ; 399238742Simp 400238742Simpinteger_unary: 401238742Simp integer_prim 402238742Simp | '-' integer_unary { $$ = -$2; } 403238742Simp | '~' integer_unary { $$ = ~$2; } 404238742Simp | '!' integer_unary { $$ = !$2; } 405238742Simp ; 406238742Simp 407204431Srajbytestring: 408204431Sraj /* empty */ 409204431Sraj { 410204431Sraj $$ = empty_data; 411204431Sraj } 412204431Sraj | bytestring DT_BYTE 413204431Sraj { 414204431Sraj $$ = data_append_byte($1, $2); 415204431Sraj } 416204431Sraj | bytestring DT_LABEL 417204431Sraj { 418204431Sraj $$ = data_add_marker($1, LABEL, $2); 419204431Sraj } 420204431Sraj ; 421204431Sraj 422204431Srajsubnodes: 423204431Sraj /* empty */ 424204431Sraj { 425204431Sraj $$ = NULL; 426204431Sraj } 427238742Simp | subnode subnodes 428204431Sraj { 429204431Sraj $$ = chain_node($1, $2); 430204431Sraj } 431204431Sraj | subnode propdef 432204431Sraj { 433238742Simp print_error("syntax error: properties must precede subnodes"); 434204431Sraj YYERROR; 435204431Sraj } 436204431Sraj ; 437204431Sraj 438204431Srajsubnode: 439238742Simp DT_PROPNODENAME nodedef 440204431Sraj { 441238742Simp $$ = name_node($2, $1); 442204431Sraj } 443238742Simp | DT_LABEL subnode 444204431Sraj { 445238742Simp add_label(&$2->labels, $1); 446238742Simp $$ = $2; 447204431Sraj } 448204431Sraj ; 449204431Sraj 450204431Sraj%% 451204431Sraj 452238742Simpvoid print_error(char const *fmt, ...) 453204431Sraj{ 454238742Simp va_list va; 455238742Simp 456238742Simp va_start(va, fmt); 457238742Simp srcpos_verror(&yylloc, fmt, va); 458238742Simp va_end(va); 459238742Simp 460204431Sraj treesource_error = 1; 461204431Sraj} 462204431Sraj 463238742Simpvoid yyerror(char const *s) { 464238742Simp print_error("%s", s); 465238742Simp} 466238742Simp 467204431Srajstatic unsigned long long eval_literal(const char *s, int base, int bits) 468204431Sraj{ 469204431Sraj unsigned long long val; 470204431Sraj char *e; 471204431Sraj 472204431Sraj errno = 0; 473204431Sraj val = strtoull(s, &e, base); 474238742Simp if (*e) { 475238742Simp size_t uls = strspn(e, "UL"); 476238742Simp if (e[uls]) 477238742Simp print_error("bad characters in literal"); 478238742Simp } 479238742Simp if ((errno == ERANGE) 480204431Sraj || ((bits < 64) && (val >= (1ULL << bits)))) 481238742Simp print_error("literal out of range"); 482204431Sraj else if (errno != 0) 483238742Simp print_error("bad literal"); 484204431Sraj return val; 485204431Sraj} 486238742Simp 487238742Simpstatic unsigned char eval_char_literal(const char *s) 488238742Simp{ 489238742Simp int i = 1; 490238742Simp char c = s[0]; 491238742Simp 492238742Simp if (c == '\0') 493238742Simp { 494238742Simp print_error("empty character literal"); 495238742Simp return 0; 496238742Simp } 497238742Simp 498238742Simp /* 499238742Simp * If the first character in the character literal is a \ then process 500238742Simp * the remaining characters as an escape encoding. If the first 501238742Simp * character is neither an escape or a terminator it should be the only 502238742Simp * character in the literal and will be returned. 503238742Simp */ 504238742Simp if (c == '\\') 505238742Simp c = get_escape_char(s, &i); 506238742Simp 507238742Simp if (s[i] != '\0') 508238742Simp print_error("malformed character literal"); 509238742Simp 510238742Simp return c; 511238742Simp} 512