dtc-parser.y 11 KB

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