xref: /openbmc/u-boot/tools/dtoc/test_dtoc.py (revision 0da90255083681a02b24528f80da9d4062ff634a)
1c0791928SSimon Glass# SPDX-License-Identifier: GPL-2.0+
283d290c5STom Rini# Copyright (c) 2012 The Chromium OS Authors.
3c0791928SSimon Glass#
4c0791928SSimon Glass
5c0791928SSimon Glass"""Tests for the dtb_platdata module
6c0791928SSimon Glass
73def0cf2SSimon GlassThis includes unit tests for some functions and functional tests for the dtoc
83def0cf2SSimon Glasstool.
9c0791928SSimon Glass"""
10c0791928SSimon Glass
11c0791928SSimon Glassimport collections
12c0791928SSimon Glassimport os
13c0791928SSimon Glassimport struct
14c0791928SSimon Glassimport unittest
15c0791928SSimon Glass
16c0791928SSimon Glassimport dtb_platdata
17c0791928SSimon Glassfrom dtb_platdata import conv_name_to_c
18c0791928SSimon Glassfrom dtb_platdata import get_compat_name
19c0791928SSimon Glassfrom dtb_platdata import get_value
20c0791928SSimon Glassfrom dtb_platdata import tab_to
21c0791928SSimon Glassimport fdt
22c0791928SSimon Glassimport fdt_util
238512ea2eSSimon Glassimport test_util
24c0791928SSimon Glassimport tools
25c0791928SSimon Glass
26c0791928SSimon Glassour_path = os.path.dirname(os.path.realpath(__file__))
27c0791928SSimon Glass
28c0791928SSimon Glass
29aab660feSSimon GlassHEADER = '''/*
30aab660feSSimon Glass * DO NOT MODIFY
31aab660feSSimon Glass *
32aab660feSSimon Glass * This file was generated by dtoc from a .dtb (device tree binary) file.
33aab660feSSimon Glass */
34aab660feSSimon Glass
35aab660feSSimon Glass#include <stdbool.h>
36b08c8c48SMasahiro Yamada#include <linux/libfdt.h>'''
37aab660feSSimon Glass
38aab660feSSimon GlassC_HEADER = '''/*
39aab660feSSimon Glass * DO NOT MODIFY
40aab660feSSimon Glass *
41aab660feSSimon Glass * This file was generated by dtoc from a .dtb (device tree binary) file.
42aab660feSSimon Glass */
43aab660feSSimon Glass
44aab660feSSimon Glass#include <common.h>
45aab660feSSimon Glass#include <dm.h>
46aab660feSSimon Glass#include <dt-structs.h>
47aab660feSSimon Glass'''
48aab660feSSimon Glass
49aab660feSSimon Glass
50fe57c784SSimon Glass
51fe57c784SSimon Glassdef get_dtb_file(dts_fname, capture_stderr=False):
52c0791928SSimon Glass    """Compile a .dts file to a .dtb
53c0791928SSimon Glass
54c0791928SSimon Glass    Args:
55c0791928SSimon Glass        dts_fname: Filename of .dts file in the current directory
56fe57c784SSimon Glass        capture_stderr: True to capture and discard stderr output
57c0791928SSimon Glass
58c0791928SSimon Glass    Returns:
59c0791928SSimon Glass        Filename of compiled file in output directory
60c0791928SSimon Glass    """
61fe57c784SSimon Glass    return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname),
62fe57c784SSimon Glass                                   capture_stderr=capture_stderr)
63c0791928SSimon Glass
64c0791928SSimon Glass
65c0791928SSimon Glassclass TestDtoc(unittest.TestCase):
66c0791928SSimon Glass    """Tests for dtoc"""
67c0791928SSimon Glass    @classmethod
68c0791928SSimon Glass    def setUpClass(cls):
69c0791928SSimon Glass        tools.PrepareOutputDir(None)
70c0791928SSimon Glass
71c0791928SSimon Glass    @classmethod
72c0791928SSimon Glass    def tearDownClass(cls):
73c0791928SSimon Glass        tools._RemoveOutputDir()
74c0791928SSimon Glass
7557f0bc42SSimon Glass    def _WritePythonString(self, fname, data):
7657f0bc42SSimon Glass        """Write a string with tabs expanded as done in this Python file
7757f0bc42SSimon Glass
7857f0bc42SSimon Glass        Args:
7957f0bc42SSimon Glass            fname: Filename to write to
8057f0bc42SSimon Glass            data: Raw string to convert
8157f0bc42SSimon Glass        """
8257f0bc42SSimon Glass        data = data.replace('\t', '\\t')
8357f0bc42SSimon Glass        with open(fname, 'w') as fd:
8457f0bc42SSimon Glass            fd.write(data)
8557f0bc42SSimon Glass
8657f0bc42SSimon Glass    def _CheckStrings(self, expected, actual):
8757f0bc42SSimon Glass        """Check that a string matches its expected value
8857f0bc42SSimon Glass
8957f0bc42SSimon Glass        If the strings do not match, they are written to the /tmp directory in
9057f0bc42SSimon Glass        the same Python format as is used here in the test. This allows for
9157f0bc42SSimon Glass        easy comparison and update of the tests.
9257f0bc42SSimon Glass
9357f0bc42SSimon Glass        Args:
9457f0bc42SSimon Glass            expected: Expected string
9557f0bc42SSimon Glass            actual: Actual string
9657f0bc42SSimon Glass        """
9757f0bc42SSimon Glass        if expected != actual:
9857f0bc42SSimon Glass            self._WritePythonString('/tmp/binman.expected', expected)
9957f0bc42SSimon Glass            self._WritePythonString('/tmp/binman.actual', actual)
10057f0bc42SSimon Glass            print 'Failures written to /tmp/binman.{expected,actual}'
10157f0bc42SSimon Glass        self.assertEquals(expected, actual)
10257f0bc42SSimon Glass
103c0791928SSimon Glass    def test_name(self):
104c0791928SSimon Glass        """Test conversion of device tree names to C identifiers"""
105c0791928SSimon Glass        self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12'))
106c0791928SSimon Glass        self.assertEqual('vendor_clock_frequency',
107c0791928SSimon Glass                         conv_name_to_c('vendor,clock-frequency'))
108c0791928SSimon Glass        self.assertEqual('rockchip_rk3399_sdhci_5_1',
109c0791928SSimon Glass                         conv_name_to_c('rockchip,rk3399-sdhci-5.1'))
110c0791928SSimon Glass
111c0791928SSimon Glass    def test_tab_to(self):
112c0791928SSimon Glass        """Test operation of tab_to() function"""
113c0791928SSimon Glass        self.assertEqual('fred ', tab_to(0, 'fred'))
114c0791928SSimon Glass        self.assertEqual('fred\t', tab_to(1, 'fred'))
115c0791928SSimon Glass        self.assertEqual('fred was here ', tab_to(1, 'fred was here'))
116c0791928SSimon Glass        self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here'))
117c0791928SSimon Glass        self.assertEqual('exactly8 ', tab_to(1, 'exactly8'))
118c0791928SSimon Glass        self.assertEqual('exactly8\t', tab_to(2, 'exactly8'))
119c0791928SSimon Glass
120c0791928SSimon Glass    def test_get_value(self):
121c0791928SSimon Glass        """Test operation of get_value() function"""
122c0791928SSimon Glass        self.assertEqual('0x45',
123c0791928SSimon Glass                         get_value(fdt.TYPE_INT, struct.pack('>I', 0x45)))
124c0791928SSimon Glass        self.assertEqual('0x45',
125c0791928SSimon Glass                         get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45)))
126c0791928SSimon Glass        self.assertEqual('0x0',
127c0791928SSimon Glass                         get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45)))
128c0791928SSimon Glass        self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test'))
129c0791928SSimon Glass        self.assertEqual('true', get_value(fdt.TYPE_BOOL, None))
130c0791928SSimon Glass
131c0791928SSimon Glass    def test_get_compat_name(self):
132c0791928SSimon Glass        """Test operation of get_compat_name() function"""
133c0791928SSimon Glass        Prop = collections.namedtuple('Prop', ['value'])
134c0791928SSimon Glass        Node = collections.namedtuple('Node', ['props'])
135c0791928SSimon Glass
136c0791928SSimon Glass        prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1'])
137c0791928SSimon Glass        node = Node({'compatible': prop})
138c0791928SSimon Glass        self.assertEqual(('rockchip_rk3399_sdhci_5_1', ['arasan_sdhci_5_1']),
139c0791928SSimon Glass                         get_compat_name(node))
140c0791928SSimon Glass
141c0791928SSimon Glass        prop = Prop(['rockchip,rk3399-sdhci-5.1'])
142c0791928SSimon Glass        node = Node({'compatible': prop})
143c0791928SSimon Glass        self.assertEqual(('rockchip_rk3399_sdhci_5_1', []),
144c0791928SSimon Glass                         get_compat_name(node))
145c0791928SSimon Glass
146c0791928SSimon Glass        prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third'])
147c0791928SSimon Glass        node = Node({'compatible': prop})
148c0791928SSimon Glass        self.assertEqual(('rockchip_rk3399_sdhci_5_1',
149c0791928SSimon Glass                          ['arasan_sdhci_5_1', 'third']),
150c0791928SSimon Glass                         get_compat_name(node))
151c0791928SSimon Glass
152c0791928SSimon Glass    def test_empty_file(self):
153c0791928SSimon Glass        """Test output from a device tree file with no nodes"""
154c0791928SSimon Glass        dtb_file = get_dtb_file('dtoc_test_empty.dts')
155c0791928SSimon Glass        output = tools.GetOutputFilename('output')
156c0791928SSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
157c0791928SSimon Glass        with open(output) as infile:
158c0791928SSimon Glass            lines = infile.read().splitlines()
159aab660feSSimon Glass        self.assertEqual(HEADER.splitlines(), lines)
160c0791928SSimon Glass
161c0791928SSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
162c0791928SSimon Glass        with open(output) as infile:
163c0791928SSimon Glass            lines = infile.read().splitlines()
164aab660feSSimon Glass        self.assertEqual(C_HEADER.splitlines() + [''], lines)
165c0791928SSimon Glass
166c0791928SSimon Glass    def test_simple(self):
167c0791928SSimon Glass        """Test output from some simple nodes with various types of data"""
168c0791928SSimon Glass        dtb_file = get_dtb_file('dtoc_test_simple.dts')
169c0791928SSimon Glass        output = tools.GetOutputFilename('output')
170c0791928SSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
171c0791928SSimon Glass        with open(output) as infile:
172c0791928SSimon Glass            data = infile.read()
17357f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
1745ec741fdSSimon Glassstruct dtd_sandbox_i2c_test {
1755ec741fdSSimon Glass};
1765ec741fdSSimon Glassstruct dtd_sandbox_pmic_test {
1775ec741fdSSimon Glass\tbool\t\tlow_power;
1785ec741fdSSimon Glass\tfdt64_t\t\treg[2];
1795ec741fdSSimon Glass};
180c0791928SSimon Glassstruct dtd_sandbox_spl_test {
181c0791928SSimon Glass\tbool\t\tboolval;
182c0791928SSimon Glass\tunsigned char\tbytearray[3];
183c0791928SSimon Glass\tunsigned char\tbyteval;
184c0791928SSimon Glass\tfdt32_t\t\tintarray[4];
185c0791928SSimon Glass\tfdt32_t\t\tintval;
186c0791928SSimon Glass\tunsigned char\tlongbytearray[9];
1872a2d91d0SSimon Glass\tunsigned char\tnotstring[5];
188c0791928SSimon Glass\tconst char *\tstringarray[3];
189c0791928SSimon Glass\tconst char *\tstringval;
190c0791928SSimon Glass};
191c0791928SSimon Glassstruct dtd_sandbox_spl_test_2 {
192c0791928SSimon Glass};
193c0791928SSimon Glass''', data)
194c0791928SSimon Glass
195c0791928SSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
196c0791928SSimon Glass        with open(output) as infile:
197c0791928SSimon Glass            data = infile.read()
19857f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
199*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_spl_test dtv_spl_test = {
200c0791928SSimon Glass\t.bytearray\t\t= {0x6, 0x0, 0x0},
201c0791928SSimon Glass\t.byteval\t\t= 0x5,
202c0791928SSimon Glass\t.intval\t\t\t= 0x1,
2032a2d91d0SSimon Glass\t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0},
20421d54ac3SSimon Glass\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
20521d54ac3SSimon Glass\t\t0x11},
206c0791928SSimon Glass\t.stringval\t\t= "message",
207c0791928SSimon Glass\t.boolval\t\t= true,
208c0791928SSimon Glass\t.intarray\t\t= {0x2, 0x3, 0x4, 0x0},
209c0791928SSimon Glass\t.stringarray\t\t= {"multi-word", "message", ""},
210c0791928SSimon Glass};
211c0791928SSimon GlassU_BOOT_DEVICE(spl_test) = {
212c0791928SSimon Glass\t.name\t\t= "sandbox_spl_test",
213c0791928SSimon Glass\t.platdata\t= &dtv_spl_test,
214c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test),
215c0791928SSimon Glass};
216c0791928SSimon Glass
217*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_spl_test dtv_spl_test2 = {
218c0791928SSimon Glass\t.bytearray\t\t= {0x1, 0x23, 0x34},
219c0791928SSimon Glass\t.byteval\t\t= 0x8,
220c0791928SSimon Glass\t.intval\t\t\t= 0x3,
22121d54ac3SSimon Glass\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
22221d54ac3SSimon Glass\t\t0x0},
223c0791928SSimon Glass\t.stringval\t\t= "message2",
224c0791928SSimon Glass\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
225c0791928SSimon Glass\t.stringarray\t\t= {"another", "multi-word", "message"},
226c0791928SSimon Glass};
227c0791928SSimon GlassU_BOOT_DEVICE(spl_test2) = {
228c0791928SSimon Glass\t.name\t\t= "sandbox_spl_test",
229c0791928SSimon Glass\t.platdata\t= &dtv_spl_test2,
230c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test2),
231c0791928SSimon Glass};
232c0791928SSimon Glass
233*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_spl_test dtv_spl_test3 = {
234c0791928SSimon Glass\t.stringarray\t\t= {"one", "", ""},
235c0791928SSimon Glass};
236c0791928SSimon GlassU_BOOT_DEVICE(spl_test3) = {
237c0791928SSimon Glass\t.name\t\t= "sandbox_spl_test",
238c0791928SSimon Glass\t.platdata\t= &dtv_spl_test3,
239c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test3),
240c0791928SSimon Glass};
241c0791928SSimon Glass
242*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
243c0791928SSimon Glass};
244c0791928SSimon GlassU_BOOT_DEVICE(spl_test4) = {
245c0791928SSimon Glass\t.name\t\t= "sandbox_spl_test_2",
246c0791928SSimon Glass\t.platdata\t= &dtv_spl_test4,
247c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test4),
248c0791928SSimon Glass};
249c0791928SSimon Glass
250*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
2515ec741fdSSimon Glass};
2525ec741fdSSimon GlassU_BOOT_DEVICE(i2c_at_0) = {
2535ec741fdSSimon Glass\t.name\t\t= "sandbox_i2c_test",
2545ec741fdSSimon Glass\t.platdata\t= &dtv_i2c_at_0,
2555ec741fdSSimon Glass\t.platdata_size\t= sizeof(dtv_i2c_at_0),
2565ec741fdSSimon Glass};
2575ec741fdSSimon Glass
258*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
2595ec741fdSSimon Glass\t.low_power\t\t= true,
2605ec741fdSSimon Glass\t.reg\t\t\t= {0x9, 0x0},
2615ec741fdSSimon Glass};
2625ec741fdSSimon GlassU_BOOT_DEVICE(pmic_at_9) = {
2635ec741fdSSimon Glass\t.name\t\t= "sandbox_pmic_test",
2645ec741fdSSimon Glass\t.platdata\t= &dtv_pmic_at_9,
2655ec741fdSSimon Glass\t.platdata_size\t= sizeof(dtv_pmic_at_9),
2665ec741fdSSimon Glass};
2675ec741fdSSimon Glass
268c0791928SSimon Glass''', data)
269c0791928SSimon Glass
270c0791928SSimon Glass    def test_phandle(self):
271c0791928SSimon Glass        """Test output from a node containing a phandle reference"""
272c0791928SSimon Glass        dtb_file = get_dtb_file('dtoc_test_phandle.dts')
273c0791928SSimon Glass        output = tools.GetOutputFilename('output')
274c0791928SSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
275c0791928SSimon Glass        with open(output) as infile:
276c0791928SSimon Glass            data = infile.read()
27757f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
278c0791928SSimon Glassstruct dtd_source {
279634eba4bSSimon Glass\tstruct phandle_2_arg clocks[4];
280c0791928SSimon Glass};
281c0791928SSimon Glassstruct dtd_target {
282c0791928SSimon Glass\tfdt32_t\t\tintval;
283c0791928SSimon Glass};
284c0791928SSimon Glass''', data)
285c0791928SSimon Glass
286c0791928SSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
287c0791928SSimon Glass        with open(output) as infile:
288c0791928SSimon Glass            data = infile.read()
28957f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
290*e4478d9aSSimon Goldschmidtstatic const struct dtd_target dtv_phandle_target = {
291634eba4bSSimon Glass\t.intval\t\t\t= 0x0,
292c0791928SSimon Glass};
293c0791928SSimon GlassU_BOOT_DEVICE(phandle_target) = {
294c0791928SSimon Glass\t.name\t\t= "target",
295c0791928SSimon Glass\t.platdata\t= &dtv_phandle_target,
296c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_phandle_target),
297c0791928SSimon Glass};
298c0791928SSimon Glass
299*e4478d9aSSimon Goldschmidtstatic const struct dtd_target dtv_phandle2_target = {
300634eba4bSSimon Glass\t.intval\t\t\t= 0x1,
301634eba4bSSimon Glass};
302634eba4bSSimon GlassU_BOOT_DEVICE(phandle2_target) = {
303634eba4bSSimon Glass\t.name\t\t= "target",
304634eba4bSSimon Glass\t.platdata\t= &dtv_phandle2_target,
305634eba4bSSimon Glass\t.platdata_size\t= sizeof(dtv_phandle2_target),
306634eba4bSSimon Glass};
307634eba4bSSimon Glass
308*e4478d9aSSimon Goldschmidtstatic const struct dtd_target dtv_phandle3_target = {
309634eba4bSSimon Glass\t.intval\t\t\t= 0x2,
310634eba4bSSimon Glass};
311634eba4bSSimon GlassU_BOOT_DEVICE(phandle3_target) = {
312634eba4bSSimon Glass\t.name\t\t= "target",
313634eba4bSSimon Glass\t.platdata\t= &dtv_phandle3_target,
314634eba4bSSimon Glass\t.platdata_size\t= sizeof(dtv_phandle3_target),
315634eba4bSSimon Glass};
316634eba4bSSimon Glass
317*e4478d9aSSimon Goldschmidtstatic const struct dtd_source dtv_phandle_source = {
31835d50370SSimon Glass\t.clocks\t\t\t= {
319634eba4bSSimon Glass\t\t\t{&dtv_phandle_target, {}},
320634eba4bSSimon Glass\t\t\t{&dtv_phandle2_target, {11}},
321634eba4bSSimon Glass\t\t\t{&dtv_phandle3_target, {12, 13}},
322634eba4bSSimon Glass\t\t\t{&dtv_phandle_target, {}},},
323c0791928SSimon Glass};
324c0791928SSimon GlassU_BOOT_DEVICE(phandle_source) = {
325c0791928SSimon Glass\t.name\t\t= "source",
326c0791928SSimon Glass\t.platdata\t= &dtv_phandle_source,
327c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_phandle_source),
328c0791928SSimon Glass};
329c0791928SSimon Glass
330*e4478d9aSSimon Goldschmidtstatic const struct dtd_source dtv_phandle_source2 = {
331760b7170SSimon Glass\t.clocks\t\t\t= {
332760b7170SSimon Glass\t\t\t{&dtv_phandle_target, {}},},
333760b7170SSimon Glass};
334760b7170SSimon GlassU_BOOT_DEVICE(phandle_source2) = {
335760b7170SSimon Glass\t.name\t\t= "source",
336760b7170SSimon Glass\t.platdata\t= &dtv_phandle_source2,
337760b7170SSimon Glass\t.platdata_size\t= sizeof(dtv_phandle_source2),
338760b7170SSimon Glass};
339760b7170SSimon Glass
340c0791928SSimon Glass''', data)
341c0791928SSimon Glass
3428512ea2eSSimon Glass    def test_phandle_single(self):
3438512ea2eSSimon Glass        """Test output from a node containing a phandle reference"""
3448512ea2eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_phandle_single.dts')
3458512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
3468512ea2eSSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
3478512ea2eSSimon Glass        with open(output) as infile:
3488512ea2eSSimon Glass            data = infile.read()
3498512ea2eSSimon Glass        self._CheckStrings(HEADER + '''
3508512ea2eSSimon Glassstruct dtd_source {
3518512ea2eSSimon Glass\tstruct phandle_0_arg clocks[1];
3528512ea2eSSimon Glass};
3538512ea2eSSimon Glassstruct dtd_target {
3548512ea2eSSimon Glass\tfdt32_t\t\tintval;
3558512ea2eSSimon Glass};
3568512ea2eSSimon Glass''', data)
3578512ea2eSSimon Glass
3588512ea2eSSimon Glass    def test_phandle_reorder(self):
3598512ea2eSSimon Glass        """Test that phandle targets are generated before their references"""
3608512ea2eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts')
3618512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
3628512ea2eSSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
3638512ea2eSSimon Glass        with open(output) as infile:
3648512ea2eSSimon Glass            data = infile.read()
3658512ea2eSSimon Glass        self._CheckStrings(C_HEADER + '''
366*e4478d9aSSimon Goldschmidtstatic const struct dtd_target dtv_phandle_target = {
3678512ea2eSSimon Glass};
3688512ea2eSSimon GlassU_BOOT_DEVICE(phandle_target) = {
3698512ea2eSSimon Glass\t.name\t\t= "target",
3708512ea2eSSimon Glass\t.platdata\t= &dtv_phandle_target,
3718512ea2eSSimon Glass\t.platdata_size\t= sizeof(dtv_phandle_target),
3728512ea2eSSimon Glass};
3738512ea2eSSimon Glass
374*e4478d9aSSimon Goldschmidtstatic const struct dtd_source dtv_phandle_source2 = {
3758512ea2eSSimon Glass\t.clocks\t\t\t= {
3768512ea2eSSimon Glass\t\t\t{&dtv_phandle_target, {}},},
3778512ea2eSSimon Glass};
3788512ea2eSSimon GlassU_BOOT_DEVICE(phandle_source2) = {
3798512ea2eSSimon Glass\t.name\t\t= "source",
3808512ea2eSSimon Glass\t.platdata\t= &dtv_phandle_source2,
3818512ea2eSSimon Glass\t.platdata_size\t= sizeof(dtv_phandle_source2),
3828512ea2eSSimon Glass};
3838512ea2eSSimon Glass
3848512ea2eSSimon Glass''', data)
3858512ea2eSSimon Glass
3868512ea2eSSimon Glass    def test_phandle_bad(self):
3878512ea2eSSimon Glass        """Test a node containing an invalid phandle fails"""
3884b4bc06eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts',
3894b4bc06eSSimon Glass                                capture_stderr=True)
3908512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
3918512ea2eSSimon Glass        with self.assertRaises(ValueError) as e:
3928512ea2eSSimon Glass            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
3938512ea2eSSimon Glass        self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
3948512ea2eSSimon Glass                      str(e.exception))
3958512ea2eSSimon Glass
3968512ea2eSSimon Glass    def test_phandle_bad2(self):
3978512ea2eSSimon Glass        """Test a phandle target missing its #*-cells property"""
3984b4bc06eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts',
3994b4bc06eSSimon Glass                                capture_stderr=True)
4008512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
4018512ea2eSSimon Glass        with self.assertRaises(ValueError) as e:
4028512ea2eSSimon Glass            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
4038512ea2eSSimon Glass        self.assertIn("Node 'phandle-target' has no '#clock-cells' property",
4048512ea2eSSimon Glass                      str(e.exception))
4058512ea2eSSimon Glass
406c0791928SSimon Glass    def test_aliases(self):
407c0791928SSimon Glass        """Test output from a node with multiple compatible strings"""
408c0791928SSimon Glass        dtb_file = get_dtb_file('dtoc_test_aliases.dts')
409c0791928SSimon Glass        output = tools.GetOutputFilename('output')
410c0791928SSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
411c0791928SSimon Glass        with open(output) as infile:
412c0791928SSimon Glass            data = infile.read()
41357f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
414c0791928SSimon Glassstruct dtd_compat1 {
415c0791928SSimon Glass\tfdt32_t\t\tintval;
416c0791928SSimon Glass};
417c0791928SSimon Glass#define dtd_compat2_1_fred dtd_compat1
418c0791928SSimon Glass#define dtd_compat3 dtd_compat1
419c0791928SSimon Glass''', data)
420c0791928SSimon Glass
421c0791928SSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
422c0791928SSimon Glass        with open(output) as infile:
423c0791928SSimon Glass            data = infile.read()
42457f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
425*e4478d9aSSimon Goldschmidtstatic const struct dtd_compat1 dtv_spl_test = {
426c0791928SSimon Glass\t.intval\t\t\t= 0x1,
427c0791928SSimon Glass};
428c0791928SSimon GlassU_BOOT_DEVICE(spl_test) = {
429c0791928SSimon Glass\t.name\t\t= "compat1",
430c0791928SSimon Glass\t.platdata\t= &dtv_spl_test,
431c0791928SSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test),
432c0791928SSimon Glass};
433c0791928SSimon Glass
434c0791928SSimon Glass''', data)
435c20ee0edSSimon Glass
436c20ee0edSSimon Glass    def test_addresses64(self):
437c20ee0edSSimon Glass        """Test output from a node with a 'reg' property with na=2, ns=2"""
438c20ee0edSSimon Glass        dtb_file = get_dtb_file('dtoc_test_addr64.dts')
439c20ee0edSSimon Glass        output = tools.GetOutputFilename('output')
440c20ee0edSSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
441c20ee0edSSimon Glass        with open(output) as infile:
442c20ee0edSSimon Glass            data = infile.read()
44357f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
444c20ee0edSSimon Glassstruct dtd_test1 {
445c20ee0edSSimon Glass\tfdt64_t\t\treg[2];
446c20ee0edSSimon Glass};
447c20ee0edSSimon Glassstruct dtd_test2 {
448c20ee0edSSimon Glass\tfdt64_t\t\treg[2];
449c20ee0edSSimon Glass};
450c20ee0edSSimon Glassstruct dtd_test3 {
451c20ee0edSSimon Glass\tfdt64_t\t\treg[4];
452c20ee0edSSimon Glass};
453c20ee0edSSimon Glass''', data)
454c20ee0edSSimon Glass
455c20ee0edSSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
456c20ee0edSSimon Glass        with open(output) as infile:
457c20ee0edSSimon Glass            data = infile.read()
45857f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
459*e4478d9aSSimon Goldschmidtstatic const struct dtd_test1 dtv_test1 = {
460c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234, 0x5678},
461c20ee0edSSimon Glass};
462c20ee0edSSimon GlassU_BOOT_DEVICE(test1) = {
463c20ee0edSSimon Glass\t.name\t\t= "test1",
464c20ee0edSSimon Glass\t.platdata\t= &dtv_test1,
465c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test1),
466c20ee0edSSimon Glass};
467c20ee0edSSimon Glass
468*e4478d9aSSimon Goldschmidtstatic const struct dtd_test2 dtv_test2 = {
469c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
470c20ee0edSSimon Glass};
471c20ee0edSSimon GlassU_BOOT_DEVICE(test2) = {
472c20ee0edSSimon Glass\t.name\t\t= "test2",
473c20ee0edSSimon Glass\t.platdata\t= &dtv_test2,
474c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test2),
475c20ee0edSSimon Glass};
476c20ee0edSSimon Glass
477*e4478d9aSSimon Goldschmidtstatic const struct dtd_test3 dtv_test3 = {
478c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
479c20ee0edSSimon Glass};
480c20ee0edSSimon GlassU_BOOT_DEVICE(test3) = {
481c20ee0edSSimon Glass\t.name\t\t= "test3",
482c20ee0edSSimon Glass\t.platdata\t= &dtv_test3,
483c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test3),
484c20ee0edSSimon Glass};
485c20ee0edSSimon Glass
486c20ee0edSSimon Glass''', data)
487c20ee0edSSimon Glass
488c20ee0edSSimon Glass    def test_addresses32(self):
489c20ee0edSSimon Glass        """Test output from a node with a 'reg' property with na=1, ns=1"""
490c20ee0edSSimon Glass        dtb_file = get_dtb_file('dtoc_test_addr32.dts')
491c20ee0edSSimon Glass        output = tools.GetOutputFilename('output')
492c20ee0edSSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
493c20ee0edSSimon Glass        with open(output) as infile:
494c20ee0edSSimon Glass            data = infile.read()
49557f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
496c20ee0edSSimon Glassstruct dtd_test1 {
497c20ee0edSSimon Glass\tfdt32_t\t\treg[2];
498c20ee0edSSimon Glass};
499c20ee0edSSimon Glassstruct dtd_test2 {
500c20ee0edSSimon Glass\tfdt32_t\t\treg[4];
501c20ee0edSSimon Glass};
502c20ee0edSSimon Glass''', data)
503c20ee0edSSimon Glass
504c20ee0edSSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
505c20ee0edSSimon Glass        with open(output) as infile:
506c20ee0edSSimon Glass            data = infile.read()
50757f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
508*e4478d9aSSimon Goldschmidtstatic const struct dtd_test1 dtv_test1 = {
509c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234, 0x5678},
510c20ee0edSSimon Glass};
511c20ee0edSSimon GlassU_BOOT_DEVICE(test1) = {
512c20ee0edSSimon Glass\t.name\t\t= "test1",
513c20ee0edSSimon Glass\t.platdata\t= &dtv_test1,
514c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test1),
515c20ee0edSSimon Glass};
516c20ee0edSSimon Glass
517*e4478d9aSSimon Goldschmidtstatic const struct dtd_test2 dtv_test2 = {
518c20ee0edSSimon Glass\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
519c20ee0edSSimon Glass};
520c20ee0edSSimon GlassU_BOOT_DEVICE(test2) = {
521c20ee0edSSimon Glass\t.name\t\t= "test2",
522c20ee0edSSimon Glass\t.platdata\t= &dtv_test2,
523c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test2),
524c20ee0edSSimon Glass};
525c20ee0edSSimon Glass
526c20ee0edSSimon Glass''', data)
527c20ee0edSSimon Glass
528c20ee0edSSimon Glass    def test_addresses64_32(self):
529c20ee0edSSimon Glass        """Test output from a node with a 'reg' property with na=2, ns=1"""
530c20ee0edSSimon Glass        dtb_file = get_dtb_file('dtoc_test_addr64_32.dts')
531c20ee0edSSimon Glass        output = tools.GetOutputFilename('output')
532c20ee0edSSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
533c20ee0edSSimon Glass        with open(output) as infile:
534c20ee0edSSimon Glass            data = infile.read()
53557f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
536c20ee0edSSimon Glassstruct dtd_test1 {
537c20ee0edSSimon Glass\tfdt64_t\t\treg[2];
538c20ee0edSSimon Glass};
539c20ee0edSSimon Glassstruct dtd_test2 {
540c20ee0edSSimon Glass\tfdt64_t\t\treg[2];
541c20ee0edSSimon Glass};
542c20ee0edSSimon Glassstruct dtd_test3 {
543c20ee0edSSimon Glass\tfdt64_t\t\treg[4];
544c20ee0edSSimon Glass};
545c20ee0edSSimon Glass''', data)
546c20ee0edSSimon Glass
547c20ee0edSSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
548c20ee0edSSimon Glass        with open(output) as infile:
549c20ee0edSSimon Glass            data = infile.read()
55057f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
551*e4478d9aSSimon Goldschmidtstatic const struct dtd_test1 dtv_test1 = {
552c20ee0edSSimon Glass\t.reg\t\t\t= {0x123400000000, 0x5678},
553c20ee0edSSimon Glass};
554c20ee0edSSimon GlassU_BOOT_DEVICE(test1) = {
555c20ee0edSSimon Glass\t.name\t\t= "test1",
556c20ee0edSSimon Glass\t.platdata\t= &dtv_test1,
557c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test1),
558c20ee0edSSimon Glass};
559c20ee0edSSimon Glass
560*e4478d9aSSimon Goldschmidtstatic const struct dtd_test2 dtv_test2 = {
561c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234567890123456, 0x98765432},
562c20ee0edSSimon Glass};
563c20ee0edSSimon GlassU_BOOT_DEVICE(test2) = {
564c20ee0edSSimon Glass\t.name\t\t= "test2",
565c20ee0edSSimon Glass\t.platdata\t= &dtv_test2,
566c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test2),
567c20ee0edSSimon Glass};
568c20ee0edSSimon Glass
569*e4478d9aSSimon Goldschmidtstatic const struct dtd_test3 dtv_test3 = {
570c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
571c20ee0edSSimon Glass};
572c20ee0edSSimon GlassU_BOOT_DEVICE(test3) = {
573c20ee0edSSimon Glass\t.name\t\t= "test3",
574c20ee0edSSimon Glass\t.platdata\t= &dtv_test3,
575c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test3),
576c20ee0edSSimon Glass};
577c20ee0edSSimon Glass
578c20ee0edSSimon Glass''', data)
579c20ee0edSSimon Glass
580c20ee0edSSimon Glass    def test_addresses32_64(self):
581c20ee0edSSimon Glass        """Test output from a node with a 'reg' property with na=1, ns=2"""
582c20ee0edSSimon Glass        dtb_file = get_dtb_file('dtoc_test_addr32_64.dts')
583c20ee0edSSimon Glass        output = tools.GetOutputFilename('output')
584c20ee0edSSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
585c20ee0edSSimon Glass        with open(output) as infile:
586c20ee0edSSimon Glass            data = infile.read()
58757f0bc42SSimon Glass        self._CheckStrings(HEADER + '''
588c20ee0edSSimon Glassstruct dtd_test1 {
589c20ee0edSSimon Glass\tfdt64_t\t\treg[2];
590c20ee0edSSimon Glass};
591c20ee0edSSimon Glassstruct dtd_test2 {
592c20ee0edSSimon Glass\tfdt64_t\t\treg[2];
593c20ee0edSSimon Glass};
594c20ee0edSSimon Glassstruct dtd_test3 {
595c20ee0edSSimon Glass\tfdt64_t\t\treg[4];
596c20ee0edSSimon Glass};
597c20ee0edSSimon Glass''', data)
598c20ee0edSSimon Glass
599c20ee0edSSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
600c20ee0edSSimon Glass        with open(output) as infile:
601c20ee0edSSimon Glass            data = infile.read()
60257f0bc42SSimon Glass        self._CheckStrings(C_HEADER + '''
603*e4478d9aSSimon Goldschmidtstatic const struct dtd_test1 dtv_test1 = {
604c20ee0edSSimon Glass\t.reg\t\t\t= {0x1234, 0x567800000000},
605c20ee0edSSimon Glass};
606c20ee0edSSimon GlassU_BOOT_DEVICE(test1) = {
607c20ee0edSSimon Glass\t.name\t\t= "test1",
608c20ee0edSSimon Glass\t.platdata\t= &dtv_test1,
609c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test1),
610c20ee0edSSimon Glass};
611c20ee0edSSimon Glass
612*e4478d9aSSimon Goldschmidtstatic const struct dtd_test2 dtv_test2 = {
613c20ee0edSSimon Glass\t.reg\t\t\t= {0x12345678, 0x9876543210987654},
614c20ee0edSSimon Glass};
615c20ee0edSSimon GlassU_BOOT_DEVICE(test2) = {
616c20ee0edSSimon Glass\t.name\t\t= "test2",
617c20ee0edSSimon Glass\t.platdata\t= &dtv_test2,
618c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test2),
619c20ee0edSSimon Glass};
620c20ee0edSSimon Glass
621*e4478d9aSSimon Goldschmidtstatic const struct dtd_test3 dtv_test3 = {
622c20ee0edSSimon Glass\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
623c20ee0edSSimon Glass};
624c20ee0edSSimon GlassU_BOOT_DEVICE(test3) = {
625c20ee0edSSimon Glass\t.name\t\t= "test3",
626c20ee0edSSimon Glass\t.platdata\t= &dtv_test3,
627c20ee0edSSimon Glass\t.platdata_size\t= sizeof(dtv_test3),
628c20ee0edSSimon Glass};
629c20ee0edSSimon Glass
630c20ee0edSSimon Glass''', data)
6318512ea2eSSimon Glass
6328512ea2eSSimon Glass    def test_bad_reg(self):
6338512ea2eSSimon Glass        """Test that a reg property with an invalid type generates an error"""
634fe57c784SSimon Glass        # Capture stderr since dtc will emit warnings for this file
635fe57c784SSimon Glass        dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True)
6368512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
6378512ea2eSSimon Glass        with self.assertRaises(ValueError) as e:
6388512ea2eSSimon Glass            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
6398512ea2eSSimon Glass        self.assertIn("Node 'spl-test' reg property is not an int",
6408512ea2eSSimon Glass                      str(e.exception))
6418512ea2eSSimon Glass
6428512ea2eSSimon Glass    def test_bad_reg2(self):
6438512ea2eSSimon Glass        """Test that a reg property with an invalid cell count is detected"""
644fe57c784SSimon Glass        # Capture stderr since dtc will emit warnings for this file
645fe57c784SSimon Glass        dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True)
6468512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
6478512ea2eSSimon Glass        with self.assertRaises(ValueError) as e:
6488512ea2eSSimon Glass            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
6498512ea2eSSimon Glass        self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
6508512ea2eSSimon Glass                      str(e.exception))
6518512ea2eSSimon Glass
6528512ea2eSSimon Glass    def test_add_prop(self):
6538512ea2eSSimon Glass        """Test that a subequent node can add a new property to a struct"""
6548512ea2eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_add_prop.dts')
6558512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
6568512ea2eSSimon Glass        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
6578512ea2eSSimon Glass        with open(output) as infile:
6588512ea2eSSimon Glass            data = infile.read()
6598512ea2eSSimon Glass        self._CheckStrings(HEADER + '''
6608512ea2eSSimon Glassstruct dtd_sandbox_spl_test {
6618512ea2eSSimon Glass\tfdt32_t\t\tintarray;
6628512ea2eSSimon Glass\tfdt32_t\t\tintval;
6638512ea2eSSimon Glass};
6648512ea2eSSimon Glass''', data)
6658512ea2eSSimon Glass
6668512ea2eSSimon Glass        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
6678512ea2eSSimon Glass        with open(output) as infile:
6688512ea2eSSimon Glass            data = infile.read()
6698512ea2eSSimon Glass        self._CheckStrings(C_HEADER + '''
670*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_spl_test dtv_spl_test = {
6718512ea2eSSimon Glass\t.intval\t\t\t= 0x1,
6728512ea2eSSimon Glass};
6738512ea2eSSimon GlassU_BOOT_DEVICE(spl_test) = {
6748512ea2eSSimon Glass\t.name\t\t= "sandbox_spl_test",
6758512ea2eSSimon Glass\t.platdata\t= &dtv_spl_test,
6768512ea2eSSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test),
6778512ea2eSSimon Glass};
6788512ea2eSSimon Glass
679*e4478d9aSSimon Goldschmidtstatic const struct dtd_sandbox_spl_test dtv_spl_test2 = {
6808512ea2eSSimon Glass\t.intarray\t\t= 0x5,
6818512ea2eSSimon Glass};
6828512ea2eSSimon GlassU_BOOT_DEVICE(spl_test2) = {
6838512ea2eSSimon Glass\t.name\t\t= "sandbox_spl_test",
6848512ea2eSSimon Glass\t.platdata\t= &dtv_spl_test2,
6858512ea2eSSimon Glass\t.platdata_size\t= sizeof(dtv_spl_test2),
6868512ea2eSSimon Glass};
6878512ea2eSSimon Glass
6888512ea2eSSimon Glass''', data)
6898512ea2eSSimon Glass
6908512ea2eSSimon Glass    def testStdout(self):
6918512ea2eSSimon Glass        """Test output to stdout"""
6928512ea2eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_simple.dts')
6938512ea2eSSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
6948512ea2eSSimon Glass            dtb_platdata.run_steps(['struct'], dtb_file, False, '-')
6958512ea2eSSimon Glass
6968512ea2eSSimon Glass    def testNoCommand(self):
6978512ea2eSSimon Glass        """Test running dtoc without a command"""
6988512ea2eSSimon Glass        with self.assertRaises(ValueError) as e:
6998512ea2eSSimon Glass            dtb_platdata.run_steps([], '', False, '')
7008512ea2eSSimon Glass        self.assertIn("Please specify a command: struct, platdata",
7018512ea2eSSimon Glass                      str(e.exception))
7028512ea2eSSimon Glass
7038512ea2eSSimon Glass    def testBadCommand(self):
7048512ea2eSSimon Glass        """Test running dtoc with an invalid command"""
7058512ea2eSSimon Glass        dtb_file = get_dtb_file('dtoc_test_simple.dts')
7068512ea2eSSimon Glass        output = tools.GetOutputFilename('output')
7078512ea2eSSimon Glass        with self.assertRaises(ValueError) as e:
7088512ea2eSSimon Glass            dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output)
7098512ea2eSSimon Glass        self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
7108512ea2eSSimon Glass                      str(e.exception))
711