dtc-parser.y revision 204488
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%locations 22 23%{ 24#include <stdio.h> 25 26#include "dtc.h" 27#include "srcpos.h" 28 29extern int yylex(void); 30extern void yyerror(char const *s); 31 32extern struct boot_info *the_boot_info; 33extern int treesource_error; 34 35static unsigned long long eval_literal(const char *s, int base, int bits); 36%} 37 38%union { 39 char *propnodename; 40 char *literal; 41 char *labelref; 42 unsigned int cbase; 43 uint8_t byte; 44 struct data data; 45 46 uint64_t addr; 47 cell_t cell; 48 struct property *prop; 49 struct property *proplist; 50 struct node *node; 51 struct node *nodelist; 52 struct reserve_info *re; 53} 54 55%token DT_V1 56%token DT_MEMRESERVE 57%token <propnodename> DT_PROPNODENAME 58%token <literal> DT_LITERAL 59%token <cbase> DT_BASE 60%token <byte> DT_BYTE 61%token <data> DT_STRING 62%token <labelref> DT_LABEL 63%token <labelref> DT_REF 64%token DT_INCBIN 65 66%type <data> propdata 67%type <data> propdataprefix 68%type <re> memreserve 69%type <re> memreserves 70%type <addr> addr 71%type <data> celllist 72%type <cell> cellval 73%type <data> bytestring 74%type <prop> propdef 75%type <proplist> proplist 76 77%type <node> devicetree 78%type <node> nodedef 79%type <node> subnode 80%type <nodelist> subnodes 81%type <labelref> label 82 83%% 84 85sourcefile: 86 DT_V1 ';' memreserves devicetree 87 { 88 the_boot_info = build_boot_info($3, $4, 0); 89 } 90 ; 91 92memreserves: 93 /* empty */ 94 { 95 $$ = NULL; 96 } 97 | memreserve memreserves 98 { 99 $$ = chain_reserve_entry($1, $2); 100 } 101 ; 102 103memreserve: 104 label DT_MEMRESERVE addr addr ';' 105 { 106 $$ = build_reserve_entry($3, $4, $1); 107 } 108 ; 109 110addr: 111 DT_LITERAL 112 { 113 $$ = eval_literal($1, 0, 64); 114 } 115 ; 116 117devicetree: 118 '/' nodedef 119 { 120 $$ = name_node($2, "", NULL); 121 } 122 ; 123 124nodedef: 125 '{' proplist subnodes '}' ';' 126 { 127 $$ = build_node($2, $3); 128 } 129 ; 130 131proplist: 132 /* empty */ 133 { 134 $$ = NULL; 135 } 136 | proplist propdef 137 { 138 $$ = chain_property($2, $1); 139 } 140 ; 141 142propdef: 143 label DT_PROPNODENAME '=' propdata ';' 144 { 145 $$ = build_property($2, $4, $1); 146 } 147 | label DT_PROPNODENAME ';' 148 { 149 $$ = build_property($2, empty_data, $1); 150 } 151 ; 152 153propdata: 154 propdataprefix DT_STRING 155 { 156 $$ = data_merge($1, $2); 157 } 158 | propdataprefix '<' celllist '>' 159 { 160 $$ = data_merge($1, $3); 161 } 162 | propdataprefix '[' bytestring ']' 163 { 164 $$ = data_merge($1, $3); 165 } 166 | propdataprefix DT_REF 167 { 168 $$ = data_add_marker($1, REF_PATH, $2); 169 } 170 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' 171 { 172 struct search_path path = { srcpos_file->dir, NULL, NULL }; 173 struct dtc_file *file = dtc_open_file($4.val, &path); 174 struct data d = empty_data; 175 176 if ($6 != 0) 177 if (fseek(file->file, $6, SEEK_SET) != 0) 178 srcpos_error(&yylloc, 179 "Couldn't seek to offset %llu in \"%s\": %s", 180 (unsigned long long)$6, 181 $4.val, 182 strerror(errno)); 183 184 d = data_copy_file(file->file, $8); 185 186 $$ = data_merge($1, d); 187 dtc_close_file(file); 188 } 189 | propdataprefix DT_INCBIN '(' DT_STRING ')' 190 { 191 struct search_path path = { srcpos_file->dir, NULL, NULL }; 192 struct dtc_file *file = dtc_open_file($4.val, &path); 193 struct data d = empty_data; 194 195 d = data_copy_file(file->file, -1); 196 197 $$ = data_merge($1, d); 198 dtc_close_file(file); 199 } 200 | propdata DT_LABEL 201 { 202 $$ = data_add_marker($1, LABEL, $2); 203 } 204 ; 205 206propdataprefix: 207 /* empty */ 208 { 209 $$ = empty_data; 210 } 211 | propdata ',' 212 { 213 $$ = $1; 214 } 215 | propdataprefix DT_LABEL 216 { 217 $$ = data_add_marker($1, LABEL, $2); 218 } 219 ; 220 221celllist: 222 /* empty */ 223 { 224 $$ = empty_data; 225 } 226 | celllist cellval 227 { 228 $$ = data_append_cell($1, $2); 229 } 230 | celllist DT_REF 231 { 232 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, 233 $2), -1); 234 } 235 | celllist DT_LABEL 236 { 237 $$ = data_add_marker($1, LABEL, $2); 238 } 239 ; 240 241cellval: 242 DT_LITERAL 243 { 244 $$ = eval_literal($1, 0, 32); 245 } 246 ; 247 248bytestring: 249 /* empty */ 250 { 251 $$ = empty_data; 252 } 253 | bytestring DT_BYTE 254 { 255 $$ = data_append_byte($1, $2); 256 } 257 | bytestring DT_LABEL 258 { 259 $$ = data_add_marker($1, LABEL, $2); 260 } 261 ; 262 263subnodes: 264 /* empty */ 265 { 266 $$ = NULL; 267 } 268 | subnode subnodes 269 { 270 $$ = chain_node($1, $2); 271 } 272 | subnode propdef 273 { 274 yyerror("syntax error: properties must precede subnodes"); 275 YYERROR; 276 } 277 ; 278 279subnode: 280 label DT_PROPNODENAME nodedef 281 { 282 $$ = name_node($3, $2, $1); 283 } 284 ; 285 286label: 287 /* empty */ 288 { 289 $$ = NULL; 290 } 291 | DT_LABEL 292 { 293 $$ = $1; 294 } 295 ; 296 297%% 298 299void yyerror(char const *s) 300{ 301 srcpos_error(&yylloc, "%s", s); 302 treesource_error = 1; 303} 304 305static unsigned long long eval_literal(const char *s, int base, int bits) 306{ 307 unsigned long long val; 308 char *e; 309 310 errno = 0; 311 val = strtoull(s, &e, base); 312 if (*e) 313 yyerror("bad characters in literal"); 314 else if ((errno == ERANGE) 315 || ((bits < 64) && (val >= (1ULL << bits)))) 316 yyerror("literal out of range"); 317 else if (errno != 0) 318 yyerror("bad literal"); 319 return val; 320} 321