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