dtc-parser.y 11 KB

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