dtc-parser.y revision 204489
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%{ 23204431Sraj#include <stdio.h> 24204431Sraj 25204431Sraj#include "dtc.h" 26204431Sraj#include "srcpos.h" 27204431Sraj 28204489SrajYYLTYPE yylloc; 29204489Sraj 30204431Srajextern int yylex(void); 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); 37204431Sraj%} 38204431Sraj 39204431Sraj%union { 40204431Sraj char *propnodename; 41204431Sraj char *literal; 42204431Sraj char *labelref; 43204431Sraj unsigned int cbase; 44204431Sraj uint8_t byte; 45204431Sraj struct data data; 46204431Sraj 47204431Sraj uint64_t addr; 48204431Sraj cell_t cell; 49204431Sraj struct property *prop; 50204431Sraj struct property *proplist; 51204431Sraj struct node *node; 52204431Sraj struct node *nodelist; 53204431Sraj struct reserve_info *re; 54204431Sraj} 55204431Sraj 56204431Sraj%token DT_V1 57204431Sraj%token DT_MEMRESERVE 58204431Sraj%token <propnodename> DT_PROPNODENAME 59204431Sraj%token <literal> DT_LITERAL 60204431Sraj%token <cbase> DT_BASE 61204431Sraj%token <byte> DT_BYTE 62204431Sraj%token <data> DT_STRING 63204431Sraj%token <labelref> DT_LABEL 64204431Sraj%token <labelref> DT_REF 65204431Sraj%token DT_INCBIN 66204431Sraj 67204431Sraj%type <data> propdata 68204431Sraj%type <data> propdataprefix 69204431Sraj%type <re> memreserve 70204431Sraj%type <re> memreserves 71204431Sraj%type <addr> addr 72204431Sraj%type <data> celllist 73204431Sraj%type <cell> cellval 74204431Sraj%type <data> bytestring 75204431Sraj%type <prop> propdef 76204431Sraj%type <proplist> proplist 77204431Sraj 78204431Sraj%type <node> devicetree 79204431Sraj%type <node> nodedef 80204431Sraj%type <node> subnode 81204431Sraj%type <nodelist> subnodes 82204431Sraj%type <labelref> label 83204431Sraj 84204431Sraj%% 85204431Sraj 86204431Srajsourcefile: 87204431Sraj DT_V1 ';' memreserves devicetree 88204431Sraj { 89204431Sraj the_boot_info = build_boot_info($3, $4, 0); 90204431Sraj } 91204431Sraj ; 92204431Sraj 93204431Srajmemreserves: 94204431Sraj /* empty */ 95204431Sraj { 96204431Sraj $$ = NULL; 97204431Sraj } 98204431Sraj | memreserve memreserves 99204431Sraj { 100204431Sraj $$ = chain_reserve_entry($1, $2); 101204431Sraj } 102204431Sraj ; 103204431Sraj 104204431Srajmemreserve: 105204431Sraj label DT_MEMRESERVE addr addr ';' 106204431Sraj { 107204431Sraj $$ = build_reserve_entry($3, $4, $1); 108204431Sraj } 109204431Sraj ; 110204431Sraj 111204431Srajaddr: 112204431Sraj DT_LITERAL 113204431Sraj { 114204431Sraj $$ = eval_literal($1, 0, 64); 115204431Sraj } 116204431Sraj ; 117204431Sraj 118204431Srajdevicetree: 119204431Sraj '/' nodedef 120204431Sraj { 121204431Sraj $$ = name_node($2, "", NULL); 122204431Sraj } 123204431Sraj ; 124204431Sraj 125204431Srajnodedef: 126204431Sraj '{' proplist subnodes '}' ';' 127204431Sraj { 128204431Sraj $$ = build_node($2, $3); 129204431Sraj } 130204431Sraj ; 131204431Sraj 132204431Srajproplist: 133204431Sraj /* empty */ 134204431Sraj { 135204431Sraj $$ = NULL; 136204431Sraj } 137204431Sraj | proplist propdef 138204431Sraj { 139204431Sraj $$ = chain_property($2, $1); 140204431Sraj } 141204431Sraj ; 142204431Sraj 143204431Srajpropdef: 144204431Sraj label DT_PROPNODENAME '=' propdata ';' 145204431Sraj { 146204431Sraj $$ = build_property($2, $4, $1); 147204431Sraj } 148204431Sraj | label DT_PROPNODENAME ';' 149204431Sraj { 150204431Sraj $$ = build_property($2, empty_data, $1); 151204431Sraj } 152204431Sraj ; 153204431Sraj 154204431Srajpropdata: 155204431Sraj propdataprefix DT_STRING 156204431Sraj { 157204431Sraj $$ = data_merge($1, $2); 158204431Sraj } 159204431Sraj | propdataprefix '<' celllist '>' 160204431Sraj { 161204431Sraj $$ = data_merge($1, $3); 162204431Sraj } 163204431Sraj | propdataprefix '[' bytestring ']' 164204431Sraj { 165204431Sraj $$ = data_merge($1, $3); 166204431Sraj } 167204431Sraj | propdataprefix DT_REF 168204431Sraj { 169204431Sraj $$ = data_add_marker($1, REF_PATH, $2); 170204431Sraj } 171204431Sraj | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' 172204431Sraj { 173204431Sraj struct search_path path = { srcpos_file->dir, NULL, NULL }; 174204431Sraj struct dtc_file *file = dtc_open_file($4.val, &path); 175204431Sraj struct data d = empty_data; 176204431Sraj 177204431Sraj if ($6 != 0) 178204431Sraj if (fseek(file->file, $6, SEEK_SET) != 0) 179204433Sraj srcpos_error(&yylloc, 180204433Sraj "Couldn't seek to offset %llu in \"%s\": %s", 181204433Sraj (unsigned long long)$6, 182204433Sraj $4.val, 183204433Sraj strerror(errno)); 184204431Sraj 185204431Sraj d = data_copy_file(file->file, $8); 186204431Sraj 187204431Sraj $$ = data_merge($1, d); 188204431Sraj dtc_close_file(file); 189204431Sraj } 190204431Sraj | propdataprefix DT_INCBIN '(' DT_STRING ')' 191204431Sraj { 192204431Sraj struct search_path path = { srcpos_file->dir, NULL, NULL }; 193204431Sraj struct dtc_file *file = dtc_open_file($4.val, &path); 194204431Sraj struct data d = empty_data; 195204431Sraj 196204431Sraj d = data_copy_file(file->file, -1); 197204431Sraj 198204431Sraj $$ = data_merge($1, d); 199204431Sraj dtc_close_file(file); 200204431Sraj } 201204431Sraj | propdata DT_LABEL 202204431Sraj { 203204431Sraj $$ = data_add_marker($1, LABEL, $2); 204204431Sraj } 205204431Sraj ; 206204431Sraj 207204431Srajpropdataprefix: 208204431Sraj /* empty */ 209204431Sraj { 210204431Sraj $$ = empty_data; 211204431Sraj } 212204431Sraj | propdata ',' 213204431Sraj { 214204431Sraj $$ = $1; 215204431Sraj } 216204431Sraj | propdataprefix DT_LABEL 217204431Sraj { 218204431Sraj $$ = data_add_marker($1, LABEL, $2); 219204431Sraj } 220204431Sraj ; 221204431Sraj 222204431Srajcelllist: 223204431Sraj /* empty */ 224204431Sraj { 225204431Sraj $$ = empty_data; 226204431Sraj } 227204431Sraj | celllist cellval 228204431Sraj { 229204431Sraj $$ = data_append_cell($1, $2); 230204431Sraj } 231204431Sraj | celllist DT_REF 232204431Sraj { 233204431Sraj $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, 234204431Sraj $2), -1); 235204431Sraj } 236204431Sraj | celllist DT_LABEL 237204431Sraj { 238204431Sraj $$ = data_add_marker($1, LABEL, $2); 239204431Sraj } 240204431Sraj ; 241204431Sraj 242204431Srajcellval: 243204431Sraj DT_LITERAL 244204431Sraj { 245204431Sraj $$ = eval_literal($1, 0, 32); 246204431Sraj } 247204431Sraj ; 248204431Sraj 249204431Srajbytestring: 250204431Sraj /* empty */ 251204431Sraj { 252204431Sraj $$ = empty_data; 253204431Sraj } 254204431Sraj | bytestring DT_BYTE 255204431Sraj { 256204431Sraj $$ = data_append_byte($1, $2); 257204431Sraj } 258204431Sraj | bytestring DT_LABEL 259204431Sraj { 260204431Sraj $$ = data_add_marker($1, LABEL, $2); 261204431Sraj } 262204431Sraj ; 263204431Sraj 264204431Srajsubnodes: 265204431Sraj /* empty */ 266204431Sraj { 267204431Sraj $$ = NULL; 268204431Sraj } 269204431Sraj | subnode subnodes 270204431Sraj { 271204431Sraj $$ = chain_node($1, $2); 272204431Sraj } 273204431Sraj | subnode propdef 274204431Sraj { 275204431Sraj yyerror("syntax error: properties must precede subnodes"); 276204431Sraj YYERROR; 277204431Sraj } 278204431Sraj ; 279204431Sraj 280204431Srajsubnode: 281204431Sraj label DT_PROPNODENAME nodedef 282204431Sraj { 283204431Sraj $$ = name_node($3, $2, $1); 284204431Sraj } 285204431Sraj ; 286204431Sraj 287204431Srajlabel: 288204431Sraj /* empty */ 289204431Sraj { 290204431Sraj $$ = NULL; 291204431Sraj } 292204431Sraj | DT_LABEL 293204431Sraj { 294204431Sraj $$ = $1; 295204431Sraj } 296204431Sraj ; 297204431Sraj 298204431Sraj%% 299204431Sraj 300204433Srajvoid yyerror(char const *s) 301204431Sraj{ 302204433Sraj srcpos_error(&yylloc, "%s", s); 303204431Sraj treesource_error = 1; 304204431Sraj} 305204431Sraj 306204431Srajstatic unsigned long long eval_literal(const char *s, int base, int bits) 307204431Sraj{ 308204431Sraj unsigned long long val; 309204431Sraj char *e; 310204431Sraj 311204431Sraj errno = 0; 312204431Sraj val = strtoull(s, &e, base); 313204431Sraj if (*e) 314204431Sraj yyerror("bad characters in literal"); 315204431Sraj else if ((errno == ERANGE) 316204431Sraj || ((bits < 64) && (val >= (1ULL << bits)))) 317204431Sraj yyerror("literal out of range"); 318204431Sraj else if (errno != 0) 319204431Sraj yyerror("bad literal"); 320204431Sraj return val; 321204431Sraj} 322