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; 34266130Sianextern bool treesource_error; 35204431Sraj%} 36204431Sraj 37204431Sraj%union { 38204431Sraj char *propnodename; 39204431Sraj char *labelref; 40204431Sraj unsigned int cbase; 41204431Sraj uint8_t byte; 42204431Sraj struct data data; 43204431Sraj 44238742Simp struct { 45238742Simp struct data data; 46238742Simp int bits; 47238742Simp } array; 48238742Simp 49204431Sraj struct property *prop; 50204431Sraj struct property *proplist; 51204431Sraj struct node *node; 52204431Sraj struct node *nodelist; 53204431Sraj struct reserve_info *re; 54238742Simp uint64_t integer; 55204431Sraj} 56204431Sraj 57204431Sraj%token DT_V1 58204431Sraj%token DT_MEMRESERVE 59238742Simp%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR 60238742Simp%token DT_BITS 61266130Sian%token DT_DEL_PROP 62266130Sian%token DT_DEL_NODE 63204431Sraj%token <propnodename> DT_PROPNODENAME 64266130Sian%token <integer> DT_LITERAL 65266130Sian%token <integer> DT_CHAR_LITERAL 66204431Sraj%token <cbase> DT_BASE 67204431Sraj%token <byte> DT_BYTE 68204431Sraj%token <data> DT_STRING 69204431Sraj%token <labelref> DT_LABEL 70204431Sraj%token <labelref> DT_REF 71204431Sraj%token DT_INCBIN 72204431Sraj 73204431Sraj%type <data> propdata 74204431Sraj%type <data> propdataprefix 75204431Sraj%type <re> memreserve 76204431Sraj%type <re> memreserves 77238742Simp%type <array> arrayprefix 78204431Sraj%type <data> bytestring 79204431Sraj%type <prop> propdef 80204431Sraj%type <proplist> proplist 81204431Sraj 82204431Sraj%type <node> devicetree 83204431Sraj%type <node> nodedef 84204431Sraj%type <node> subnode 85204431Sraj%type <nodelist> subnodes 86204431Sraj 87238742Simp%type <integer> integer_prim 88238742Simp%type <integer> integer_unary 89238742Simp%type <integer> integer_mul 90238742Simp%type <integer> integer_add 91238742Simp%type <integer> integer_shift 92238742Simp%type <integer> integer_rela 93238742Simp%type <integer> integer_eq 94238742Simp%type <integer> integer_bitand 95238742Simp%type <integer> integer_bitxor 96238742Simp%type <integer> integer_bitor 97238742Simp%type <integer> integer_and 98238742Simp%type <integer> integer_or 99238742Simp%type <integer> integer_trinary 100238742Simp%type <integer> integer_expr 101238742Simp 102204431Sraj%% 103204431Sraj 104204431Srajsourcefile: 105204431Sraj DT_V1 ';' memreserves devicetree 106204431Sraj { 107238742Simp the_boot_info = build_boot_info($3, $4, 108238742Simp guess_boot_cpuid($4)); 109204431Sraj } 110204431Sraj ; 111204431Sraj 112204431Srajmemreserves: 113204431Sraj /* empty */ 114204431Sraj { 115204431Sraj $$ = NULL; 116204431Sraj } 117204431Sraj | memreserve memreserves 118204431Sraj { 119204431Sraj $$ = chain_reserve_entry($1, $2); 120204431Sraj } 121204431Sraj ; 122204431Sraj 123204431Srajmemreserve: 124238742Simp DT_MEMRESERVE integer_prim integer_prim ';' 125204431Sraj { 126238742Simp $$ = build_reserve_entry($2, $3); 127204431Sraj } 128238742Simp | DT_LABEL memreserve 129204431Sraj { 130238742Simp add_label(&$2->labels, $1); 131238742Simp $$ = $2; 132204431Sraj } 133238742Simp ; 134204431Sraj 135204431Srajdevicetree: 136204431Sraj '/' nodedef 137204431Sraj { 138238742Simp $$ = name_node($2, ""); 139204431Sraj } 140238742Simp | devicetree '/' nodedef 141238742Simp { 142238742Simp $$ = merge_nodes($1, $3); 143238742Simp } 144238742Simp | devicetree DT_REF nodedef 145238742Simp { 146238742Simp struct node *target = get_node_by_ref($1, $2); 147238742Simp 148238742Simp if (target) 149238742Simp merge_nodes(target, $3); 150238742Simp else 151238742Simp print_error("label or path, '%s', not found", $2); 152238742Simp $$ = $1; 153238742Simp } 154266130Sian | devicetree DT_DEL_NODE DT_REF ';' 155266130Sian { 156266130Sian struct node *target = get_node_by_ref($1, $3); 157266130Sian 158266130Sian if (!target) 159266130Sian print_error("label or path, '%s', not found", $3); 160266130Sian else 161266130Sian delete_node(target); 162266130Sian 163266130Sian $$ = $1; 164266130Sian } 165204431Sraj ; 166204431Sraj 167204431Srajnodedef: 168204431Sraj '{' proplist subnodes '}' ';' 169204431Sraj { 170204431Sraj $$ = build_node($2, $3); 171204431Sraj } 172204431Sraj ; 173204431Sraj 174204431Srajproplist: 175204431Sraj /* empty */ 176204431Sraj { 177204431Sraj $$ = NULL; 178204431Sraj } 179204431Sraj | proplist propdef 180204431Sraj { 181204431Sraj $$ = chain_property($2, $1); 182204431Sraj } 183204431Sraj ; 184204431Sraj 185204431Srajpropdef: 186238742Simp DT_PROPNODENAME '=' propdata ';' 187204431Sraj { 188238742Simp $$ = build_property($1, $3); 189204431Sraj } 190238742Simp | DT_PROPNODENAME ';' 191204431Sraj { 192238742Simp $$ = build_property($1, empty_data); 193204431Sraj } 194266130Sian | DT_DEL_PROP DT_PROPNODENAME ';' 195266130Sian { 196266130Sian $$ = build_property_delete($2); 197266130Sian } 198238742Simp | DT_LABEL propdef 199238742Simp { 200238742Simp add_label(&$2->labels, $1); 201238742Simp $$ = $2; 202238742Simp } 203204431Sraj ; 204204431Sraj 205204431Srajpropdata: 206204431Sraj propdataprefix DT_STRING 207204431Sraj { 208204431Sraj $$ = data_merge($1, $2); 209204431Sraj } 210238742Simp | propdataprefix arrayprefix '>' 211204431Sraj { 212238742Simp $$ = data_merge($1, $2.data); 213204431Sraj } 214204431Sraj | propdataprefix '[' bytestring ']' 215204431Sraj { 216204431Sraj $$ = data_merge($1, $3); 217204431Sraj } 218204431Sraj | propdataprefix DT_REF 219204431Sraj { 220204431Sraj $$ = data_add_marker($1, REF_PATH, $2); 221204431Sraj } 222238742Simp | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' 223204431Sraj { 224238742Simp FILE *f = srcfile_relative_open($4.val, NULL); 225238742Simp struct data d; 226204431Sraj 227204431Sraj if ($6 != 0) 228238742Simp if (fseek(f, $6, SEEK_SET) != 0) 229266130Sian die("Couldn't seek to offset %llu in \"%s\": %s", 230266130Sian (unsigned long long)$6, $4.val, 231266130Sian strerror(errno)); 232204431Sraj 233238742Simp d = data_copy_file(f, $8); 234204431Sraj 235204431Sraj $$ = data_merge($1, d); 236238742Simp fclose(f); 237204431Sraj } 238204431Sraj | propdataprefix DT_INCBIN '(' DT_STRING ')' 239204431Sraj { 240238742Simp FILE *f = srcfile_relative_open($4.val, NULL); 241204431Sraj struct data d = empty_data; 242204431Sraj 243238742Simp d = data_copy_file(f, -1); 244204431Sraj 245204431Sraj $$ = data_merge($1, d); 246238742Simp fclose(f); 247204431Sraj } 248204431Sraj | propdata DT_LABEL 249204431Sraj { 250204431Sraj $$ = data_add_marker($1, LABEL, $2); 251204431Sraj } 252204431Sraj ; 253204431Sraj 254204431Srajpropdataprefix: 255204431Sraj /* empty */ 256204431Sraj { 257204431Sraj $$ = empty_data; 258204431Sraj } 259204431Sraj | propdata ',' 260204431Sraj { 261204431Sraj $$ = $1; 262204431Sraj } 263204431Sraj | propdataprefix DT_LABEL 264204431Sraj { 265204431Sraj $$ = data_add_marker($1, LABEL, $2); 266204431Sraj } 267204431Sraj ; 268204431Sraj 269238742Simparrayprefix: 270238742Simp DT_BITS DT_LITERAL '<' 271204431Sraj { 272266130Sian unsigned long long bits; 273238742Simp 274266130Sian bits = $2; 275266130Sian 276266130Sian if ((bits != 8) && (bits != 16) && 277266130Sian (bits != 32) && (bits != 64)) 278238742Simp { 279238742Simp print_error("Only 8, 16, 32 and 64-bit elements" 280238742Simp " are currently supported"); 281266130Sian bits = 32; 282238742Simp } 283266130Sian 284266130Sian $$.data = empty_data; 285266130Sian $$.bits = bits; 286204431Sraj } 287238742Simp | '<' 288204431Sraj { 289238742Simp $$.data = empty_data; 290238742Simp $$.bits = 32; 291204431Sraj } 292238742Simp | arrayprefix integer_prim 293204431Sraj { 294238742Simp if ($1.bits < 64) { 295238742Simp uint64_t mask = (1ULL << $1.bits) - 1; 296238742Simp /* 297238742Simp * Bits above mask must either be all zero 298238742Simp * (positive within range of mask) or all one 299238742Simp * (negative and sign-extended). The second 300238742Simp * condition is true if when we set all bits 301238742Simp * within the mask to one (i.e. | in the 302238742Simp * mask), all bits are one. 303238742Simp */ 304238742Simp if (($2 > mask) && (($2 | mask) != -1ULL)) 305238742Simp print_error( 306238742Simp "integer value out of range " 307238742Simp "%016lx (%d bits)", $1.bits); 308238742Simp } 309238742Simp 310238742Simp $$.data = data_append_integer($1.data, $2, $1.bits); 311204431Sraj } 312238742Simp | arrayprefix DT_REF 313204431Sraj { 314238742Simp uint64_t val = ~0ULL >> (64 - $1.bits); 315238742Simp 316238742Simp if ($1.bits == 32) 317238742Simp $1.data = data_add_marker($1.data, 318238742Simp REF_PHANDLE, 319238742Simp $2); 320238742Simp else 321238742Simp print_error("References are only allowed in " 322238742Simp "arrays with 32-bit elements."); 323238742Simp 324238742Simp $$.data = data_append_integer($1.data, val, $1.bits); 325204431Sraj } 326238742Simp | arrayprefix DT_LABEL 327238742Simp { 328238742Simp $$.data = data_add_marker($1.data, LABEL, $2); 329238742Simp } 330204431Sraj ; 331204431Sraj 332238742Simpinteger_prim: 333204431Sraj DT_LITERAL 334238742Simp | DT_CHAR_LITERAL 335238742Simp | '(' integer_expr ')' 336238742Simp { 337238742Simp $$ = $2; 338238742Simp } 339204431Sraj ; 340204431Sraj 341238742Simpinteger_expr: 342238742Simp integer_trinary 343238742Simp ; 344238742Simp 345238742Simpinteger_trinary: 346238742Simp integer_or 347238742Simp | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } 348238742Simp ; 349238742Simp 350238742Simpinteger_or: 351238742Simp integer_and 352238742Simp | integer_or DT_OR integer_and { $$ = $1 || $3; } 353238742Simp ; 354238742Simp 355238742Simpinteger_and: 356238742Simp integer_bitor 357238742Simp | integer_and DT_AND integer_bitor { $$ = $1 && $3; } 358238742Simp ; 359238742Simp 360238742Simpinteger_bitor: 361238742Simp integer_bitxor 362238742Simp | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } 363238742Simp ; 364238742Simp 365238742Simpinteger_bitxor: 366238742Simp integer_bitand 367238742Simp | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } 368238742Simp ; 369238742Simp 370238742Simpinteger_bitand: 371238742Simp integer_eq 372238742Simp | integer_bitand '&' integer_eq { $$ = $1 & $3; } 373238742Simp ; 374238742Simp 375238742Simpinteger_eq: 376238742Simp integer_rela 377238742Simp | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } 378238742Simp | integer_eq DT_NE integer_rela { $$ = $1 != $3; } 379238742Simp ; 380238742Simp 381238742Simpinteger_rela: 382238742Simp integer_shift 383238742Simp | integer_rela '<' integer_shift { $$ = $1 < $3; } 384238742Simp | integer_rela '>' integer_shift { $$ = $1 > $3; } 385238742Simp | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } 386238742Simp | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } 387238742Simp ; 388238742Simp 389238742Simpinteger_shift: 390238742Simp integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } 391238742Simp | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } 392238742Simp | integer_add 393238742Simp ; 394238742Simp 395238742Simpinteger_add: 396238742Simp integer_add '+' integer_mul { $$ = $1 + $3; } 397238742Simp | integer_add '-' integer_mul { $$ = $1 - $3; } 398238742Simp | integer_mul 399238742Simp ; 400238742Simp 401238742Simpinteger_mul: 402238742Simp integer_mul '*' integer_unary { $$ = $1 * $3; } 403238742Simp | integer_mul '/' integer_unary { $$ = $1 / $3; } 404238742Simp | integer_mul '%' integer_unary { $$ = $1 % $3; } 405238742Simp | integer_unary 406238742Simp ; 407238742Simp 408238742Simpinteger_unary: 409238742Simp integer_prim 410238742Simp | '-' integer_unary { $$ = -$2; } 411238742Simp | '~' integer_unary { $$ = ~$2; } 412238742Simp | '!' integer_unary { $$ = !$2; } 413238742Simp ; 414238742Simp 415204431Srajbytestring: 416204431Sraj /* empty */ 417204431Sraj { 418204431Sraj $$ = empty_data; 419204431Sraj } 420204431Sraj | bytestring DT_BYTE 421204431Sraj { 422204431Sraj $$ = data_append_byte($1, $2); 423204431Sraj } 424204431Sraj | bytestring DT_LABEL 425204431Sraj { 426204431Sraj $$ = data_add_marker($1, LABEL, $2); 427204431Sraj } 428204431Sraj ; 429204431Sraj 430204431Srajsubnodes: 431204431Sraj /* empty */ 432204431Sraj { 433204431Sraj $$ = NULL; 434204431Sraj } 435238742Simp | subnode subnodes 436204431Sraj { 437204431Sraj $$ = chain_node($1, $2); 438204431Sraj } 439204431Sraj | subnode propdef 440204431Sraj { 441238742Simp print_error("syntax error: properties must precede subnodes"); 442204431Sraj YYERROR; 443204431Sraj } 444204431Sraj ; 445204431Sraj 446204431Srajsubnode: 447238742Simp DT_PROPNODENAME nodedef 448204431Sraj { 449238742Simp $$ = name_node($2, $1); 450204431Sraj } 451266130Sian | DT_DEL_NODE DT_PROPNODENAME ';' 452266130Sian { 453266130Sian $$ = name_node(build_node_delete(), $2); 454266130Sian } 455238742Simp | DT_LABEL subnode 456204431Sraj { 457238742Simp add_label(&$2->labels, $1); 458238742Simp $$ = $2; 459204431Sraj } 460204431Sraj ; 461204431Sraj 462204431Sraj%% 463204431Sraj 464238742Simpvoid print_error(char const *fmt, ...) 465204431Sraj{ 466238742Simp va_list va; 467238742Simp 468238742Simp va_start(va, fmt); 469266130Sian srcpos_verror(&yylloc, "Error", fmt, va); 470238742Simp va_end(va); 471238742Simp 472266130Sian treesource_error = true; 473204431Sraj} 474204431Sraj 475238742Simpvoid yyerror(char const *s) { 476238742Simp print_error("%s", s); 477238742Simp} 478