dtc-parser.y 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. #include <stdio.h>
  22. #include "dtc.h"
  23. #include "srcpos.h"
  24. YYLTYPE yylloc;
  25. extern int yylex(void);
  26. extern void print_error(char const *fmt, ...);
  27. extern void yyerror(char const *s);
  28. extern struct boot_info *the_boot_info;
  29. extern int treesource_error;
  30. static unsigned long long eval_literal(const char *s, int base, int bits);
  31. static unsigned char eval_char_literal(const char *s);
  32. %}
  33. %union {
  34. char *propnodename;
  35. char *literal;
  36. char *labelref;
  37. unsigned int cbase;
  38. uint8_t byte;
  39. struct data data;
  40. struct {
  41. struct data data;
  42. int bits;
  43. } array;
  44. struct property *prop;
  45. struct property *proplist;
  46. struct node *node;
  47. struct node *nodelist;
  48. struct reserve_info *re;
  49. uint64_t integer;
  50. }
  51. %token DT_V1
  52. %token DT_MEMRESERVE
  53. %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
  54. %token DT_BITS
  55. %token DT_DEL_PROP
  56. %token DT_DEL_NODE
  57. %token <propnodename> DT_PROPNODENAME
  58. %token <literal> DT_LITERAL
  59. %token <literal> DT_CHAR_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. %type <data> propdata
  67. %type <data> propdataprefix
  68. %type <re> memreserve
  69. %type <re> memreserves
  70. %type <array> arrayprefix
  71. %type <data> bytestring
  72. %type <prop> propdef
  73. %type <proplist> proplist
  74. %type <node> devicetree
  75. %type <node> nodedef
  76. %type <node> subnode
  77. %type <nodelist> subnodes
  78. %type <integer> integer_prim
  79. %type <integer> integer_unary
  80. %type <integer> integer_mul
  81. %type <integer> integer_add
  82. %type <integer> integer_shift
  83. %type <integer> integer_rela
  84. %type <integer> integer_eq
  85. %type <integer> integer_bitand
  86. %type <integer> integer_bitxor
  87. %type <integer> integer_bitor
  88. %type <integer> integer_and
  89. %type <integer> integer_or
  90. %type <integer> integer_trinary
  91. %type <integer> integer_expr
  92. %%
  93. sourcefile:
  94. DT_V1 ';' memreserves devicetree
  95. {
  96. the_boot_info = build_boot_info($3, $4,
  97. guess_boot_cpuid($4));
  98. }
  99. ;
  100. memreserves:
  101. /* empty */
  102. {
  103. $$ = NULL;
  104. }
  105. | memreserve memreserves
  106. {
  107. $$ = chain_reserve_entry($1, $2);
  108. }
  109. ;
  110. memreserve:
  111. DT_MEMRESERVE integer_prim integer_prim ';'
  112. {
  113. $$ = build_reserve_entry($2, $3);
  114. }
  115. | DT_LABEL memreserve
  116. {
  117. add_label(&$2->labels, $1);
  118. $$ = $2;
  119. }
  120. ;
  121. devicetree:
  122. '/' nodedef
  123. {
  124. $$ = name_node($2, "");
  125. }
  126. | devicetree '/' nodedef
  127. {
  128. $$ = merge_nodes($1, $3);
  129. }
  130. | devicetree DT_REF nodedef
  131. {
  132. struct node *target = get_node_by_ref($1, $2);
  133. if (target)
  134. merge_nodes(target, $3);
  135. else
  136. print_error("label or path, '%s', not found", $2);
  137. $$ = $1;
  138. }
  139. | devicetree DT_DEL_NODE DT_REF ';'
  140. {
  141. struct node *target = get_node_by_ref($1, $3);
  142. if (!target)
  143. print_error("label or path, '%s', not found", $3);
  144. else
  145. delete_node(target);
  146. $$ = $1;
  147. }
  148. ;
  149. nodedef:
  150. '{' proplist subnodes '}' ';'
  151. {
  152. $$ = build_node($2, $3);
  153. }
  154. ;
  155. proplist:
  156. /* empty */
  157. {
  158. $$ = NULL;
  159. }
  160. | proplist propdef
  161. {
  162. $$ = chain_property($2, $1);
  163. }
  164. ;
  165. propdef:
  166. DT_PROPNODENAME '=' propdata ';'
  167. {
  168. $$ = build_property($1, $3);
  169. }
  170. | DT_PROPNODENAME ';'
  171. {
  172. $$ = build_property($1, empty_data);
  173. }
  174. | DT_DEL_PROP DT_PROPNODENAME ';'
  175. {
  176. $$ = build_property_delete($2);
  177. }
  178. | DT_LABEL propdef
  179. {
  180. add_label(&$2->labels, $1);
  181. $$ = $2;
  182. }
  183. ;
  184. propdata:
  185. propdataprefix DT_STRING
  186. {
  187. $$ = data_merge($1, $2);
  188. }
  189. | propdataprefix arrayprefix '>'
  190. {
  191. $$ = data_merge($1, $2.data);
  192. }
  193. | propdataprefix '[' bytestring ']'
  194. {
  195. $$ = data_merge($1, $3);
  196. }
  197. | propdataprefix DT_REF
  198. {
  199. $$ = data_add_marker($1, REF_PATH, $2);
  200. }
  201. | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
  202. {
  203. FILE *f = srcfile_relative_open($4.val, NULL);
  204. struct data d;
  205. if ($6 != 0)
  206. if (fseek(f, $6, SEEK_SET) != 0)
  207. print_error("Couldn't seek to offset %llu in \"%s\": %s",
  208. (unsigned long long)$6,
  209. $4.val,
  210. strerror(errno));
  211. d = data_copy_file(f, $8);
  212. $$ = data_merge($1, d);
  213. fclose(f);
  214. }
  215. | propdataprefix DT_INCBIN '(' DT_STRING ')'
  216. {
  217. FILE *f = srcfile_relative_open($4.val, NULL);
  218. struct data d = empty_data;
  219. d = data_copy_file(f, -1);
  220. $$ = data_merge($1, d);
  221. fclose(f);
  222. }
  223. | propdata DT_LABEL
  224. {
  225. $$ = data_add_marker($1, LABEL, $2);
  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. arrayprefix:
  243. DT_BITS DT_LITERAL '<'
  244. {
  245. $$.data = empty_data;
  246. $$.bits = eval_literal($2, 0, 7);
  247. if (($$.bits != 8) &&
  248. ($$.bits != 16) &&
  249. ($$.bits != 32) &&
  250. ($$.bits != 64))
  251. {
  252. print_error("Only 8, 16, 32 and 64-bit elements"
  253. " are currently supported");
  254. $$.bits = 32;
  255. }
  256. }
  257. | '<'
  258. {
  259. $$.data = empty_data;
  260. $$.bits = 32;
  261. }
  262. | arrayprefix integer_prim
  263. {
  264. if ($1.bits < 64) {
  265. uint64_t mask = (1ULL << $1.bits) - 1;
  266. /*
  267. * Bits above mask must either be all zero
  268. * (positive within range of mask) or all one
  269. * (negative and sign-extended). The second
  270. * condition is true if when we set all bits
  271. * within the mask to one (i.e. | in the
  272. * mask), all bits are one.
  273. */
  274. if (($2 > mask) && (($2 | mask) != -1ULL))
  275. print_error(
  276. "integer value out of range "
  277. "%016lx (%d bits)", $1.bits);
  278. }
  279. $$.data = data_append_integer($1.data, $2, $1.bits);
  280. }
  281. | arrayprefix DT_REF
  282. {
  283. uint64_t val = ~0ULL >> (64 - $1.bits);
  284. if ($1.bits == 32)
  285. $1.data = data_add_marker($1.data,
  286. REF_PHANDLE,
  287. $2);
  288. else
  289. print_error("References are only allowed in "
  290. "arrays with 32-bit elements.");
  291. $$.data = data_append_integer($1.data, val, $1.bits);
  292. }
  293. | arrayprefix DT_LABEL
  294. {
  295. $$.data = data_add_marker($1.data, LABEL, $2);
  296. }
  297. ;
  298. integer_prim:
  299. DT_LITERAL
  300. {
  301. $$ = eval_literal($1, 0, 64);
  302. }
  303. | DT_CHAR_LITERAL
  304. {
  305. $$ = eval_char_literal($1);
  306. }
  307. | '(' integer_expr ')'
  308. {
  309. $$ = $2;
  310. }
  311. ;
  312. integer_expr:
  313. integer_trinary
  314. ;
  315. integer_trinary:
  316. integer_or
  317. | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
  318. ;
  319. integer_or:
  320. integer_and
  321. | integer_or DT_OR integer_and { $$ = $1 || $3; }
  322. ;
  323. integer_and:
  324. integer_bitor
  325. | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
  326. ;
  327. integer_bitor:
  328. integer_bitxor
  329. | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
  330. ;
  331. integer_bitxor:
  332. integer_bitand
  333. | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
  334. ;
  335. integer_bitand:
  336. integer_eq
  337. | integer_bitand '&' integer_eq { $$ = $1 & $3; }
  338. ;
  339. integer_eq:
  340. integer_rela
  341. | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
  342. | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
  343. ;
  344. integer_rela:
  345. integer_shift
  346. | integer_rela '<' integer_shift { $$ = $1 < $3; }
  347. | integer_rela '>' integer_shift { $$ = $1 > $3; }
  348. | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
  349. | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
  350. ;
  351. integer_shift:
  352. integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
  353. | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
  354. | integer_add
  355. ;
  356. integer_add:
  357. integer_add '+' integer_mul { $$ = $1 + $3; }
  358. | integer_add '-' integer_mul { $$ = $1 - $3; }
  359. | integer_mul
  360. ;
  361. integer_mul:
  362. integer_mul '*' integer_unary { $$ = $1 * $3; }
  363. | integer_mul '/' integer_unary { $$ = $1 / $3; }
  364. | integer_mul '%' integer_unary { $$ = $1 % $3; }
  365. | integer_unary
  366. ;
  367. integer_unary:
  368. integer_prim
  369. | '-' integer_unary { $$ = -$2; }
  370. | '~' integer_unary { $$ = ~$2; }
  371. | '!' integer_unary { $$ = !$2; }
  372. ;
  373. bytestring:
  374. /* empty */
  375. {
  376. $$ = empty_data;
  377. }
  378. | bytestring DT_BYTE
  379. {
  380. $$ = data_append_byte($1, $2);
  381. }
  382. | bytestring DT_LABEL
  383. {
  384. $$ = data_add_marker($1, LABEL, $2);
  385. }
  386. ;
  387. subnodes:
  388. /* empty */
  389. {
  390. $$ = NULL;
  391. }
  392. | subnode subnodes
  393. {
  394. $$ = chain_node($1, $2);
  395. }
  396. | subnode propdef
  397. {
  398. print_error("syntax error: properties must precede subnodes");
  399. YYERROR;
  400. }
  401. ;
  402. subnode:
  403. DT_PROPNODENAME nodedef
  404. {
  405. $$ = name_node($2, $1);
  406. }
  407. | DT_DEL_NODE DT_PROPNODENAME ';'
  408. {
  409. $$ = name_node(build_node_delete(), $2);
  410. }
  411. | DT_LABEL subnode
  412. {
  413. add_label(&$2->labels, $1);
  414. $$ = $2;
  415. }
  416. ;
  417. %%
  418. void print_error(char const *fmt, ...)
  419. {
  420. va_list va;
  421. va_start(va, fmt);
  422. srcpos_verror(&yylloc, fmt, va);
  423. va_end(va);
  424. treesource_error = 1;
  425. }
  426. void yyerror(char const *s) {
  427. print_error("%s", s);
  428. }
  429. static unsigned long long eval_literal(const char *s, int base, int bits)
  430. {
  431. unsigned long long val;
  432. char *e;
  433. errno = 0;
  434. val = strtoull(s, &e, base);
  435. if (*e) {
  436. size_t uls = strspn(e, "UL");
  437. if (e[uls])
  438. print_error("bad characters in literal");
  439. }
  440. if ((errno == ERANGE)
  441. || ((bits < 64) && (val >= (1ULL << bits))))
  442. print_error("literal out of range");
  443. else if (errno != 0)
  444. print_error("bad literal");
  445. return val;
  446. }
  447. static unsigned char eval_char_literal(const char *s)
  448. {
  449. int i = 1;
  450. char c = s[0];
  451. if (c == '\0')
  452. {
  453. print_error("empty character literal");
  454. return 0;
  455. }
  456. /*
  457. * If the first character in the character literal is a \ then process
  458. * the remaining characters as an escape encoding. If the first
  459. * character is neither an escape or a terminator it should be the only
  460. * character in the literal and will be returned.
  461. */
  462. if (c == '\\')
  463. c = get_escape_char(s, &i);
  464. if (s[i] != '\0')
  465. print_error("malformed character literal");
  466. return c;
  467. }