dtc-parser.y 6.4 KB

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