test_dtoc.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. #!/usr/bin/env python3
  2. # SPDX-License-Identifier: GPL-2.0+
  3. # Copyright (c) 2012 The Chromium OS Authors.
  4. #
  5. """Tests for the dtb_platdata module
  6. This includes unit tests for some functions and functional tests for the dtoc
  7. tool.
  8. """
  9. from __future__ import print_function
  10. import collections
  11. import os
  12. import struct
  13. import unittest
  14. import dtb_platdata
  15. from dtb_platdata import conv_name_to_c
  16. from dtb_platdata import get_compat_name
  17. from dtb_platdata import get_value
  18. from dtb_platdata import tab_to
  19. import fdt
  20. import fdt_util
  21. import test_util
  22. import tools
  23. our_path = os.path.dirname(os.path.realpath(__file__))
  24. HEADER = '''/*
  25. * DO NOT MODIFY
  26. *
  27. * This file was generated by dtoc from a .dtb (device tree binary) file.
  28. */
  29. #include <stdbool.h>
  30. #include <linux/libfdt.h>'''
  31. C_HEADER = '''/*
  32. * DO NOT MODIFY
  33. *
  34. * This file was generated by dtoc from a .dtb (device tree binary) file.
  35. */
  36. #include <common.h>
  37. #include <dm.h>
  38. #include <dt-structs.h>
  39. '''
  40. def get_dtb_file(dts_fname, capture_stderr=False):
  41. """Compile a .dts file to a .dtb
  42. Args:
  43. dts_fname: Filename of .dts file in the current directory
  44. capture_stderr: True to capture and discard stderr output
  45. Returns:
  46. Filename of compiled file in output directory
  47. """
  48. return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname),
  49. capture_stderr=capture_stderr)
  50. class TestDtoc(unittest.TestCase):
  51. """Tests for dtoc"""
  52. @classmethod
  53. def setUpClass(cls):
  54. tools.PrepareOutputDir(None)
  55. @classmethod
  56. def tearDownClass(cls):
  57. tools._RemoveOutputDir()
  58. def _WritePythonString(self, fname, data):
  59. """Write a string with tabs expanded as done in this Python file
  60. Args:
  61. fname: Filename to write to
  62. data: Raw string to convert
  63. """
  64. data = data.replace('\t', '\\t')
  65. with open(fname, 'w') as fd:
  66. fd.write(data)
  67. def _CheckStrings(self, expected, actual):
  68. """Check that a string matches its expected value
  69. If the strings do not match, they are written to the /tmp directory in
  70. the same Python format as is used here in the test. This allows for
  71. easy comparison and update of the tests.
  72. Args:
  73. expected: Expected string
  74. actual: Actual string
  75. """
  76. if expected != actual:
  77. self._WritePythonString('/tmp/binman.expected', expected)
  78. self._WritePythonString('/tmp/binman.actual', actual)
  79. print('Failures written to /tmp/binman.{expected,actual}')
  80. self.assertEquals(expected, actual)
  81. def test_name(self):
  82. """Test conversion of device tree names to C identifiers"""
  83. self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12'))
  84. self.assertEqual('vendor_clock_frequency',
  85. conv_name_to_c('vendor,clock-frequency'))
  86. self.assertEqual('rockchip_rk3399_sdhci_5_1',
  87. conv_name_to_c('rockchip,rk3399-sdhci-5.1'))
  88. def test_tab_to(self):
  89. """Test operation of tab_to() function"""
  90. self.assertEqual('fred ', tab_to(0, 'fred'))
  91. self.assertEqual('fred\t', tab_to(1, 'fred'))
  92. self.assertEqual('fred was here ', tab_to(1, 'fred was here'))
  93. self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here'))
  94. self.assertEqual('exactly8 ', tab_to(1, 'exactly8'))
  95. self.assertEqual('exactly8\t', tab_to(2, 'exactly8'))
  96. def test_get_value(self):
  97. """Test operation of get_value() function"""
  98. self.assertEqual('0x45',
  99. get_value(fdt.TYPE_INT, struct.pack('>I', 0x45)))
  100. self.assertEqual('0x45',
  101. get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45)))
  102. self.assertEqual('0x0',
  103. get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45)))
  104. self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test'))
  105. self.assertEqual('true', get_value(fdt.TYPE_BOOL, None))
  106. def test_get_compat_name(self):
  107. """Test operation of get_compat_name() function"""
  108. Prop = collections.namedtuple('Prop', ['value'])
  109. Node = collections.namedtuple('Node', ['props'])
  110. prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1'])
  111. node = Node({'compatible': prop})
  112. self.assertEqual(('rockchip_rk3399_sdhci_5_1', ['arasan_sdhci_5_1']),
  113. get_compat_name(node))
  114. prop = Prop(['rockchip,rk3399-sdhci-5.1'])
  115. node = Node({'compatible': prop})
  116. self.assertEqual(('rockchip_rk3399_sdhci_5_1', []),
  117. get_compat_name(node))
  118. prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third'])
  119. node = Node({'compatible': prop})
  120. self.assertEqual(('rockchip_rk3399_sdhci_5_1',
  121. ['arasan_sdhci_5_1', 'third']),
  122. get_compat_name(node))
  123. def test_empty_file(self):
  124. """Test output from a device tree file with no nodes"""
  125. dtb_file = get_dtb_file('dtoc_test_empty.dts')
  126. output = tools.GetOutputFilename('output')
  127. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  128. with open(output) as infile:
  129. lines = infile.read().splitlines()
  130. self.assertEqual(HEADER.splitlines(), lines)
  131. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  132. with open(output) as infile:
  133. lines = infile.read().splitlines()
  134. self.assertEqual(C_HEADER.splitlines() + [''], lines)
  135. def test_simple(self):
  136. """Test output from some simple nodes with various types of data"""
  137. dtb_file = get_dtb_file('dtoc_test_simple.dts')
  138. output = tools.GetOutputFilename('output')
  139. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  140. with open(output) as infile:
  141. data = infile.read()
  142. self._CheckStrings(HEADER + '''
  143. struct dtd_sandbox_i2c_test {
  144. };
  145. struct dtd_sandbox_pmic_test {
  146. \tbool\t\tlow_power;
  147. \tfdt64_t\t\treg[2];
  148. };
  149. struct dtd_sandbox_spl_test {
  150. \tbool\t\tboolval;
  151. \tunsigned char\tbytearray[3];
  152. \tunsigned char\tbyteval;
  153. \tfdt32_t\t\tintarray[4];
  154. \tfdt32_t\t\tintval;
  155. \tunsigned char\tlongbytearray[9];
  156. \tunsigned char\tnotstring[5];
  157. \tconst char *\tstringarray[3];
  158. \tconst char *\tstringval;
  159. };
  160. struct dtd_sandbox_spl_test_2 {
  161. };
  162. ''', data)
  163. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  164. with open(output) as infile:
  165. data = infile.read()
  166. self._CheckStrings(C_HEADER + '''
  167. static const struct dtd_sandbox_spl_test dtv_spl_test = {
  168. \t.boolval\t\t= true,
  169. \t.bytearray\t\t= {0x6, 0x0, 0x0},
  170. \t.byteval\t\t= 0x5,
  171. \t.intarray\t\t= {0x2, 0x3, 0x4, 0x0},
  172. \t.intval\t\t\t= 0x1,
  173. \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
  174. \t\t0x11},
  175. \t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0},
  176. \t.stringarray\t\t= {"multi-word", "message", ""},
  177. \t.stringval\t\t= "message",
  178. };
  179. U_BOOT_DEVICE(spl_test) = {
  180. \t.name\t\t= "sandbox_spl_test",
  181. \t.platdata\t= &dtv_spl_test,
  182. \t.platdata_size\t= sizeof(dtv_spl_test),
  183. };
  184. static const struct dtd_sandbox_spl_test dtv_spl_test2 = {
  185. \t.bytearray\t\t= {0x1, 0x23, 0x34},
  186. \t.byteval\t\t= 0x8,
  187. \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
  188. \t.intval\t\t\t= 0x3,
  189. \t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  190. \t\t0x0},
  191. \t.stringarray\t\t= {"another", "multi-word", "message"},
  192. \t.stringval\t\t= "message2",
  193. };
  194. U_BOOT_DEVICE(spl_test2) = {
  195. \t.name\t\t= "sandbox_spl_test",
  196. \t.platdata\t= &dtv_spl_test2,
  197. \t.platdata_size\t= sizeof(dtv_spl_test2),
  198. };
  199. static const struct dtd_sandbox_spl_test dtv_spl_test3 = {
  200. \t.stringarray\t\t= {"one", "", ""},
  201. };
  202. U_BOOT_DEVICE(spl_test3) = {
  203. \t.name\t\t= "sandbox_spl_test",
  204. \t.platdata\t= &dtv_spl_test3,
  205. \t.platdata_size\t= sizeof(dtv_spl_test3),
  206. };
  207. static const struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
  208. };
  209. U_BOOT_DEVICE(spl_test4) = {
  210. \t.name\t\t= "sandbox_spl_test_2",
  211. \t.platdata\t= &dtv_spl_test4,
  212. \t.platdata_size\t= sizeof(dtv_spl_test4),
  213. };
  214. static const struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
  215. };
  216. U_BOOT_DEVICE(i2c_at_0) = {
  217. \t.name\t\t= "sandbox_i2c_test",
  218. \t.platdata\t= &dtv_i2c_at_0,
  219. \t.platdata_size\t= sizeof(dtv_i2c_at_0),
  220. };
  221. static const struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
  222. \t.low_power\t\t= true,
  223. \t.reg\t\t\t= {0x9, 0x0},
  224. };
  225. U_BOOT_DEVICE(pmic_at_9) = {
  226. \t.name\t\t= "sandbox_pmic_test",
  227. \t.platdata\t= &dtv_pmic_at_9,
  228. \t.platdata_size\t= sizeof(dtv_pmic_at_9),
  229. };
  230. ''', data)
  231. def test_phandle(self):
  232. """Test output from a node containing a phandle reference"""
  233. dtb_file = get_dtb_file('dtoc_test_phandle.dts')
  234. output = tools.GetOutputFilename('output')
  235. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  236. with open(output) as infile:
  237. data = infile.read()
  238. self._CheckStrings(HEADER + '''
  239. struct dtd_source {
  240. \tstruct phandle_2_arg clocks[4];
  241. };
  242. struct dtd_target {
  243. \tfdt32_t\t\tintval;
  244. };
  245. ''', data)
  246. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  247. with open(output) as infile:
  248. data = infile.read()
  249. self._CheckStrings(C_HEADER + '''
  250. static const struct dtd_target dtv_phandle_target = {
  251. \t.intval\t\t\t= 0x0,
  252. };
  253. U_BOOT_DEVICE(phandle_target) = {
  254. \t.name\t\t= "target",
  255. \t.platdata\t= &dtv_phandle_target,
  256. \t.platdata_size\t= sizeof(dtv_phandle_target),
  257. };
  258. static const struct dtd_target dtv_phandle2_target = {
  259. \t.intval\t\t\t= 0x1,
  260. };
  261. U_BOOT_DEVICE(phandle2_target) = {
  262. \t.name\t\t= "target",
  263. \t.platdata\t= &dtv_phandle2_target,
  264. \t.platdata_size\t= sizeof(dtv_phandle2_target),
  265. };
  266. static const struct dtd_target dtv_phandle3_target = {
  267. \t.intval\t\t\t= 0x2,
  268. };
  269. U_BOOT_DEVICE(phandle3_target) = {
  270. \t.name\t\t= "target",
  271. \t.platdata\t= &dtv_phandle3_target,
  272. \t.platdata_size\t= sizeof(dtv_phandle3_target),
  273. };
  274. static const struct dtd_source dtv_phandle_source = {
  275. \t.clocks\t\t\t= {
  276. \t\t\t{&dtv_phandle_target, {}},
  277. \t\t\t{&dtv_phandle2_target, {11}},
  278. \t\t\t{&dtv_phandle3_target, {12, 13}},
  279. \t\t\t{&dtv_phandle_target, {}},},
  280. };
  281. U_BOOT_DEVICE(phandle_source) = {
  282. \t.name\t\t= "source",
  283. \t.platdata\t= &dtv_phandle_source,
  284. \t.platdata_size\t= sizeof(dtv_phandle_source),
  285. };
  286. static const struct dtd_source dtv_phandle_source2 = {
  287. \t.clocks\t\t\t= {
  288. \t\t\t{&dtv_phandle_target, {}},},
  289. };
  290. U_BOOT_DEVICE(phandle_source2) = {
  291. \t.name\t\t= "source",
  292. \t.platdata\t= &dtv_phandle_source2,
  293. \t.platdata_size\t= sizeof(dtv_phandle_source2),
  294. };
  295. ''', data)
  296. def test_phandle_single(self):
  297. """Test output from a node containing a phandle reference"""
  298. dtb_file = get_dtb_file('dtoc_test_phandle_single.dts')
  299. output = tools.GetOutputFilename('output')
  300. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  301. with open(output) as infile:
  302. data = infile.read()
  303. self._CheckStrings(HEADER + '''
  304. struct dtd_source {
  305. \tstruct phandle_0_arg clocks[1];
  306. };
  307. struct dtd_target {
  308. \tfdt32_t\t\tintval;
  309. };
  310. ''', data)
  311. def test_phandle_reorder(self):
  312. """Test that phandle targets are generated before their references"""
  313. dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts')
  314. output = tools.GetOutputFilename('output')
  315. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  316. with open(output) as infile:
  317. data = infile.read()
  318. self._CheckStrings(C_HEADER + '''
  319. static const struct dtd_target dtv_phandle_target = {
  320. };
  321. U_BOOT_DEVICE(phandle_target) = {
  322. \t.name\t\t= "target",
  323. \t.platdata\t= &dtv_phandle_target,
  324. \t.platdata_size\t= sizeof(dtv_phandle_target),
  325. };
  326. static const struct dtd_source dtv_phandle_source2 = {
  327. \t.clocks\t\t\t= {
  328. \t\t\t{&dtv_phandle_target, {}},},
  329. };
  330. U_BOOT_DEVICE(phandle_source2) = {
  331. \t.name\t\t= "source",
  332. \t.platdata\t= &dtv_phandle_source2,
  333. \t.platdata_size\t= sizeof(dtv_phandle_source2),
  334. };
  335. ''', data)
  336. def test_phandle_bad(self):
  337. """Test a node containing an invalid phandle fails"""
  338. dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts',
  339. capture_stderr=True)
  340. output = tools.GetOutputFilename('output')
  341. with self.assertRaises(ValueError) as e:
  342. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  343. self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
  344. str(e.exception))
  345. def test_phandle_bad2(self):
  346. """Test a phandle target missing its #*-cells property"""
  347. dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts',
  348. capture_stderr=True)
  349. output = tools.GetOutputFilename('output')
  350. with self.assertRaises(ValueError) as e:
  351. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  352. self.assertIn("Node 'phandle-target' has no '#clock-cells' property",
  353. str(e.exception))
  354. def test_aliases(self):
  355. """Test output from a node with multiple compatible strings"""
  356. dtb_file = get_dtb_file('dtoc_test_aliases.dts')
  357. output = tools.GetOutputFilename('output')
  358. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  359. with open(output) as infile:
  360. data = infile.read()
  361. self._CheckStrings(HEADER + '''
  362. struct dtd_compat1 {
  363. \tfdt32_t\t\tintval;
  364. };
  365. #define dtd_compat2_1_fred dtd_compat1
  366. #define dtd_compat3 dtd_compat1
  367. ''', data)
  368. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  369. with open(output) as infile:
  370. data = infile.read()
  371. self._CheckStrings(C_HEADER + '''
  372. static const struct dtd_compat1 dtv_spl_test = {
  373. \t.intval\t\t\t= 0x1,
  374. };
  375. U_BOOT_DEVICE(spl_test) = {
  376. \t.name\t\t= "compat1",
  377. \t.platdata\t= &dtv_spl_test,
  378. \t.platdata_size\t= sizeof(dtv_spl_test),
  379. };
  380. ''', data)
  381. def test_addresses64(self):
  382. """Test output from a node with a 'reg' property with na=2, ns=2"""
  383. dtb_file = get_dtb_file('dtoc_test_addr64.dts')
  384. output = tools.GetOutputFilename('output')
  385. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  386. with open(output) as infile:
  387. data = infile.read()
  388. self._CheckStrings(HEADER + '''
  389. struct dtd_test1 {
  390. \tfdt64_t\t\treg[2];
  391. };
  392. struct dtd_test2 {
  393. \tfdt64_t\t\treg[2];
  394. };
  395. struct dtd_test3 {
  396. \tfdt64_t\t\treg[4];
  397. };
  398. ''', data)
  399. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  400. with open(output) as infile:
  401. data = infile.read()
  402. self._CheckStrings(C_HEADER + '''
  403. static const struct dtd_test1 dtv_test1 = {
  404. \t.reg\t\t\t= {0x1234, 0x5678},
  405. };
  406. U_BOOT_DEVICE(test1) = {
  407. \t.name\t\t= "test1",
  408. \t.platdata\t= &dtv_test1,
  409. \t.platdata_size\t= sizeof(dtv_test1),
  410. };
  411. static const struct dtd_test2 dtv_test2 = {
  412. \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
  413. };
  414. U_BOOT_DEVICE(test2) = {
  415. \t.name\t\t= "test2",
  416. \t.platdata\t= &dtv_test2,
  417. \t.platdata_size\t= sizeof(dtv_test2),
  418. };
  419. static const struct dtd_test3 dtv_test3 = {
  420. \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
  421. };
  422. U_BOOT_DEVICE(test3) = {
  423. \t.name\t\t= "test3",
  424. \t.platdata\t= &dtv_test3,
  425. \t.platdata_size\t= sizeof(dtv_test3),
  426. };
  427. ''', data)
  428. def test_addresses32(self):
  429. """Test output from a node with a 'reg' property with na=1, ns=1"""
  430. dtb_file = get_dtb_file('dtoc_test_addr32.dts')
  431. output = tools.GetOutputFilename('output')
  432. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  433. with open(output) as infile:
  434. data = infile.read()
  435. self._CheckStrings(HEADER + '''
  436. struct dtd_test1 {
  437. \tfdt32_t\t\treg[2];
  438. };
  439. struct dtd_test2 {
  440. \tfdt32_t\t\treg[4];
  441. };
  442. ''', data)
  443. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  444. with open(output) as infile:
  445. data = infile.read()
  446. self._CheckStrings(C_HEADER + '''
  447. static const struct dtd_test1 dtv_test1 = {
  448. \t.reg\t\t\t= {0x1234, 0x5678},
  449. };
  450. U_BOOT_DEVICE(test1) = {
  451. \t.name\t\t= "test1",
  452. \t.platdata\t= &dtv_test1,
  453. \t.platdata_size\t= sizeof(dtv_test1),
  454. };
  455. static const struct dtd_test2 dtv_test2 = {
  456. \t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
  457. };
  458. U_BOOT_DEVICE(test2) = {
  459. \t.name\t\t= "test2",
  460. \t.platdata\t= &dtv_test2,
  461. \t.platdata_size\t= sizeof(dtv_test2),
  462. };
  463. ''', data)
  464. def test_addresses64_32(self):
  465. """Test output from a node with a 'reg' property with na=2, ns=1"""
  466. dtb_file = get_dtb_file('dtoc_test_addr64_32.dts')
  467. output = tools.GetOutputFilename('output')
  468. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  469. with open(output) as infile:
  470. data = infile.read()
  471. self._CheckStrings(HEADER + '''
  472. struct dtd_test1 {
  473. \tfdt64_t\t\treg[2];
  474. };
  475. struct dtd_test2 {
  476. \tfdt64_t\t\treg[2];
  477. };
  478. struct dtd_test3 {
  479. \tfdt64_t\t\treg[4];
  480. };
  481. ''', data)
  482. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  483. with open(output) as infile:
  484. data = infile.read()
  485. self._CheckStrings(C_HEADER + '''
  486. static const struct dtd_test1 dtv_test1 = {
  487. \t.reg\t\t\t= {0x123400000000, 0x5678},
  488. };
  489. U_BOOT_DEVICE(test1) = {
  490. \t.name\t\t= "test1",
  491. \t.platdata\t= &dtv_test1,
  492. \t.platdata_size\t= sizeof(dtv_test1),
  493. };
  494. static const struct dtd_test2 dtv_test2 = {
  495. \t.reg\t\t\t= {0x1234567890123456, 0x98765432},
  496. };
  497. U_BOOT_DEVICE(test2) = {
  498. \t.name\t\t= "test2",
  499. \t.platdata\t= &dtv_test2,
  500. \t.platdata_size\t= sizeof(dtv_test2),
  501. };
  502. static const struct dtd_test3 dtv_test3 = {
  503. \t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
  504. };
  505. U_BOOT_DEVICE(test3) = {
  506. \t.name\t\t= "test3",
  507. \t.platdata\t= &dtv_test3,
  508. \t.platdata_size\t= sizeof(dtv_test3),
  509. };
  510. ''', data)
  511. def test_addresses32_64(self):
  512. """Test output from a node with a 'reg' property with na=1, ns=2"""
  513. dtb_file = get_dtb_file('dtoc_test_addr32_64.dts')
  514. output = tools.GetOutputFilename('output')
  515. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  516. with open(output) as infile:
  517. data = infile.read()
  518. self._CheckStrings(HEADER + '''
  519. struct dtd_test1 {
  520. \tfdt64_t\t\treg[2];
  521. };
  522. struct dtd_test2 {
  523. \tfdt64_t\t\treg[2];
  524. };
  525. struct dtd_test3 {
  526. \tfdt64_t\t\treg[4];
  527. };
  528. ''', data)
  529. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  530. with open(output) as infile:
  531. data = infile.read()
  532. self._CheckStrings(C_HEADER + '''
  533. static const struct dtd_test1 dtv_test1 = {
  534. \t.reg\t\t\t= {0x1234, 0x567800000000},
  535. };
  536. U_BOOT_DEVICE(test1) = {
  537. \t.name\t\t= "test1",
  538. \t.platdata\t= &dtv_test1,
  539. \t.platdata_size\t= sizeof(dtv_test1),
  540. };
  541. static const struct dtd_test2 dtv_test2 = {
  542. \t.reg\t\t\t= {0x12345678, 0x9876543210987654},
  543. };
  544. U_BOOT_DEVICE(test2) = {
  545. \t.name\t\t= "test2",
  546. \t.platdata\t= &dtv_test2,
  547. \t.platdata_size\t= sizeof(dtv_test2),
  548. };
  549. static const struct dtd_test3 dtv_test3 = {
  550. \t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
  551. };
  552. U_BOOT_DEVICE(test3) = {
  553. \t.name\t\t= "test3",
  554. \t.platdata\t= &dtv_test3,
  555. \t.platdata_size\t= sizeof(dtv_test3),
  556. };
  557. ''', data)
  558. def test_bad_reg(self):
  559. """Test that a reg property with an invalid type generates an error"""
  560. # Capture stderr since dtc will emit warnings for this file
  561. dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True)
  562. output = tools.GetOutputFilename('output')
  563. with self.assertRaises(ValueError) as e:
  564. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  565. self.assertIn("Node 'spl-test' reg property is not an int",
  566. str(e.exception))
  567. def test_bad_reg2(self):
  568. """Test that a reg property with an invalid cell count is detected"""
  569. # Capture stderr since dtc will emit warnings for this file
  570. dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True)
  571. output = tools.GetOutputFilename('output')
  572. with self.assertRaises(ValueError) as e:
  573. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  574. self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
  575. str(e.exception))
  576. def test_add_prop(self):
  577. """Test that a subequent node can add a new property to a struct"""
  578. dtb_file = get_dtb_file('dtoc_test_add_prop.dts')
  579. output = tools.GetOutputFilename('output')
  580. dtb_platdata.run_steps(['struct'], dtb_file, False, output)
  581. with open(output) as infile:
  582. data = infile.read()
  583. self._CheckStrings(HEADER + '''
  584. struct dtd_sandbox_spl_test {
  585. \tfdt32_t\t\tintarray;
  586. \tfdt32_t\t\tintval;
  587. };
  588. ''', data)
  589. dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
  590. with open(output) as infile:
  591. data = infile.read()
  592. self._CheckStrings(C_HEADER + '''
  593. static const struct dtd_sandbox_spl_test dtv_spl_test = {
  594. \t.intval\t\t\t= 0x1,
  595. };
  596. U_BOOT_DEVICE(spl_test) = {
  597. \t.name\t\t= "sandbox_spl_test",
  598. \t.platdata\t= &dtv_spl_test,
  599. \t.platdata_size\t= sizeof(dtv_spl_test),
  600. };
  601. static const struct dtd_sandbox_spl_test dtv_spl_test2 = {
  602. \t.intarray\t\t= 0x5,
  603. };
  604. U_BOOT_DEVICE(spl_test2) = {
  605. \t.name\t\t= "sandbox_spl_test",
  606. \t.platdata\t= &dtv_spl_test2,
  607. \t.platdata_size\t= sizeof(dtv_spl_test2),
  608. };
  609. ''', data)
  610. def testStdout(self):
  611. """Test output to stdout"""
  612. dtb_file = get_dtb_file('dtoc_test_simple.dts')
  613. with test_util.capture_sys_output() as (stdout, stderr):
  614. dtb_platdata.run_steps(['struct'], dtb_file, False, '-')
  615. def testNoCommand(self):
  616. """Test running dtoc without a command"""
  617. with self.assertRaises(ValueError) as e:
  618. dtb_platdata.run_steps([], '', False, '')
  619. self.assertIn("Please specify a command: struct, platdata",
  620. str(e.exception))
  621. def testBadCommand(self):
  622. """Test running dtoc with an invalid command"""
  623. dtb_file = get_dtb_file('dtoc_test_simple.dts')
  624. output = tools.GetOutputFilename('output')
  625. with self.assertRaises(ValueError) as e:
  626. dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output)
  627. self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
  628. str(e.exception))