dtc-parser.y 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  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 <inttypes.h>
  23. #include "dtc.h"
  24. #include "srcpos.h"
  25. extern int yylex(void);
  26. extern void yyerror(char const *s);
  27. #define ERROR(loc, ...) \
  28. do { \
  29. srcpos_error((loc), "Error", __VA_ARGS__); \
  30. treesource_error = true; \
  31. } while (0)
  32. extern struct dt_info *parser_output;
  33. extern bool treesource_error;
  34. %}
  35. %union {
  36. char *propnodename;
  37. char *labelref;
  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. unsigned int flags;
  51. }
  52. %token DT_V1
  53. %token DT_PLUGIN
  54. %token DT_MEMRESERVE
  55. %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
  56. %token DT_BITS
  57. %token DT_DEL_PROP
  58. %token DT_DEL_NODE
  59. %token DT_OMIT_NO_REF
  60. %token <propnodename> DT_PROPNODENAME
  61. %token <integer> DT_LITERAL
  62. %token <integer> DT_CHAR_LITERAL
  63. %token <byte> DT_BYTE
  64. %token <data> DT_STRING
  65. %token <labelref> DT_LABEL
  66. %token <labelref> DT_REF
  67. %token DT_INCBIN
  68. %type <data> propdata
  69. %type <data> propdataprefix
  70. %type <flags> header
  71. %type <flags> headers
  72. %type <re> memreserve
  73. %type <re> memreserves
  74. %type <array> arrayprefix
  75. %type <data> bytestring
  76. %type <prop> propdef
  77. %type <proplist> proplist
  78. %type <node> devicetree
  79. %type <node> nodedef
  80. %type <node> subnode
  81. %type <nodelist> subnodes
  82. %type <integer> integer_prim
  83. %type <integer> integer_unary
  84. %type <integer> integer_mul
  85. %type <integer> integer_add
  86. %type <integer> integer_shift
  87. %type <integer> integer_rela
  88. %type <integer> integer_eq
  89. %type <integer> integer_bitand
  90. %type <integer> integer_bitxor
  91. %type <integer> integer_bitor
  92. %type <integer> integer_and
  93. %type <integer> integer_or
  94. %type <integer> integer_trinary
  95. %type <integer> integer_expr
  96. %%
  97. sourcefile:
  98. headers memreserves devicetree
  99. {
  100. parser_output = build_dt_info($1, $2, $3,
  101. guess_boot_cpuid($3));
  102. }
  103. ;
  104. header:
  105. DT_V1 ';'
  106. {
  107. $$ = DTSF_V1;
  108. }
  109. | DT_V1 ';' DT_PLUGIN ';'
  110. {
  111. $$ = DTSF_V1 | DTSF_PLUGIN;
  112. }
  113. ;
  114. headers:
  115. header
  116. | header headers
  117. {
  118. if ($2 != $1)
  119. ERROR(&@2, "Header flags don't match earlier ones");
  120. $$ = $1;
  121. }
  122. ;
  123. memreserves:
  124. /* empty */
  125. {
  126. $$ = NULL;
  127. }
  128. | memreserve memreserves
  129. {
  130. $$ = chain_reserve_entry($1, $2);
  131. }
  132. ;
  133. memreserve:
  134. DT_MEMRESERVE integer_prim integer_prim ';'
  135. {
  136. $$ = build_reserve_entry($2, $3);
  137. }
  138. | DT_LABEL memreserve
  139. {
  140. add_label(&$2->labels, $1);
  141. $$ = $2;
  142. }
  143. ;
  144. devicetree:
  145. '/' nodedef
  146. {
  147. $$ = name_node($2, "");
  148. }
  149. | devicetree '/' nodedef
  150. {
  151. $$ = merge_nodes($1, $3);
  152. }
  153. | DT_REF nodedef
  154. {
  155. /*
  156. * We rely on the rule being always:
  157. * versioninfo plugindecl memreserves devicetree
  158. * so $-1 is what we want (plugindecl)
  159. */
  160. if (!($<flags>-1 & DTSF_PLUGIN))
  161. ERROR(&@2, "Label or path %s not found", $1);
  162. $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
  163. }
  164. | devicetree DT_LABEL DT_REF nodedef
  165. {
  166. struct node *target = get_node_by_ref($1, $3);
  167. if (target) {
  168. add_label(&target->labels, $2);
  169. merge_nodes(target, $4);
  170. } else
  171. ERROR(&@3, "Label or path %s not found", $3);
  172. $$ = $1;
  173. }
  174. | devicetree DT_REF nodedef
  175. {
  176. /*
  177. * We rely on the rule being always:
  178. * versioninfo plugindecl memreserves devicetree
  179. * so $-1 is what we want (plugindecl)
  180. */
  181. if ($<flags>-1 & DTSF_PLUGIN) {
  182. add_orphan_node($1, $3, $2);
  183. } else {
  184. struct node *target = get_node_by_ref($1, $2);
  185. if (target)
  186. merge_nodes(target, $3);
  187. else
  188. ERROR(&@2, "Label or path %s not found", $2);
  189. }
  190. $$ = $1;
  191. }
  192. | devicetree DT_DEL_NODE DT_REF ';'
  193. {
  194. struct node *target = get_node_by_ref($1, $3);
  195. if (target)
  196. delete_node(target);
  197. else
  198. ERROR(&@3, "Label or path %s not found", $3);
  199. $$ = $1;
  200. }
  201. | devicetree DT_OMIT_NO_REF DT_REF ';'
  202. {
  203. struct node *target = get_node_by_ref($1, $3);
  204. if (target)
  205. omit_node_if_unused(target);
  206. else
  207. ERROR(&@3, "Label or path %s not found", $3);
  208. $$ = $1;
  209. }
  210. ;
  211. nodedef:
  212. '{' proplist subnodes '}' ';'
  213. {
  214. $$ = build_node($2, $3);
  215. }
  216. ;
  217. proplist:
  218. /* empty */
  219. {
  220. $$ = NULL;
  221. }
  222. | proplist propdef
  223. {
  224. $$ = chain_property($2, $1);
  225. }
  226. ;
  227. propdef:
  228. DT_PROPNODENAME '=' propdata ';'
  229. {
  230. $$ = build_property($1, $3);
  231. }
  232. | DT_PROPNODENAME ';'
  233. {
  234. $$ = build_property($1, empty_data);
  235. }
  236. | DT_DEL_PROP DT_PROPNODENAME ';'
  237. {
  238. $$ = build_property_delete($2);
  239. }
  240. | DT_LABEL propdef
  241. {
  242. add_label(&$2->labels, $1);
  243. $$ = $2;
  244. }
  245. ;
  246. propdata:
  247. propdataprefix DT_STRING
  248. {
  249. $$ = data_merge($1, $2);
  250. }
  251. | propdataprefix arrayprefix '>'
  252. {
  253. $$ = data_merge($1, $2.data);
  254. }
  255. | propdataprefix '[' bytestring ']'
  256. {
  257. $$ = data_merge($1, $3);
  258. }
  259. | propdataprefix DT_REF
  260. {
  261. $$ = data_add_marker($1, REF_PATH, $2);
  262. }
  263. | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
  264. {
  265. FILE *f = srcfile_relative_open($4.val, NULL);
  266. struct data d;
  267. if ($6 != 0)
  268. if (fseek(f, $6, SEEK_SET) != 0)
  269. die("Couldn't seek to offset %llu in \"%s\": %s",
  270. (unsigned long long)$6, $4.val,
  271. strerror(errno));
  272. d = data_copy_file(f, $8);
  273. $$ = data_merge($1, d);
  274. fclose(f);
  275. }
  276. | propdataprefix DT_INCBIN '(' DT_STRING ')'
  277. {
  278. FILE *f = srcfile_relative_open($4.val, NULL);
  279. struct data d = empty_data;
  280. d = data_copy_file(f, -1);
  281. $$ = data_merge($1, d);
  282. fclose(f);
  283. }
  284. | propdata DT_LABEL
  285. {
  286. $$ = data_add_marker($1, LABEL, $2);
  287. }
  288. ;
  289. propdataprefix:
  290. /* empty */
  291. {
  292. $$ = empty_data;
  293. }
  294. | propdata ','
  295. {
  296. $$ = $1;
  297. }
  298. | propdataprefix DT_LABEL
  299. {
  300. $$ = data_add_marker($1, LABEL, $2);
  301. }
  302. ;
  303. arrayprefix:
  304. DT_BITS DT_LITERAL '<'
  305. {
  306. unsigned long long bits;
  307. bits = $2;
  308. if ((bits != 8) && (bits != 16) &&
  309. (bits != 32) && (bits != 64)) {
  310. ERROR(&@2, "Array elements must be"
  311. " 8, 16, 32 or 64-bits");
  312. bits = 32;
  313. }
  314. $$.data = empty_data;
  315. $$.bits = bits;
  316. }
  317. | '<'
  318. {
  319. $$.data = empty_data;
  320. $$.bits = 32;
  321. }
  322. | arrayprefix integer_prim
  323. {
  324. if ($1.bits < 64) {
  325. uint64_t mask = (1ULL << $1.bits) - 1;
  326. /*
  327. * Bits above mask must either be all zero
  328. * (positive within range of mask) or all one
  329. * (negative and sign-extended). The second
  330. * condition is true if when we set all bits
  331. * within the mask to one (i.e. | in the
  332. * mask), all bits are one.
  333. */
  334. if (($2 > mask) && (($2 | mask) != -1ULL))
  335. ERROR(&@2, "Value out of range for"
  336. " %d-bit array element", $1.bits);
  337. }
  338. $$.data = data_append_integer($1.data, $2, $1.bits);
  339. }
  340. | arrayprefix DT_REF
  341. {
  342. uint64_t val = ~0ULL >> (64 - $1.bits);
  343. if ($1.bits == 32)
  344. $1.data = data_add_marker($1.data,
  345. REF_PHANDLE,
  346. $2);
  347. else
  348. ERROR(&@2, "References are only allowed in "
  349. "arrays with 32-bit elements.");
  350. $$.data = data_append_integer($1.data, val, $1.bits);
  351. }
  352. | arrayprefix DT_LABEL
  353. {
  354. $$.data = data_add_marker($1.data, LABEL, $2);
  355. }
  356. ;
  357. integer_prim:
  358. DT_LITERAL
  359. | DT_CHAR_LITERAL
  360. | '(' integer_expr ')'
  361. {
  362. $$ = $2;
  363. }
  364. ;
  365. integer_expr:
  366. integer_trinary
  367. ;
  368. integer_trinary:
  369. integer_or
  370. | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
  371. ;
  372. integer_or:
  373. integer_and
  374. | integer_or DT_OR integer_and { $$ = $1 || $3; }
  375. ;
  376. integer_and:
  377. integer_bitor
  378. | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
  379. ;
  380. integer_bitor:
  381. integer_bitxor
  382. | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
  383. ;
  384. integer_bitxor:
  385. integer_bitand
  386. | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
  387. ;
  388. integer_bitand:
  389. integer_eq
  390. | integer_bitand '&' integer_eq { $$ = $1 & $3; }
  391. ;
  392. integer_eq:
  393. integer_rela
  394. | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
  395. | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
  396. ;
  397. integer_rela:
  398. integer_shift
  399. | integer_rela '<' integer_shift { $$ = $1 < $3; }
  400. | integer_rela '>' integer_shift { $$ = $1 > $3; }
  401. | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
  402. | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
  403. ;
  404. integer_shift:
  405. integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
  406. | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
  407. | integer_add
  408. ;
  409. integer_add:
  410. integer_add '+' integer_mul { $$ = $1 + $3; }
  411. | integer_add '-' integer_mul { $$ = $1 - $3; }
  412. | integer_mul
  413. ;
  414. integer_mul:
  415. integer_mul '*' integer_unary { $$ = $1 * $3; }
  416. | integer_mul '/' integer_unary
  417. {
  418. if ($3 != 0) {
  419. $$ = $1 / $3;
  420. } else {
  421. ERROR(&@$, "Division by zero");
  422. $$ = 0;
  423. }
  424. }
  425. | integer_mul '%' integer_unary
  426. {
  427. if ($3 != 0) {
  428. $$ = $1 % $3;
  429. } else {
  430. ERROR(&@$, "Division by zero");
  431. $$ = 0;
  432. }
  433. }
  434. | integer_unary
  435. ;
  436. integer_unary:
  437. integer_prim
  438. | '-' integer_unary { $$ = -$2; }
  439. | '~' integer_unary { $$ = ~$2; }
  440. | '!' integer_unary { $$ = !$2; }
  441. ;
  442. bytestring:
  443. /* empty */
  444. {
  445. $$ = empty_data;
  446. }
  447. | bytestring DT_BYTE
  448. {
  449. $$ = data_append_byte($1, $2);
  450. }
  451. | bytestring DT_LABEL
  452. {
  453. $$ = data_add_marker($1, LABEL, $2);
  454. }
  455. ;
  456. subnodes:
  457. /* empty */
  458. {
  459. $$ = NULL;
  460. }
  461. | subnode subnodes
  462. {
  463. $$ = chain_node($1, $2);
  464. }
  465. | subnode propdef
  466. {
  467. ERROR(&@2, "Properties must precede subnodes");
  468. YYERROR;
  469. }
  470. ;
  471. subnode:
  472. DT_PROPNODENAME nodedef
  473. {
  474. $$ = name_node($2, $1);
  475. }
  476. | DT_DEL_NODE DT_PROPNODENAME ';'
  477. {
  478. $$ = name_node(build_node_delete(), $2);
  479. }
  480. | DT_OMIT_NO_REF subnode
  481. {
  482. $$ = omit_node_if_unused($2);
  483. }
  484. | DT_LABEL subnode
  485. {
  486. add_label(&$2->labels, $1);
  487. $$ = $2;
  488. }
  489. ;
  490. %%
  491. void yyerror(char const *s)
  492. {
  493. ERROR(&yylloc, "%s", s);
  494. }