blob: 622b39df39534aa332d92a791f46c2a83864f4d7 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass9d2eb922017-06-18 22:09:06 -06002# Copyright (c) 2012 The Chromium OS Authors.
3#
Simon Glass9d2eb922017-06-18 22:09:06 -06004
5"""Tests for the dtb_platdata module
6
Simon Glass70cd0d72018-07-06 10:27:20 -06007This includes unit tests for some functions and functional tests for the dtoc
8tool.
Simon Glass9d2eb922017-06-18 22:09:06 -06009"""
10
11import collections
12import os
13import struct
14import unittest
15
16import dtb_platdata
17from dtb_platdata import conv_name_to_c
18from dtb_platdata import get_compat_name
19from dtb_platdata import get_value
20from dtb_platdata import tab_to
21import fdt
22import fdt_util
Simon Glass961c1ce2018-07-06 10:27:35 -060023import test_util
Simon Glass9d2eb922017-06-18 22:09:06 -060024import tools
25
26our_path = os.path.dirname(os.path.realpath(__file__))
27
28
Simon Glasseb37e2d2017-11-12 21:52:17 -070029HEADER = '''/*
30 * DO NOT MODIFY
31 *
32 * This file was generated by dtoc from a .dtb (device tree binary) file.
33 */
34
35#include <stdbool.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090036#include <linux/libfdt.h>'''
Simon Glasseb37e2d2017-11-12 21:52:17 -070037
38C_HEADER = '''/*
39 * DO NOT MODIFY
40 *
41 * This file was generated by dtoc from a .dtb (device tree binary) file.
42 */
43
44#include <common.h>
45#include <dm.h>
46#include <dt-structs.h>
47'''
48
49
Simon Glass9d2eb922017-06-18 22:09:06 -060050def get_dtb_file(dts_fname):
51 """Compile a .dts file to a .dtb
52
53 Args:
54 dts_fname: Filename of .dts file in the current directory
55
56 Returns:
57 Filename of compiled file in output directory
58 """
59 return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname))
60
61
62class TestDtoc(unittest.TestCase):
63 """Tests for dtoc"""
64 @classmethod
65 def setUpClass(cls):
66 tools.PrepareOutputDir(None)
67
68 @classmethod
69 def tearDownClass(cls):
70 tools._RemoveOutputDir()
71
Simon Glassc47c2b32018-07-06 10:27:25 -060072 def _WritePythonString(self, fname, data):
73 """Write a string with tabs expanded as done in this Python file
74
75 Args:
76 fname: Filename to write to
77 data: Raw string to convert
78 """
79 data = data.replace('\t', '\\t')
80 with open(fname, 'w') as fd:
81 fd.write(data)
82
83 def _CheckStrings(self, expected, actual):
84 """Check that a string matches its expected value
85
86 If the strings do not match, they are written to the /tmp directory in
87 the same Python format as is used here in the test. This allows for
88 easy comparison and update of the tests.
89
90 Args:
91 expected: Expected string
92 actual: Actual string
93 """
94 if expected != actual:
95 self._WritePythonString('/tmp/binman.expected', expected)
96 self._WritePythonString('/tmp/binman.actual', actual)
97 print 'Failures written to /tmp/binman.{expected,actual}'
98 self.assertEquals(expected, actual)
99
Simon Glass9d2eb922017-06-18 22:09:06 -0600100 def test_name(self):
101 """Test conversion of device tree names to C identifiers"""
102 self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12'))
103 self.assertEqual('vendor_clock_frequency',
104 conv_name_to_c('vendor,clock-frequency'))
105 self.assertEqual('rockchip_rk3399_sdhci_5_1',
106 conv_name_to_c('rockchip,rk3399-sdhci-5.1'))
107
108 def test_tab_to(self):
109 """Test operation of tab_to() function"""
110 self.assertEqual('fred ', tab_to(0, 'fred'))
111 self.assertEqual('fred\t', tab_to(1, 'fred'))
112 self.assertEqual('fred was here ', tab_to(1, 'fred was here'))
113 self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here'))
114 self.assertEqual('exactly8 ', tab_to(1, 'exactly8'))
115 self.assertEqual('exactly8\t', tab_to(2, 'exactly8'))
116
117 def test_get_value(self):
118 """Test operation of get_value() function"""
119 self.assertEqual('0x45',
120 get_value(fdt.TYPE_INT, struct.pack('>I', 0x45)))
121 self.assertEqual('0x45',
122 get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45)))
123 self.assertEqual('0x0',
124 get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45)))
125 self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test'))
126 self.assertEqual('true', get_value(fdt.TYPE_BOOL, None))
127
128 def test_get_compat_name(self):
129 """Test operation of get_compat_name() function"""
130 Prop = collections.namedtuple('Prop', ['value'])
131 Node = collections.namedtuple('Node', ['props'])
132
133 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1'])
134 node = Node({'compatible': prop})
135 self.assertEqual(('rockchip_rk3399_sdhci_5_1', ['arasan_sdhci_5_1']),
136 get_compat_name(node))
137
138 prop = Prop(['rockchip,rk3399-sdhci-5.1'])
139 node = Node({'compatible': prop})
140 self.assertEqual(('rockchip_rk3399_sdhci_5_1', []),
141 get_compat_name(node))
142
143 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third'])
144 node = Node({'compatible': prop})
145 self.assertEqual(('rockchip_rk3399_sdhci_5_1',
146 ['arasan_sdhci_5_1', 'third']),
147 get_compat_name(node))
148
149 def test_empty_file(self):
150 """Test output from a device tree file with no nodes"""
151 dtb_file = get_dtb_file('dtoc_test_empty.dts')
152 output = tools.GetOutputFilename('output')
153 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
154 with open(output) as infile:
155 lines = infile.read().splitlines()
Simon Glasseb37e2d2017-11-12 21:52:17 -0700156 self.assertEqual(HEADER.splitlines(), lines)
Simon Glass9d2eb922017-06-18 22:09:06 -0600157
158 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
159 with open(output) as infile:
160 lines = infile.read().splitlines()
Simon Glasseb37e2d2017-11-12 21:52:17 -0700161 self.assertEqual(C_HEADER.splitlines() + [''], lines)
Simon Glass9d2eb922017-06-18 22:09:06 -0600162
163 def test_simple(self):
164 """Test output from some simple nodes with various types of data"""
165 dtb_file = get_dtb_file('dtoc_test_simple.dts')
166 output = tools.GetOutputFilename('output')
167 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
168 with open(output) as infile:
169 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600170 self._CheckStrings(HEADER + '''
Simon Glass90e5f0a2017-08-29 14:15:51 -0600171struct dtd_sandbox_i2c_test {
172};
173struct dtd_sandbox_pmic_test {
174\tbool\t\tlow_power;
175\tfdt64_t\t\treg[2];
176};
Simon Glass9d2eb922017-06-18 22:09:06 -0600177struct dtd_sandbox_spl_test {
178\tbool\t\tboolval;
179\tunsigned char\tbytearray[3];
180\tunsigned char\tbyteval;
181\tfdt32_t\t\tintarray[4];
182\tfdt32_t\t\tintval;
183\tunsigned char\tlongbytearray[9];
Simon Glass9c526332018-07-06 10:27:28 -0600184\tunsigned char\tnotstring[5];
Simon Glass9d2eb922017-06-18 22:09:06 -0600185\tconst char *\tstringarray[3];
186\tconst char *\tstringval;
187};
188struct dtd_sandbox_spl_test_2 {
189};
190''', data)
191
192 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
193 with open(output) as infile:
194 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600195 self._CheckStrings(C_HEADER + '''
Simon Glass9d2eb922017-06-18 22:09:06 -0600196static struct dtd_sandbox_spl_test dtv_spl_test = {
197\t.bytearray\t\t= {0x6, 0x0, 0x0},
198\t.byteval\t\t= 0x5,
199\t.intval\t\t\t= 0x1,
Simon Glass9c526332018-07-06 10:27:28 -0600200\t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0},
Simon Glass131e0b02017-08-29 14:15:49 -0600201\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
202\t\t0x11},
Simon Glass9d2eb922017-06-18 22:09:06 -0600203\t.stringval\t\t= "message",
204\t.boolval\t\t= true,
205\t.intarray\t\t= {0x2, 0x3, 0x4, 0x0},
206\t.stringarray\t\t= {"multi-word", "message", ""},
207};
208U_BOOT_DEVICE(spl_test) = {
209\t.name\t\t= "sandbox_spl_test",
210\t.platdata\t= &dtv_spl_test,
211\t.platdata_size\t= sizeof(dtv_spl_test),
212};
213
214static struct dtd_sandbox_spl_test dtv_spl_test2 = {
215\t.bytearray\t\t= {0x1, 0x23, 0x34},
216\t.byteval\t\t= 0x8,
217\t.intval\t\t\t= 0x3,
Simon Glass131e0b02017-08-29 14:15:49 -0600218\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
219\t\t0x0},
Simon Glass9d2eb922017-06-18 22:09:06 -0600220\t.stringval\t\t= "message2",
221\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
222\t.stringarray\t\t= {"another", "multi-word", "message"},
223};
224U_BOOT_DEVICE(spl_test2) = {
225\t.name\t\t= "sandbox_spl_test",
226\t.platdata\t= &dtv_spl_test2,
227\t.platdata_size\t= sizeof(dtv_spl_test2),
228};
229
230static struct dtd_sandbox_spl_test dtv_spl_test3 = {
231\t.stringarray\t\t= {"one", "", ""},
232};
233U_BOOT_DEVICE(spl_test3) = {
234\t.name\t\t= "sandbox_spl_test",
235\t.platdata\t= &dtv_spl_test3,
236\t.platdata_size\t= sizeof(dtv_spl_test3),
237};
238
239static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
240};
241U_BOOT_DEVICE(spl_test4) = {
242\t.name\t\t= "sandbox_spl_test_2",
243\t.platdata\t= &dtv_spl_test4,
244\t.platdata_size\t= sizeof(dtv_spl_test4),
245};
246
Simon Glass90e5f0a2017-08-29 14:15:51 -0600247static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
248};
249U_BOOT_DEVICE(i2c_at_0) = {
250\t.name\t\t= "sandbox_i2c_test",
251\t.platdata\t= &dtv_i2c_at_0,
252\t.platdata_size\t= sizeof(dtv_i2c_at_0),
253};
254
255static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
256\t.low_power\t\t= true,
257\t.reg\t\t\t= {0x9, 0x0},
258};
259U_BOOT_DEVICE(pmic_at_9) = {
260\t.name\t\t= "sandbox_pmic_test",
261\t.platdata\t= &dtv_pmic_at_9,
262\t.platdata_size\t= sizeof(dtv_pmic_at_9),
263};
264
Simon Glass9d2eb922017-06-18 22:09:06 -0600265''', data)
266
267 def test_phandle(self):
268 """Test output from a node containing a phandle reference"""
269 dtb_file = get_dtb_file('dtoc_test_phandle.dts')
270 output = tools.GetOutputFilename('output')
271 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
272 with open(output) as infile:
273 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600274 self._CheckStrings(HEADER + '''
Simon Glass9d2eb922017-06-18 22:09:06 -0600275struct dtd_source {
Simon Glass3deeb472017-08-29 14:15:59 -0600276\tstruct phandle_2_arg clocks[4];
Simon Glass9d2eb922017-06-18 22:09:06 -0600277};
278struct dtd_target {
279\tfdt32_t\t\tintval;
280};
281''', data)
282
283 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
284 with open(output) as infile:
285 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600286 self._CheckStrings(C_HEADER + '''
Simon Glass9d2eb922017-06-18 22:09:06 -0600287static struct dtd_target dtv_phandle_target = {
Simon Glass3deeb472017-08-29 14:15:59 -0600288\t.intval\t\t\t= 0x0,
Simon Glass9d2eb922017-06-18 22:09:06 -0600289};
290U_BOOT_DEVICE(phandle_target) = {
291\t.name\t\t= "target",
292\t.platdata\t= &dtv_phandle_target,
293\t.platdata_size\t= sizeof(dtv_phandle_target),
294};
295
Simon Glass3deeb472017-08-29 14:15:59 -0600296static struct dtd_target dtv_phandle2_target = {
297\t.intval\t\t\t= 0x1,
298};
299U_BOOT_DEVICE(phandle2_target) = {
300\t.name\t\t= "target",
301\t.platdata\t= &dtv_phandle2_target,
302\t.platdata_size\t= sizeof(dtv_phandle2_target),
303};
304
305static struct dtd_target dtv_phandle3_target = {
306\t.intval\t\t\t= 0x2,
307};
308U_BOOT_DEVICE(phandle3_target) = {
309\t.name\t\t= "target",
310\t.platdata\t= &dtv_phandle3_target,
311\t.platdata_size\t= sizeof(dtv_phandle3_target),
312};
313
Simon Glass9d2eb922017-06-18 22:09:06 -0600314static struct dtd_source dtv_phandle_source = {
Simon Glassd0cd0752017-08-29 14:15:57 -0600315\t.clocks\t\t\t= {
Simon Glass3deeb472017-08-29 14:15:59 -0600316\t\t\t{&dtv_phandle_target, {}},
317\t\t\t{&dtv_phandle2_target, {11}},
318\t\t\t{&dtv_phandle3_target, {12, 13}},
319\t\t\t{&dtv_phandle_target, {}},},
Simon Glass9d2eb922017-06-18 22:09:06 -0600320};
321U_BOOT_DEVICE(phandle_source) = {
322\t.name\t\t= "source",
323\t.platdata\t= &dtv_phandle_source,
324\t.platdata_size\t= sizeof(dtv_phandle_source),
325};
326
Simon Glass609e2b12018-07-06 10:27:31 -0600327static struct dtd_source dtv_phandle_source2 = {
328\t.clocks\t\t\t= {
329\t\t\t{&dtv_phandle_target, {}},},
330};
331U_BOOT_DEVICE(phandle_source2) = {
332\t.name\t\t= "source",
333\t.platdata\t= &dtv_phandle_source2,
334\t.platdata_size\t= sizeof(dtv_phandle_source2),
335};
336
Simon Glass9d2eb922017-06-18 22:09:06 -0600337''', data)
338
Simon Glass961c1ce2018-07-06 10:27:35 -0600339 def test_phandle_single(self):
340 """Test output from a node containing a phandle reference"""
341 dtb_file = get_dtb_file('dtoc_test_phandle_single.dts')
342 output = tools.GetOutputFilename('output')
343 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
344 with open(output) as infile:
345 data = infile.read()
346 self._CheckStrings(HEADER + '''
347struct dtd_source {
348\tstruct phandle_0_arg clocks[1];
349};
350struct dtd_target {
351\tfdt32_t\t\tintval;
352};
353''', data)
354
355 def test_phandle_reorder(self):
356 """Test that phandle targets are generated before their references"""
357 dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts')
358 output = tools.GetOutputFilename('output')
359 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
360 with open(output) as infile:
361 data = infile.read()
362 self._CheckStrings(C_HEADER + '''
363static struct dtd_target dtv_phandle_target = {
364};
365U_BOOT_DEVICE(phandle_target) = {
366\t.name\t\t= "target",
367\t.platdata\t= &dtv_phandle_target,
368\t.platdata_size\t= sizeof(dtv_phandle_target),
369};
370
371static struct dtd_source dtv_phandle_source2 = {
372\t.clocks\t\t\t= {
373\t\t\t{&dtv_phandle_target, {}},},
374};
375U_BOOT_DEVICE(phandle_source2) = {
376\t.name\t\t= "source",
377\t.platdata\t= &dtv_phandle_source2,
378\t.platdata_size\t= sizeof(dtv_phandle_source2),
379};
380
381''', data)
382
383 def test_phandle_bad(self):
384 """Test a node containing an invalid phandle fails"""
385 dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts')
386 output = tools.GetOutputFilename('output')
387 with self.assertRaises(ValueError) as e:
388 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
389 self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
390 str(e.exception))
391
392 def test_phandle_bad2(self):
393 """Test a phandle target missing its #*-cells property"""
394 dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts')
395 output = tools.GetOutputFilename('output')
396 with self.assertRaises(ValueError) as e:
397 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
398 self.assertIn("Node 'phandle-target' has no '#clock-cells' property",
399 str(e.exception))
400
Simon Glass9d2eb922017-06-18 22:09:06 -0600401 def test_aliases(self):
402 """Test output from a node with multiple compatible strings"""
403 dtb_file = get_dtb_file('dtoc_test_aliases.dts')
404 output = tools.GetOutputFilename('output')
405 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
406 with open(output) as infile:
407 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600408 self._CheckStrings(HEADER + '''
Simon Glass9d2eb922017-06-18 22:09:06 -0600409struct dtd_compat1 {
410\tfdt32_t\t\tintval;
411};
412#define dtd_compat2_1_fred dtd_compat1
413#define dtd_compat3 dtd_compat1
414''', data)
415
416 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
417 with open(output) as infile:
418 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600419 self._CheckStrings(C_HEADER + '''
Simon Glass9d2eb922017-06-18 22:09:06 -0600420static struct dtd_compat1 dtv_spl_test = {
421\t.intval\t\t\t= 0x1,
422};
423U_BOOT_DEVICE(spl_test) = {
424\t.name\t\t= "compat1",
425\t.platdata\t= &dtv_spl_test,
426\t.platdata_size\t= sizeof(dtv_spl_test),
427};
428
429''', data)
Simon Glass1b1fe412017-08-29 14:15:50 -0600430
431 def test_addresses64(self):
432 """Test output from a node with a 'reg' property with na=2, ns=2"""
433 dtb_file = get_dtb_file('dtoc_test_addr64.dts')
434 output = tools.GetOutputFilename('output')
435 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
436 with open(output) as infile:
437 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600438 self._CheckStrings(HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600439struct dtd_test1 {
440\tfdt64_t\t\treg[2];
441};
442struct dtd_test2 {
443\tfdt64_t\t\treg[2];
444};
445struct dtd_test3 {
446\tfdt64_t\t\treg[4];
447};
448''', data)
449
450 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
451 with open(output) as infile:
452 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600453 self._CheckStrings(C_HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600454static struct dtd_test1 dtv_test1 = {
455\t.reg\t\t\t= {0x1234, 0x5678},
456};
457U_BOOT_DEVICE(test1) = {
458\t.name\t\t= "test1",
459\t.platdata\t= &dtv_test1,
460\t.platdata_size\t= sizeof(dtv_test1),
461};
462
463static struct dtd_test2 dtv_test2 = {
464\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
465};
466U_BOOT_DEVICE(test2) = {
467\t.name\t\t= "test2",
468\t.platdata\t= &dtv_test2,
469\t.platdata_size\t= sizeof(dtv_test2),
470};
471
472static struct dtd_test3 dtv_test3 = {
473\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
474};
475U_BOOT_DEVICE(test3) = {
476\t.name\t\t= "test3",
477\t.platdata\t= &dtv_test3,
478\t.platdata_size\t= sizeof(dtv_test3),
479};
480
481''', data)
482
483 def test_addresses32(self):
484 """Test output from a node with a 'reg' property with na=1, ns=1"""
485 dtb_file = get_dtb_file('dtoc_test_addr32.dts')
486 output = tools.GetOutputFilename('output')
487 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
488 with open(output) as infile:
489 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600490 self._CheckStrings(HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600491struct dtd_test1 {
492\tfdt32_t\t\treg[2];
493};
494struct dtd_test2 {
495\tfdt32_t\t\treg[4];
496};
497''', data)
498
499 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
500 with open(output) as infile:
501 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600502 self._CheckStrings(C_HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600503static struct dtd_test1 dtv_test1 = {
504\t.reg\t\t\t= {0x1234, 0x5678},
505};
506U_BOOT_DEVICE(test1) = {
507\t.name\t\t= "test1",
508\t.platdata\t= &dtv_test1,
509\t.platdata_size\t= sizeof(dtv_test1),
510};
511
512static struct dtd_test2 dtv_test2 = {
513\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
514};
515U_BOOT_DEVICE(test2) = {
516\t.name\t\t= "test2",
517\t.platdata\t= &dtv_test2,
518\t.platdata_size\t= sizeof(dtv_test2),
519};
520
521''', data)
522
523 def test_addresses64_32(self):
524 """Test output from a node with a 'reg' property with na=2, ns=1"""
525 dtb_file = get_dtb_file('dtoc_test_addr64_32.dts')
526 output = tools.GetOutputFilename('output')
527 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
528 with open(output) as infile:
529 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600530 self._CheckStrings(HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600531struct dtd_test1 {
532\tfdt64_t\t\treg[2];
533};
534struct dtd_test2 {
535\tfdt64_t\t\treg[2];
536};
537struct dtd_test3 {
538\tfdt64_t\t\treg[4];
539};
540''', data)
541
542 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
543 with open(output) as infile:
544 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600545 self._CheckStrings(C_HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600546static struct dtd_test1 dtv_test1 = {
547\t.reg\t\t\t= {0x123400000000, 0x5678},
548};
549U_BOOT_DEVICE(test1) = {
550\t.name\t\t= "test1",
551\t.platdata\t= &dtv_test1,
552\t.platdata_size\t= sizeof(dtv_test1),
553};
554
555static struct dtd_test2 dtv_test2 = {
556\t.reg\t\t\t= {0x1234567890123456, 0x98765432},
557};
558U_BOOT_DEVICE(test2) = {
559\t.name\t\t= "test2",
560\t.platdata\t= &dtv_test2,
561\t.platdata_size\t= sizeof(dtv_test2),
562};
563
564static struct dtd_test3 dtv_test3 = {
565\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
566};
567U_BOOT_DEVICE(test3) = {
568\t.name\t\t= "test3",
569\t.platdata\t= &dtv_test3,
570\t.platdata_size\t= sizeof(dtv_test3),
571};
572
573''', data)
574
575 def test_addresses32_64(self):
576 """Test output from a node with a 'reg' property with na=1, ns=2"""
577 dtb_file = get_dtb_file('dtoc_test_addr32_64.dts')
578 output = tools.GetOutputFilename('output')
579 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
580 with open(output) as infile:
581 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600582 self._CheckStrings(HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600583struct dtd_test1 {
584\tfdt64_t\t\treg[2];
585};
586struct dtd_test2 {
587\tfdt64_t\t\treg[2];
588};
589struct dtd_test3 {
590\tfdt64_t\t\treg[4];
591};
592''', data)
593
594 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
595 with open(output) as infile:
596 data = infile.read()
Simon Glassc47c2b32018-07-06 10:27:25 -0600597 self._CheckStrings(C_HEADER + '''
Simon Glass1b1fe412017-08-29 14:15:50 -0600598static struct dtd_test1 dtv_test1 = {
599\t.reg\t\t\t= {0x1234, 0x567800000000},
600};
601U_BOOT_DEVICE(test1) = {
602\t.name\t\t= "test1",
603\t.platdata\t= &dtv_test1,
604\t.platdata_size\t= sizeof(dtv_test1),
605};
606
607static struct dtd_test2 dtv_test2 = {
608\t.reg\t\t\t= {0x12345678, 0x9876543210987654},
609};
610U_BOOT_DEVICE(test2) = {
611\t.name\t\t= "test2",
612\t.platdata\t= &dtv_test2,
613\t.platdata_size\t= sizeof(dtv_test2),
614};
615
616static struct dtd_test3 dtv_test3 = {
617\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
618};
619U_BOOT_DEVICE(test3) = {
620\t.name\t\t= "test3",
621\t.platdata\t= &dtv_test3,
622\t.platdata_size\t= sizeof(dtv_test3),
623};
624
625''', data)
Simon Glass961c1ce2018-07-06 10:27:35 -0600626
627 def test_bad_reg(self):
628 """Test that a reg property with an invalid type generates an error"""
629 dtb_file = get_dtb_file('dtoc_test_bad_reg.dts')
630 output = tools.GetOutputFilename('output')
631 with self.assertRaises(ValueError) as e:
632 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
633 self.assertIn("Node 'spl-test' reg property is not an int",
634 str(e.exception))
635
636 def test_bad_reg2(self):
637 """Test that a reg property with an invalid cell count is detected"""
638 dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts')
639 output = tools.GetOutputFilename('output')
640 with self.assertRaises(ValueError) as e:
641 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
642 self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
643 str(e.exception))
644
645 def test_add_prop(self):
646 """Test that a subequent node can add a new property to a struct"""
647 dtb_file = get_dtb_file('dtoc_test_add_prop.dts')
648 output = tools.GetOutputFilename('output')
649 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
650 with open(output) as infile:
651 data = infile.read()
652 self._CheckStrings(HEADER + '''
653struct dtd_sandbox_spl_test {
654\tfdt32_t\t\tintarray;
655\tfdt32_t\t\tintval;
656};
657''', data)
658
659 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
660 with open(output) as infile:
661 data = infile.read()
662 self._CheckStrings(C_HEADER + '''
663static struct dtd_sandbox_spl_test dtv_spl_test = {
664\t.intval\t\t\t= 0x1,
665};
666U_BOOT_DEVICE(spl_test) = {
667\t.name\t\t= "sandbox_spl_test",
668\t.platdata\t= &dtv_spl_test,
669\t.platdata_size\t= sizeof(dtv_spl_test),
670};
671
672static struct dtd_sandbox_spl_test dtv_spl_test2 = {
673\t.intarray\t\t= 0x5,
674};
675U_BOOT_DEVICE(spl_test2) = {
676\t.name\t\t= "sandbox_spl_test",
677\t.platdata\t= &dtv_spl_test2,
678\t.platdata_size\t= sizeof(dtv_spl_test2),
679};
680
681''', data)
682
683 def testStdout(self):
684 """Test output to stdout"""
685 dtb_file = get_dtb_file('dtoc_test_simple.dts')
686 with test_util.capture_sys_output() as (stdout, stderr):
687 dtb_platdata.run_steps(['struct'], dtb_file, False, '-')
688
689 def testNoCommand(self):
690 """Test running dtoc without a command"""
691 with self.assertRaises(ValueError) as e:
692 dtb_platdata.run_steps([], '', False, '')
693 self.assertIn("Please specify a command: struct, platdata",
694 str(e.exception))
695
696 def testBadCommand(self):
697 """Test running dtoc with an invalid command"""
698 dtb_file = get_dtb_file('dtoc_test_simple.dts')
699 output = tools.GetOutputFilename('output')
700 with self.assertRaises(ValueError) as e:
701 dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output)
702 self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
703 str(e.exception))