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 #include <stdio.h> 23 24 #include "dtc.h" 25 #include "srcpos.h" 26 27 YYLTYPE yylloc; 28 29 extern int yylex(void); 30 extern void print_error(char const *fmt, ...); 31 extern void yyerror(char const *s); 32 33 extern struct boot_info *the_boot_info; 34 extern int treesource_error; 35 36 static 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 83 %% 84 85 sourcefile: 86 DT_V1 ';' memreserves devicetree 87 { 88 the_boot_info = build_boot_info($3, $4, 89 guess_boot_cpuid($4)); 90 } 91 ; 92 93 memreserves: 94 /* empty */ 95 { 96 $$ = NULL; 97 } 98 | memreserve memreserves 99 { 100 $$ = chain_reserve_entry($1, $2); 101 } 102 ; 103 104 memreserve: 105 DT_MEMRESERVE addr addr ';' 106 { 107 $$ = build_reserve_entry($2, $3); 108 } 109 | DT_LABEL memreserve 110 { 111 add_label(&$2->labels, $1); 112 $$ = $2; 113 } 114 ; 115 116 addr: 117 DT_LITERAL 118 { 119 $$ = eval_literal($1, 0, 64); 120 } 121 ; 122 123 devicetree: 124 '/' nodedef 125 { 126 $$ = name_node($2, ""); 127 } 128 | devicetree '/' nodedef 129 { 130 $$ = merge_nodes($1, $3); 131 } 132 | devicetree DT_REF nodedef 133 { 134 struct node *target = get_node_by_ref($1, $2); 135 136 if (target) 137 merge_nodes(target, $3); 138 else 139 print_error("label or path, '%s', not found", $2); 140 $$ = $1; 141 } 142 ; 143 144 nodedef: 145 '{' proplist subnodes '}' ';' 146 { 147 $$ = build_node($2, $3); 148 } 149 ; 150 151 proplist: 152 /* empty */ 153 { 154 $$ = NULL; 155 } 156 | proplist propdef 157 { 158 $$ = chain_property($2, $1); 159 } 160 ; 161 162 propdef: 163 DT_PROPNODENAME '=' propdata ';' 164 { 165 $$ = build_property($1, $3); 166 } 167 | DT_PROPNODENAME ';' 168 { 169 $$ = build_property($1, empty_data); 170 } 171 | DT_LABEL propdef 172 { 173 add_label(&$2->labels, $1); 174 $$ = $2; 175 } 176 ; 177 178 propdata: 179 propdataprefix DT_STRING 180 { 181 $$ = data_merge($1, $2); 182 } 183 | propdataprefix '<' celllist '>' 184 { 185 $$ = data_merge($1, $3); 186 } 187 | propdataprefix '[' bytestring ']' 188 { 189 $$ = data_merge($1, $3); 190 } 191 | propdataprefix DT_REF 192 { 193 $$ = data_add_marker($1, REF_PATH, $2); 194 } 195 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' 196 { 197 FILE *f = srcfile_relative_open($4.val, NULL); 198 struct data d; 199 200 if ($6 != 0) 201 if (fseek(f, $6, SEEK_SET) != 0) 202 print_error("Couldn't seek to offset %llu in \"%s\": %s", 203 (unsigned long long)$6, 204 $4.val, 205 strerror(errno)); 206 207 d = data_copy_file(f, $8); 208 209 $$ = data_merge($1, d); 210 fclose(f); 211 } 212 | propdataprefix DT_INCBIN '(' DT_STRING ')' 213 { 214 FILE *f = srcfile_relative_open($4.val, NULL); 215 struct data d = empty_data; 216 217 d = data_copy_file(f, -1); 218 219 $$ = data_merge($1, d); 220 fclose(f); 221 } 222 | propdata DT_LABEL 223 { 224 $$ = data_add_marker($1, LABEL, $2); 225 } 226 ; 227 228 propdataprefix: 229 /* empty */ 230 { 231 $$ = empty_data; 232 } 233 | propdata ',' 234 { 235 $$ = $1; 236 } 237 | propdataprefix DT_LABEL 238 { 239 $$ = data_add_marker($1, LABEL, $2); 240 } 241 ; 242 243 celllist: 244 /* empty */ 245 { 246 $$ = empty_data; 247 } 248 | celllist cellval 249 { 250 $$ = data_append_cell($1, $2); 251 } 252 | celllist DT_REF 253 { 254 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, 255 $2), -1); 256 } 257 | celllist DT_LABEL 258 { 259 $$ = data_add_marker($1, LABEL, $2); 260 } 261 ; 262 263 cellval: 264 DT_LITERAL 265 { 266 $$ = eval_literal($1, 0, 32); 267 } 268 ; 269 270 bytestring: 271 /* empty */ 272 { 273 $$ = empty_data; 274 } 275 | bytestring DT_BYTE 276 { 277 $$ = data_append_byte($1, $2); 278 } 279 | bytestring DT_LABEL 280 { 281 $$ = data_add_marker($1, LABEL, $2); 282 } 283 ; 284 285 subnodes: 286 /* empty */ 287 { 288 $$ = NULL; 289 } 290 | subnode subnodes 291 { 292 $$ = chain_node($1, $2); 293 } 294 | subnode propdef 295 { 296 print_error("syntax error: properties must precede subnodes"); 297 YYERROR; 298 } 299 ; 300 301 subnode: 302 DT_PROPNODENAME nodedef 303 { 304 $$ = name_node($2, $1); 305 } 306 | DT_LABEL subnode 307 { 308 add_label(&$2->labels, $1); 309 $$ = $2; 310 } 311 ; 312 313 %% 314 315 void print_error(char const *fmt, ...) 316 { 317 va_list va; 318 319 va_start(va, fmt); 320 srcpos_verror(&yylloc, fmt, va); 321 va_end(va); 322 323 treesource_error = 1; 324 } 325 326 void yyerror(char const *s) { 327 print_error("%s", s); 328 } 329 330 static unsigned long long eval_literal(const char *s, int base, int bits) 331 { 332 unsigned long long val; 333 char *e; 334 335 errno = 0; 336 val = strtoull(s, &e, base); 337 if (*e) 338 print_error("bad characters in literal"); 339 else if ((errno == ERANGE) 340 || ((bits < 64) && (val >= (1ULL << bits)))) 341 print_error("literal out of range"); 342 else if (errno != 0) 343 print_error("bad literal"); 344 return val; 345 } 346