1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0+ 3# Copyright (c) 2012 The Chromium OS Authors. 4# 5 6"""Tests for the dtb_platdata module 7 8This includes unit tests for some functions and functional tests for the dtoc 9tool. 10""" 11 12import collections 13import copy 14import glob 15import os 16import pathlib 17import struct 18import unittest 19 20from dtoc import dtb_platdata 21from dtoc import fdt 22from dtoc import fdt_util 23from dtoc import src_scan 24from dtoc.dtb_platdata import Ftype 25from dtoc.dtb_platdata import get_value 26from dtoc.dtb_platdata import tab_to 27from dtoc.src_scan import conv_name_to_c 28from dtoc.src_scan import get_compat_name 29from u_boot_pylib import test_util 30from u_boot_pylib import tools 31 32DTOC_DIR = pathlib.Path(__file__).parent 33TEST_DATA_DIR = DTOC_DIR / 'test/' 34 35 36HEADER = '''/* 37 * DO NOT MODIFY 38 * 39 * Defines the structs used to hold devicetree data. 40 * This was generated by dtoc from a .dtb (device tree binary) file. 41 */ 42 43#include <stdbool.h> 44#include <linux/libfdt.h>''' 45 46DECL_HEADER = '''/* 47 * DO NOT MODIFY 48 * 49 * Declares externs for all device/uclass instances. 50 * This was generated by dtoc from a .dtb (device tree binary) file. 51 */ 52''' 53 54C_HEADER_PRE = '''/* 55 * DO NOT MODIFY 56 * 57 * Declares the U_BOOT_DRIVER() records and platform data. 58 * This was generated by dtoc from a .dtb (device tree binary) file. 59 */ 60''' 61 62C_HEADER = C_HEADER_PRE + ''' 63/* Allow use of U_BOOT_DRVINFO() in this file */ 64#define DT_PLAT_C 65 66#include <common.h> 67#include <dm.h> 68#include <dt-structs.h> 69''' 70 71UCLASS_HEADER_COMMON = '''/* 72 * DO NOT MODIFY 73 * 74 * Declares the uclass instances (struct uclass). 75 * This was generated by dtoc from a .dtb (device tree binary) file. 76 */ 77''' 78 79# Scanner saved from a previous run of the tests (to speed things up) 80saved_scan = None 81 82# This is a test so is allowed to access private things in the module it is 83# testing 84# pylint: disable=W0212 85 86def get_dtb_file(dts_fname, capture_stderr=False): 87 """Compile a .dts file to a .dtb 88 89 Args: 90 dts_fname (str): Filename of .dts file in the current directory 91 capture_stderr (bool): True to capture and discard stderr output 92 93 Returns: 94 str: Filename of compiled file in output directory 95 """ 96 return fdt_util.EnsureCompiled(str(TEST_DATA_DIR / dts_fname), 97 capture_stderr=capture_stderr) 98 99 100def setup(): 101 global saved_scan 102 103 # Disable warnings so that calls to get_normalized_compat_name() will not 104 # output things. 105 saved_scan = src_scan.Scanner(None, False) 106 saved_scan.scan_drivers() 107 108def copy_scan(): 109 """Get a copy of saved_scan so that each test can start clean""" 110 return copy.deepcopy(saved_scan) 111 112 113class TestDtoc(unittest.TestCase): 114 """Tests for dtoc""" 115 @classmethod 116 def setUpClass(cls): 117 tools.prepare_output_dir(None) 118 cls.maxDiff = None 119 120 @classmethod 121 def tearDownClass(cls): 122 tools.finalise_output_dir() 123 124 @staticmethod 125 def _write_python_string(fname, data): 126 """Write a string with tabs expanded as done in this Python file 127 128 Args: 129 fname (str): Filename to write to 130 data (str): Raw string to convert 131 """ 132 data = data.replace('\t', '\\t') 133 with open(fname, 'w') as fout: 134 fout.write(data) 135 136 def _check_strings(self, expected, actual): 137 """Check that a string matches its expected value 138 139 If the strings do not match, they are written to the /tmp directory in 140 the same Python format as is used here in the test. This allows for 141 easy comparison and update of the tests. 142 143 Args: 144 expected (str): Expected string 145 actual (str): Actual string 146 """ 147 if expected != actual: 148 self._write_python_string('/tmp/binman.expected', expected) 149 self._write_python_string('/tmp/binman.actual', actual) 150 print('Failures written to /tmp/binman.{expected,actual}') 151 self.assertEqual(expected, actual) 152 153 @staticmethod 154 def run_test(args, dtb_file, output, instantiate=False): 155 """Run a test using dtoc 156 157 Args: 158 args (list of str): List of arguments for dtoc 159 dtb_file (str): Filename of .dtb file 160 output (str): Filename of output file 161 162 Returns: 163 DtbPlatdata object 164 """ 165 # Make a copy of the 'scan' object, since it includes uclasses and 166 # drivers, which get updated during execution. 167 return dtb_platdata.run_steps( 168 args, dtb_file, False, output, [], None, instantiate, 169 warning_disabled=True, scan=copy_scan()) 170 171 def test_name(self): 172 """Test conversion of device tree names to C identifiers""" 173 self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12')) 174 self.assertEqual('vendor_clock_frequency', 175 conv_name_to_c('vendor,clock-frequency')) 176 self.assertEqual('rockchip_rk3399_sdhci_5_1', 177 conv_name_to_c('rockchip,rk3399-sdhci-5.1')) 178 179 def test_tab_to(self): 180 """Test operation of tab_to() function""" 181 self.assertEqual('fred ', tab_to(0, 'fred')) 182 self.assertEqual('fred\t', tab_to(1, 'fred')) 183 self.assertEqual('fred was here ', tab_to(1, 'fred was here')) 184 self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here')) 185 self.assertEqual('exactly8 ', tab_to(1, 'exactly8')) 186 self.assertEqual('exactly8\t', tab_to(2, 'exactly8')) 187 188 def test_get_value(self): 189 """Test operation of get_value() function""" 190 self.assertEqual('0x45', 191 get_value(fdt.Type.INT, struct.pack('>I', 0x45))) 192 self.assertEqual('0x45', 193 get_value(fdt.Type.BYTE, struct.pack('<I', 0x45))) 194 self.assertEqual('0x0', 195 get_value(fdt.Type.BYTE, struct.pack('>I', 0x45))) 196 self.assertEqual('"test"', get_value(fdt.Type.STRING, 'test')) 197 self.assertEqual('true', get_value(fdt.Type.BOOL, None)) 198 199 def test_get_compat_name(self): 200 """Test operation of get_compat_name() function""" 201 Prop = collections.namedtuple('Prop', ['value']) 202 Node = collections.namedtuple('Node', ['props']) 203 204 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1']) 205 node = Node({'compatible': prop}) 206 self.assertEqual((['rockchip_rk3399_sdhci_5_1', 'arasan_sdhci_5_1']), 207 get_compat_name(node)) 208 209 prop = Prop(['rockchip,rk3399-sdhci-5.1']) 210 node = Node({'compatible': prop}) 211 self.assertEqual((['rockchip_rk3399_sdhci_5_1']), 212 get_compat_name(node)) 213 214 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third']) 215 node = Node({'compatible': prop}) 216 self.assertEqual((['rockchip_rk3399_sdhci_5_1', 217 'arasan_sdhci_5_1', 'third']), 218 get_compat_name(node)) 219 220 def test_empty_file(self): 221 """Test output from a device tree file with no nodes""" 222 dtb_file = get_dtb_file('dtoc_test_empty.dts') 223 output = tools.get_output_filename('output') 224 225 # Run this one without saved_scan to complete test coverage 226 dtb_platdata.run_steps(['struct'], dtb_file, False, output, [], None, 227 False) 228 with open(output) as infile: 229 lines = infile.read().splitlines() 230 self.assertEqual(HEADER.splitlines(), lines) 231 232 self.run_test(['platdata'], dtb_file, output) 233 with open(output) as infile: 234 lines = infile.read().splitlines() 235 self.assertEqual(C_HEADER.splitlines() + [''], lines) 236 237 decl_text = DECL_HEADER + ''' 238#include <dm/device-internal.h> 239#include <dm/uclass-internal.h> 240 241/* driver declarations - these allow DM_DRIVER_GET() to be used */ 242extern U_BOOT_DRIVER(sandbox_i2c); 243extern U_BOOT_DRIVER(sandbox_pmic); 244extern U_BOOT_DRIVER(sandbox_spl_test); 245extern U_BOOT_DRIVER(sandbox_spl_test); 246extern U_BOOT_DRIVER(sandbox_spl_test); 247 248/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */ 249extern UCLASS_DRIVER(i2c); 250extern UCLASS_DRIVER(misc); 251extern UCLASS_DRIVER(pmic); 252''' 253 decl_text_inst = DECL_HEADER + ''' 254#include <dm/device-internal.h> 255#include <dm/uclass-internal.h> 256 257/* driver declarations - these allow DM_DRIVER_GET() to be used */ 258extern U_BOOT_DRIVER(sandbox_i2c); 259extern U_BOOT_DRIVER(root_driver); 260extern U_BOOT_DRIVER(denx_u_boot_test_bus); 261extern U_BOOT_DRIVER(sandbox_spl_test); 262extern U_BOOT_DRIVER(sandbox_spl_test); 263extern U_BOOT_DRIVER(denx_u_boot_fdt_test); 264extern U_BOOT_DRIVER(denx_u_boot_fdt_test); 265 266/* device declarations - these allow DM_DEVICE_REF() to be used */ 267extern DM_DEVICE_INST(i2c); 268extern DM_DEVICE_INST(root); 269extern DM_DEVICE_INST(some_bus); 270extern DM_DEVICE_INST(spl_test); 271extern DM_DEVICE_INST(spl_test3); 272extern DM_DEVICE_INST(test); 273extern DM_DEVICE_INST(test0); 274 275/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */ 276extern UCLASS_DRIVER(i2c); 277extern UCLASS_DRIVER(misc); 278extern UCLASS_DRIVER(root); 279extern UCLASS_DRIVER(testbus); 280extern UCLASS_DRIVER(testfdt); 281 282/* uclass declarations - needed for DM_UCLASS_REF() */ 283extern DM_UCLASS_INST(i2c); 284extern DM_UCLASS_INST(misc); 285extern DM_UCLASS_INST(root); 286extern DM_UCLASS_INST(testbus); 287extern DM_UCLASS_INST(testfdt); 288''' 289 struct_text = HEADER + ''' 290struct dtd_sandbox_i2c { 291}; 292struct dtd_sandbox_pmic { 293\tbool\t\tlow_power; 294\tfdt32_t\t\treg[1]; 295}; 296struct dtd_sandbox_spl_test { 297\tconst char * acpi_name; 298\tbool\t\tboolval; 299\tunsigned char\tbytearray[3]; 300\tunsigned char\tbyteval; 301\tfdt32_t\t\tint64val[2]; 302\tfdt32_t\t\tintarray[3]; 303\tfdt32_t\t\tintval; 304\tunsigned char\tlongbytearray[9]; 305\tfdt32_t\t\tmaybe_empty_int[1]; 306\tunsigned char\tnotstring[5]; 307\tconst char *\tstringarray[3]; 308\tconst char *\tstringval; 309}; 310''' 311 platdata_text = C_HEADER + ''' 312/* 313 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 314 * 315 * idx driver_info driver 316 * --- -------------------- -------------------- 317 * 0: i2c_at_0 sandbox_i2c 318 * 1: pmic_at_9 sandbox_pmic 319 * 2: spl_test sandbox_spl_test 320 * 3: spl_test2 sandbox_spl_test 321 * 4: spl_test3 sandbox_spl_test 322 * --- -------------------- -------------------- 323 */ 324 325/* 326 * Node /i2c@0 index 0 327 * driver sandbox_i2c parent None 328 */ 329static struct dtd_sandbox_i2c dtv_i2c_at_0 = { 330}; 331U_BOOT_DRVINFO(i2c_at_0) = { 332\t.name\t\t= "sandbox_i2c", 333\t.plat\t\t= &dtv_i2c_at_0, 334\t.plat_size\t= sizeof(dtv_i2c_at_0), 335\t.parent_idx\t= -1, 336}; 337 338/* 339 * Node /i2c@0/pmic@9 index 1 340 * driver sandbox_pmic parent sandbox_i2c 341 */ 342static struct dtd_sandbox_pmic dtv_pmic_at_9 = { 343\t.low_power\t\t= true, 344\t.reg\t\t\t= {0x9}, 345}; 346U_BOOT_DRVINFO(pmic_at_9) = { 347\t.name\t\t= "sandbox_pmic", 348\t.plat\t\t= &dtv_pmic_at_9, 349\t.plat_size\t= sizeof(dtv_pmic_at_9), 350\t.parent_idx\t= 0, 351}; 352 353/* 354 * Node /spl-test index 2 355 * driver sandbox_spl_test parent None 356 */ 357static struct dtd_sandbox_spl_test dtv_spl_test = { 358\t.boolval\t\t= true, 359\t.bytearray\t\t= {0x6, 0x0, 0x0}, 360\t.byteval\t\t= 0x5, 361\t.int64val\t\t= {0x12345678, 0x9abcdef0}, 362\t.intarray\t\t= {0x2, 0x3, 0x4}, 363\t.intval\t\t\t= 0x1, 364\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 365\t\t0x11}, 366\t.maybe_empty_int\t= {0x0}, 367\t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0}, 368\t.stringarray\t\t= {"multi-word", "message", ""}, 369\t.stringval\t\t= "message", 370}; 371U_BOOT_DRVINFO(spl_test) = { 372\t.name\t\t= "sandbox_spl_test", 373\t.plat\t\t= &dtv_spl_test, 374\t.plat_size\t= sizeof(dtv_spl_test), 375\t.parent_idx\t= -1, 376}; 377 378/* 379 * Node /spl-test2 index 3 380 * driver sandbox_spl_test parent None 381 */ 382static struct dtd_sandbox_spl_test dtv_spl_test2 = { 383\t.acpi_name\t\t= "\\\\_SB.GPO0", 384\t.bytearray\t\t= {0x1, 0x23, 0x34}, 385\t.byteval\t\t= 0x8, 386\t.intarray\t\t= {0x5, 0x0, 0x0}, 387\t.intval\t\t\t= 0x3, 388\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0x0, 0x0, 0x0, 0x0, 389\t\t0x0}, 390\t.stringarray\t\t= {"another", "multi-word", "message"}, 391\t.stringval\t\t= "message2", 392}; 393U_BOOT_DRVINFO(spl_test2) = { 394\t.name\t\t= "sandbox_spl_test", 395\t.plat\t\t= &dtv_spl_test2, 396\t.plat_size\t= sizeof(dtv_spl_test2), 397\t.parent_idx\t= -1, 398}; 399 400/* 401 * Node /spl-test3 index 4 402 * driver sandbox_spl_test parent None 403 */ 404static struct dtd_sandbox_spl_test dtv_spl_test3 = { 405\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 406\t\t0x0}, 407\t.maybe_empty_int\t= {0x1}, 408\t.stringarray\t\t= {"one", "", ""}, 409}; 410U_BOOT_DRVINFO(spl_test3) = { 411\t.name\t\t= "sandbox_spl_test", 412\t.plat\t\t= &dtv_spl_test3, 413\t.plat_size\t= sizeof(dtv_spl_test3), 414\t.parent_idx\t= -1, 415}; 416 417''' 418 uclass_text_inst = ''' 419 420#include <common.h> 421#include <dm.h> 422#include <dt-structs.h> 423 424/* 425 * uclass declarations, ordered by 'struct uclass' linker_list idx: 426 * 0: i2c 427 * 1: misc 428 * 2: root 429 * 3: testbus 430 * 4: testfdt 431 * 432 * Sequence numbers allocated in each uclass: 433 * i2c: UCLASS_I2C 434 * 4: /i2c 435 * misc: UCLASS_MISC 436 * 0: /spl-test 437 * 1: /spl-test3 438 * root: UCLASS_ROOT 439 * 0: / 440 * testbus: UCLASS_TEST_BUS 441 * 2: /some-bus 442 * testfdt: UCLASS_TEST_FDT 443 * 1: /some-bus/test 444 * 2: /some-bus/test0 445 */ 446 447struct list_head uclass_head = { 448 .prev = &DM_UCLASS_REF(testfdt)->sibling_node, 449 .next = &DM_UCLASS_REF(i2c)->sibling_node, 450}; 451 452DM_UCLASS_INST(i2c) = { 453 .uc_drv = DM_UCLASS_DRIVER_REF(i2c), 454 .sibling_node = { 455 .prev = &uclass_head, 456 .next = &DM_UCLASS_REF(misc)->sibling_node, 457 }, 458 .dev_head = { 459 .prev = &DM_DEVICE_REF(i2c)->uclass_node, 460 .next = &DM_DEVICE_REF(i2c)->uclass_node, 461 }, 462}; 463 464DM_UCLASS_INST(misc) = { 465 .uc_drv = DM_UCLASS_DRIVER_REF(misc), 466 .sibling_node = { 467 .prev = &DM_UCLASS_REF(i2c)->sibling_node, 468 .next = &DM_UCLASS_REF(root)->sibling_node, 469 }, 470 .dev_head = { 471 .prev = &DM_DEVICE_REF(spl_test3)->uclass_node, 472 .next = &DM_DEVICE_REF(spl_test)->uclass_node, 473 }, 474}; 475 476DM_UCLASS_INST(root) = { 477 .uc_drv = DM_UCLASS_DRIVER_REF(root), 478 .sibling_node = { 479 .prev = &DM_UCLASS_REF(misc)->sibling_node, 480 .next = &DM_UCLASS_REF(testbus)->sibling_node, 481 }, 482 .dev_head = { 483 .prev = &DM_DEVICE_REF(root)->uclass_node, 484 .next = &DM_DEVICE_REF(root)->uclass_node, 485 }, 486}; 487 488DM_UCLASS_INST(testbus) = { 489 .uc_drv = DM_UCLASS_DRIVER_REF(testbus), 490 .sibling_node = { 491 .prev = &DM_UCLASS_REF(root)->sibling_node, 492 .next = &DM_UCLASS_REF(testfdt)->sibling_node, 493 }, 494 .dev_head = { 495 .prev = &DM_DEVICE_REF(some_bus)->uclass_node, 496 .next = &DM_DEVICE_REF(some_bus)->uclass_node, 497 }, 498}; 499 500#include <dm/test.h> 501u8 _testfdt_priv_[sizeof(struct dm_test_uc_priv)] 502 __attribute__ ((section (".priv_data"))); 503DM_UCLASS_INST(testfdt) = { 504 .priv_ = _testfdt_priv_, 505 .uc_drv = DM_UCLASS_DRIVER_REF(testfdt), 506 .sibling_node = { 507 .prev = &DM_UCLASS_REF(testbus)->sibling_node, 508 .next = &uclass_head, 509 }, 510 .dev_head = { 511 .prev = &DM_DEVICE_REF(test0)->uclass_node, 512 .next = &DM_DEVICE_REF(test)->uclass_node, 513 }, 514}; 515 516''' 517 device_text_inst = '''/* 518 * DO NOT MODIFY 519 * 520 * Declares the DM_DEVICE_INST() records. 521 * This was generated by dtoc from a .dtb (device tree binary) file. 522 */ 523 524#include <common.h> 525#include <dm.h> 526#include <dt-structs.h> 527 528/* 529 * udevice declarations, ordered by 'struct udevice' linker_list position: 530 * 531 * idx udevice driver 532 * --- -------------------- -------------------- 533 * 0: i2c sandbox_i2c 534 * 1: root root_driver 535 * 2: some_bus denx_u_boot_test_bus 536 * 3: spl_test sandbox_spl_test 537 * 4: spl_test3 sandbox_spl_test 538 * 5: test denx_u_boot_fdt_test 539 * 6: test0 denx_u_boot_fdt_test 540 * --- -------------------- -------------------- 541 */ 542 543/* 544 * Node /i2c index 0 545 * driver sandbox_i2c parent root_driver 546*/ 547static struct dtd_sandbox_i2c dtv_i2c = { 548\t.intval\t\t\t= 0x3, 549}; 550 551#include <asm/i2c.h> 552u8 _sandbox_i2c_priv_i2c[sizeof(struct sandbox_i2c_priv)] 553\t__attribute__ ((section (".priv_data"))); 554#include <i2c.h> 555u8 _sandbox_i2c_uc_priv_i2c[sizeof(struct dm_i2c_bus)] 556\t__attribute__ ((section (".priv_data"))); 557 558DM_DEVICE_INST(i2c) = { 559\t.driver\t\t= DM_DRIVER_REF(sandbox_i2c), 560\t.name\t\t= "sandbox_i2c", 561\t.plat_\t\t= &dtv_i2c, 562\t.priv_\t\t= _sandbox_i2c_priv_i2c, 563\t.uclass\t\t= DM_UCLASS_REF(i2c), 564\t.uclass_priv_ = _sandbox_i2c_uc_priv_i2c, 565\t.uclass_node\t= { 566\t\t.prev = &DM_UCLASS_REF(i2c)->dev_head, 567\t\t.next = &DM_UCLASS_REF(i2c)->dev_head, 568\t}, 569\t.child_head\t= { 570\t\t.prev = &DM_DEVICE_REF(i2c)->child_head, 571\t\t.next = &DM_DEVICE_REF(i2c)->child_head, 572\t}, 573\t.sibling_node\t= { 574\t\t.prev = &DM_DEVICE_REF(root)->child_head, 575\t\t.next = &DM_DEVICE_REF(some_bus)->sibling_node, 576\t}, 577\t.seq_ = 4, 578}; 579 580/* 581 * Node / index 1 582 * driver root_driver parent None 583*/ 584static struct dtd_root_driver dtv_root = { 585}; 586 587DM_DEVICE_INST(root) = { 588\t.driver\t\t= DM_DRIVER_REF(root_driver), 589\t.name\t\t= "root_driver", 590\t.plat_\t\t= &dtv_root, 591\t.uclass\t\t= DM_UCLASS_REF(root), 592\t.uclass_node\t= { 593\t\t.prev = &DM_UCLASS_REF(root)->dev_head, 594\t\t.next = &DM_UCLASS_REF(root)->dev_head, 595\t}, 596\t.child_head\t= { 597\t\t.prev = &DM_DEVICE_REF(spl_test3)->sibling_node, 598\t\t.next = &DM_DEVICE_REF(i2c)->sibling_node, 599\t}, 600\t.seq_ = 0, 601}; 602 603/* 604 * Node /some-bus index 2 605 * driver denx_u_boot_test_bus parent root_driver 606*/ 607 608#include <dm/test.h> 609struct dm_test_pdata __attribute__ ((section (".priv_data"))) 610\t_denx_u_boot_test_bus_plat_some_bus = { 611\t.dtplat = { 612\t\t.ping_add\t\t= 0x4, 613\t\t.ping_expect\t\t= 0x4, 614\t\t.reg\t\t\t= {0x3, 0x1}, 615\t}, 616}; 617#include <dm/test.h> 618u8 _denx_u_boot_test_bus_priv_some_bus[sizeof(struct dm_test_priv)] 619\t__attribute__ ((section (".priv_data"))); 620#include <dm/test.h> 621u8 _denx_u_boot_test_bus_ucplat_some_bus[sizeof(struct dm_test_uclass_plat)] 622\t__attribute__ ((section (".priv_data"))); 623#include <dm/test.h> 624u8 _denx_u_boot_test_bus_uc_priv_some_bus[sizeof(struct dm_test_uclass_priv)] 625 __attribute__ ((section (".priv_data"))); 626#include <test.h> 627 628DM_DEVICE_INST(some_bus) = { 629\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_test_bus), 630\t.name\t\t= "denx_u_boot_test_bus", 631\t.plat_\t\t= &_denx_u_boot_test_bus_plat_some_bus, 632\t.uclass_plat_\t= _denx_u_boot_test_bus_ucplat_some_bus, 633\t.driver_data\t= DM_TEST_TYPE_FIRST, 634\t.priv_\t\t= _denx_u_boot_test_bus_priv_some_bus, 635\t.uclass\t\t= DM_UCLASS_REF(testbus), 636\t.uclass_priv_ = _denx_u_boot_test_bus_uc_priv_some_bus, 637\t.uclass_node\t= { 638\t\t.prev = &DM_UCLASS_REF(testbus)->dev_head, 639\t\t.next = &DM_UCLASS_REF(testbus)->dev_head, 640\t}, 641\t.child_head\t= { 642\t\t.prev = &DM_DEVICE_REF(test0)->sibling_node, 643\t\t.next = &DM_DEVICE_REF(test)->sibling_node, 644\t}, 645\t.sibling_node\t= { 646\t\t.prev = &DM_DEVICE_REF(i2c)->sibling_node, 647\t\t.next = &DM_DEVICE_REF(spl_test)->sibling_node, 648\t}, 649\t.seq_ = 2, 650}; 651 652/* 653 * Node /spl-test index 3 654 * driver sandbox_spl_test parent root_driver 655*/ 656static struct dtd_sandbox_spl_test dtv_spl_test = { 657\t.boolval\t\t= true, 658\t.intval\t\t\t= 0x1, 659}; 660 661DM_DEVICE_INST(spl_test) = { 662\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test), 663\t.name\t\t= "sandbox_spl_test", 664\t.plat_\t\t= &dtv_spl_test, 665\t.uclass\t\t= DM_UCLASS_REF(misc), 666\t.uclass_node\t= { 667\t\t.prev = &DM_UCLASS_REF(misc)->dev_head, 668\t\t.next = &DM_DEVICE_REF(spl_test3)->uclass_node, 669\t}, 670\t.child_head\t= { 671\t\t.prev = &DM_DEVICE_REF(spl_test)->child_head, 672\t\t.next = &DM_DEVICE_REF(spl_test)->child_head, 673\t}, 674\t.sibling_node\t= { 675\t\t.prev = &DM_DEVICE_REF(some_bus)->sibling_node, 676\t\t.next = &DM_DEVICE_REF(spl_test3)->sibling_node, 677\t}, 678\t.seq_ = 0, 679}; 680 681/* 682 * Node /spl-test3 index 4 683 * driver sandbox_spl_test parent root_driver 684*/ 685static struct dtd_sandbox_spl_test dtv_spl_test3 = { 686\t.longbytearray\t\t= {0x90a0b0c, 0xd0e0f10}, 687\t.stringarray\t\t= "one", 688}; 689 690DM_DEVICE_INST(spl_test3) = { 691\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test), 692\t.name\t\t= "sandbox_spl_test", 693\t.plat_\t\t= &dtv_spl_test3, 694\t.uclass\t\t= DM_UCLASS_REF(misc), 695\t.uclass_node\t= { 696\t\t.prev = &DM_DEVICE_REF(spl_test)->uclass_node, 697\t\t.next = &DM_UCLASS_REF(misc)->dev_head, 698\t}, 699\t.child_head\t= { 700\t\t.prev = &DM_DEVICE_REF(spl_test3)->child_head, 701\t\t.next = &DM_DEVICE_REF(spl_test3)->child_head, 702\t}, 703\t.sibling_node\t= { 704\t\t.prev = &DM_DEVICE_REF(spl_test)->sibling_node, 705\t\t.next = &DM_DEVICE_REF(root)->child_head, 706\t}, 707\t.seq_ = 1, 708}; 709 710/* 711 * Node /some-bus/test index 5 712 * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus 713*/ 714 715#include <dm/test.h> 716struct dm_test_pdata __attribute__ ((section (".priv_data"))) 717\t_denx_u_boot_fdt_test_plat_test = { 718\t.dtplat = { 719\t\t.ping_add\t\t= 0x5, 720\t\t.ping_expect\t\t= 0x5, 721\t\t.reg\t\t\t= {0x5}, 722\t}, 723}; 724#include <dm/test.h> 725u8 _denx_u_boot_fdt_test_priv_test[sizeof(struct dm_test_priv)] 726\t__attribute__ ((section (".priv_data"))); 727#include <dm/test.h> 728u8 _denx_u_boot_fdt_test_parent_plat_test[sizeof(struct dm_test_parent_plat)] 729\t__attribute__ ((section (".priv_data"))); 730#include <dm/test.h> 731u8 _denx_u_boot_fdt_test_parent_priv_test[sizeof(struct dm_test_parent_data)] 732\t__attribute__ ((section (".priv_data"))); 733 734DM_DEVICE_INST(test) = { 735\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test), 736\t.name\t\t= "denx_u_boot_fdt_test", 737\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test, 738\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test, 739\t.driver_data\t= DM_TEST_TYPE_FIRST, 740\t.parent\t\t= DM_DEVICE_REF(some_bus), 741\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test, 742\t.uclass\t\t= DM_UCLASS_REF(testfdt), 743\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test, 744\t.uclass_node\t= { 745\t\t.prev = &DM_UCLASS_REF(testfdt)->dev_head, 746\t\t.next = &DM_DEVICE_REF(test0)->uclass_node, 747\t}, 748\t.child_head\t= { 749\t\t.prev = &DM_DEVICE_REF(test)->child_head, 750\t\t.next = &DM_DEVICE_REF(test)->child_head, 751\t}, 752\t.sibling_node\t= { 753\t\t.prev = &DM_DEVICE_REF(some_bus)->child_head, 754\t\t.next = &DM_DEVICE_REF(test0)->sibling_node, 755\t}, 756\t.seq_ = 1, 757}; 758 759/* 760 * Node /some-bus/test0 index 6 761 * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus 762*/ 763 764#include <dm/test.h> 765struct dm_test_pdata __attribute__ ((section (".priv_data"))) 766\t_denx_u_boot_fdt_test_plat_test0 = { 767\t.dtplat = { 768\t}, 769}; 770#include <dm/test.h> 771u8 _denx_u_boot_fdt_test_priv_test0[sizeof(struct dm_test_priv)] 772\t__attribute__ ((section (".priv_data"))); 773#include <dm/test.h> 774u8 _denx_u_boot_fdt_test_parent_plat_test0[sizeof(struct dm_test_parent_plat)] 775\t__attribute__ ((section (".priv_data"))); 776#include <dm/test.h> 777u8 _denx_u_boot_fdt_test_parent_priv_test0[sizeof(struct dm_test_parent_data)] 778\t__attribute__ ((section (".priv_data"))); 779 780DM_DEVICE_INST(test0) = { 781\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test), 782\t.name\t\t= "denx_u_boot_fdt_test", 783\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test0, 784\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test0, 785\t.driver_data\t= DM_TEST_TYPE_SECOND, 786\t.parent\t\t= DM_DEVICE_REF(some_bus), 787\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test0, 788\t.uclass\t\t= DM_UCLASS_REF(testfdt), 789\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test0, 790\t.uclass_node\t= { 791\t\t.prev = &DM_DEVICE_REF(test)->uclass_node, 792\t\t.next = &DM_UCLASS_REF(testfdt)->dev_head, 793\t}, 794\t.child_head\t= { 795\t\t.prev = &DM_DEVICE_REF(test0)->child_head, 796\t\t.next = &DM_DEVICE_REF(test0)->child_head, 797\t}, 798\t.sibling_node\t= { 799\t\t.prev = &DM_DEVICE_REF(test)->sibling_node, 800\t\t.next = &DM_DEVICE_REF(some_bus)->child_head, 801\t}, 802\t.seq_ = 2, 803}; 804 805''' 806 807 def test_simple(self): 808 """Test output from some simple nodes with various types of data""" 809 dtb_file = get_dtb_file('dtoc_test_simple.dts') 810 output = tools.get_output_filename('output') 811 self.run_test(['struct'], dtb_file, output) 812 with open(output) as infile: 813 data = infile.read() 814 815 self._check_strings(self.struct_text, data) 816 817 self.run_test(['platdata'], dtb_file, output) 818 with open(output) as infile: 819 data = infile.read() 820 821 self._check_strings(self.platdata_text, data) 822 823 self.run_test(['decl'], dtb_file, output) 824 with open(output) as infile: 825 data = infile.read() 826 827 self._check_strings(self.decl_text, data) 828 829 # Try the 'all' command 830 self.run_test(['all'], dtb_file, output) 831 data = tools.read_file(output, binary=False) 832 self._check_strings( 833 self.decl_text + self.platdata_text + self.struct_text, data) 834 835 def test_driver_alias(self): 836 """Test output from a device tree file with a driver alias""" 837 dtb_file = get_dtb_file('dtoc_test_driver_alias.dts') 838 output = tools.get_output_filename('output') 839 self.run_test(['struct'], dtb_file, output) 840 with open(output) as infile: 841 data = infile.read() 842 self._check_strings(HEADER + ''' 843struct dtd_sandbox_gpio { 844\tconst char *\tgpio_bank_name; 845\tbool\t\tgpio_controller; 846\tfdt32_t\t\tsandbox_gpio_count; 847}; 848''', data) 849 850 self.run_test(['platdata'], dtb_file, output) 851 with open(output) as infile: 852 data = infile.read() 853 self._check_strings(C_HEADER + ''' 854/* 855 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 856 * 857 * idx driver_info driver 858 * --- -------------------- -------------------- 859 * 0: gpios_at_0 sandbox_gpio 860 * --- -------------------- -------------------- 861 */ 862 863/* 864 * Node /gpios@0 index 0 865 * driver sandbox_gpio parent None 866 */ 867static struct dtd_sandbox_gpio dtv_gpios_at_0 = { 868\t.gpio_bank_name\t\t= "a", 869\t.gpio_controller\t= true, 870\t.sandbox_gpio_count\t= 0x14, 871}; 872U_BOOT_DRVINFO(gpios_at_0) = { 873\t.name\t\t= "sandbox_gpio", 874\t.plat\t\t= &dtv_gpios_at_0, 875\t.plat_size\t= sizeof(dtv_gpios_at_0), 876\t.parent_idx\t= -1, 877}; 878 879''', data) 880 881 def test_invalid_driver(self): 882 """Test output from a device tree file with an invalid driver""" 883 dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts') 884 output = tools.get_output_filename('output') 885 with test_util.capture_sys_output() as _: 886 dtb_platdata.run_steps( 887 ['struct'], dtb_file, False, output, [], None, False, 888 scan=copy_scan()) 889 with open(output) as infile: 890 data = infile.read() 891 self._check_strings(HEADER + ''' 892struct dtd_invalid { 893}; 894''', data) 895 896 with test_util.capture_sys_output() as _: 897 dtb_platdata.run_steps( 898 ['platdata'], dtb_file, False, output, [], None, False, 899 scan=copy_scan()) 900 with open(output) as infile: 901 data = infile.read() 902 self._check_strings(C_HEADER + ''' 903/* 904 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 905 * 906 * idx driver_info driver 907 * --- -------------------- -------------------- 908 * 0: spl_test invalid 909 * --- -------------------- -------------------- 910 */ 911 912/* Node /spl-test index 0 */ 913static struct dtd_invalid dtv_spl_test = { 914}; 915U_BOOT_DRVINFO(spl_test) = { 916\t.name\t\t= "invalid", 917\t.plat\t\t= &dtv_spl_test, 918\t.plat_size\t= sizeof(dtv_spl_test), 919\t.parent_idx\t= -1, 920}; 921 922''', data) 923 924 def test_phandle(self): 925 """Test output from a node containing a phandle reference""" 926 dtb_file = get_dtb_file('dtoc_test_phandle.dts') 927 output = tools.get_output_filename('output') 928 self.run_test(['struct'], dtb_file, output) 929 with open(output) as infile: 930 data = infile.read() 931 self._check_strings(HEADER + ''' 932struct dtd_source { 933\tstruct phandle_2_arg clocks[4]; 934\tunsigned char phandle_name_offset[13]; 935}; 936struct dtd_target { 937\tfdt32_t\t\tintval; 938}; 939''', data) 940 941 self.run_test(['platdata'], dtb_file, output) 942 with open(output) as infile: 943 data = infile.read() 944 self._check_strings(C_HEADER + ''' 945/* 946 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 947 * 948 * idx driver_info driver 949 * --- -------------------- -------------------- 950 * 0: phandle2_target target 951 * 1: phandle3_target target 952 * 2: phandle_source source 953 * 3: phandle_source2 source 954 * 4: phandle_target target 955 * --- -------------------- -------------------- 956 */ 957 958/* Node /phandle2-target index 0 */ 959static struct dtd_target dtv_phandle2_target = { 960\t.intval\t\t\t= 0x1, 961}; 962U_BOOT_DRVINFO(phandle2_target) = { 963\t.name\t\t= "target", 964\t.plat\t\t= &dtv_phandle2_target, 965\t.plat_size\t= sizeof(dtv_phandle2_target), 966\t.parent_idx\t= -1, 967}; 968 969/* Node /phandle3-target index 1 */ 970static struct dtd_target dtv_phandle3_target = { 971\t.intval\t\t\t= 0x2, 972}; 973U_BOOT_DRVINFO(phandle3_target) = { 974\t.name\t\t= "target", 975\t.plat\t\t= &dtv_phandle3_target, 976\t.plat_size\t= sizeof(dtv_phandle3_target), 977\t.parent_idx\t= -1, 978}; 979 980/* Node /phandle-source index 2 */ 981static struct dtd_source dtv_phandle_source = { 982\t.clocks\t\t\t= { 983\t\t\t{4, {}}, 984\t\t\t{0, {11}}, 985\t\t\t{1, {12, 13}}, 986\t\t\t{4, {}},}, 987\t.phandle_name_offset = {0x0, 0x0, 0x0, 0x3, 0x66, 0x72, 0x65, 0x64, 988\t\t0x0, 0x0, 0x0, 0x0, 0x7b}, 989}; 990U_BOOT_DRVINFO(phandle_source) = { 991\t.name\t\t= "source", 992\t.plat\t\t= &dtv_phandle_source, 993\t.plat_size\t= sizeof(dtv_phandle_source), 994\t.parent_idx\t= -1, 995}; 996 997/* Node /phandle-source2 index 3 */ 998static struct dtd_source dtv_phandle_source2 = { 999\t.clocks\t\t\t= { 1000\t\t\t{4, {}},}, 1001}; 1002U_BOOT_DRVINFO(phandle_source2) = { 1003\t.name\t\t= "source", 1004\t.plat\t\t= &dtv_phandle_source2, 1005\t.plat_size\t= sizeof(dtv_phandle_source2), 1006\t.parent_idx\t= -1, 1007}; 1008 1009/* Node /phandle-target index 4 */ 1010static struct dtd_target dtv_phandle_target = { 1011\t.intval\t\t\t= 0x0, 1012}; 1013U_BOOT_DRVINFO(phandle_target) = { 1014\t.name\t\t= "target", 1015\t.plat\t\t= &dtv_phandle_target, 1016\t.plat_size\t= sizeof(dtv_phandle_target), 1017\t.parent_idx\t= -1, 1018}; 1019 1020''', data) 1021 1022 def test_phandle_single(self): 1023 """Test output from a node containing a phandle reference""" 1024 dtb_file = get_dtb_file('dtoc_test_phandle_single.dts') 1025 output = tools.get_output_filename('output') 1026 self.run_test(['struct'], dtb_file, output) 1027 with open(output) as infile: 1028 data = infile.read() 1029 self._check_strings(HEADER + ''' 1030struct dtd_source { 1031\tstruct phandle_0_arg clocks[1]; 1032}; 1033struct dtd_target { 1034\tfdt32_t\t\tintval; 1035}; 1036''', data) 1037 1038 def test_phandle_reorder(self): 1039 """Test that phandle targets are generated before their references""" 1040 dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts') 1041 output = tools.get_output_filename('output') 1042 self.run_test(['platdata'], dtb_file, output) 1043 with open(output) as infile: 1044 data = infile.read() 1045 self._check_strings(C_HEADER + ''' 1046/* 1047 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1048 * 1049 * idx driver_info driver 1050 * --- -------------------- -------------------- 1051 * 0: phandle_source2 source 1052 * 1: phandle_target target 1053 * --- -------------------- -------------------- 1054 */ 1055 1056/* Node /phandle-source2 index 0 */ 1057static struct dtd_source dtv_phandle_source2 = { 1058\t.clocks\t\t\t= { 1059\t\t\t{1, {}},}, 1060}; 1061U_BOOT_DRVINFO(phandle_source2) = { 1062\t.name\t\t= "source", 1063\t.plat\t\t= &dtv_phandle_source2, 1064\t.plat_size\t= sizeof(dtv_phandle_source2), 1065\t.parent_idx\t= -1, 1066}; 1067 1068/* Node /phandle-target index 1 */ 1069static struct dtd_target dtv_phandle_target = { 1070}; 1071U_BOOT_DRVINFO(phandle_target) = { 1072\t.name\t\t= "target", 1073\t.plat\t\t= &dtv_phandle_target, 1074\t.plat_size\t= sizeof(dtv_phandle_target), 1075\t.parent_idx\t= -1, 1076}; 1077 1078''', data) 1079 1080 def test_phandle_cd_gpio(self): 1081 """Test that phandle targets are generated when unsing cd-gpios""" 1082 dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts') 1083 output = tools.get_output_filename('output') 1084 dtb_platdata.run_steps( 1085 ['platdata'], dtb_file, False, output, [], None, False, 1086 warning_disabled=True, scan=copy_scan()) 1087 with open(output) as infile: 1088 data = infile.read() 1089 self._check_strings(C_HEADER + ''' 1090/* 1091 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1092 * 1093 * idx driver_info driver 1094 * --- -------------------- -------------------- 1095 * 0: phandle2_target target 1096 * 1: phandle3_target target 1097 * 2: phandle_source source 1098 * 3: phandle_source2 source 1099 * 4: phandle_target target 1100 * --- -------------------- -------------------- 1101 */ 1102 1103/* Node /phandle2-target index 0 */ 1104static struct dtd_target dtv_phandle2_target = { 1105\t.intval\t\t\t= 0x1, 1106}; 1107U_BOOT_DRVINFO(phandle2_target) = { 1108\t.name\t\t= "target", 1109\t.plat\t\t= &dtv_phandle2_target, 1110\t.plat_size\t= sizeof(dtv_phandle2_target), 1111\t.parent_idx\t= -1, 1112}; 1113 1114/* Node /phandle3-target index 1 */ 1115static struct dtd_target dtv_phandle3_target = { 1116\t.intval\t\t\t= 0x2, 1117}; 1118U_BOOT_DRVINFO(phandle3_target) = { 1119\t.name\t\t= "target", 1120\t.plat\t\t= &dtv_phandle3_target, 1121\t.plat_size\t= sizeof(dtv_phandle3_target), 1122\t.parent_idx\t= -1, 1123}; 1124 1125/* Node /phandle-source index 2 */ 1126static struct dtd_source dtv_phandle_source = { 1127\t.cd_gpios\t\t= { 1128\t\t\t{4, {}}, 1129\t\t\t{0, {11}}, 1130\t\t\t{1, {12, 13}}, 1131\t\t\t{4, {}},}, 1132}; 1133U_BOOT_DRVINFO(phandle_source) = { 1134\t.name\t\t= "source", 1135\t.plat\t\t= &dtv_phandle_source, 1136\t.plat_size\t= sizeof(dtv_phandle_source), 1137\t.parent_idx\t= -1, 1138}; 1139 1140/* Node /phandle-source2 index 3 */ 1141static struct dtd_source dtv_phandle_source2 = { 1142\t.cd_gpios\t\t= { 1143\t\t\t{4, {}},}, 1144}; 1145U_BOOT_DRVINFO(phandle_source2) = { 1146\t.name\t\t= "source", 1147\t.plat\t\t= &dtv_phandle_source2, 1148\t.plat_size\t= sizeof(dtv_phandle_source2), 1149\t.parent_idx\t= -1, 1150}; 1151 1152/* Node /phandle-target index 4 */ 1153static struct dtd_target dtv_phandle_target = { 1154\t.intval\t\t\t= 0x0, 1155}; 1156U_BOOT_DRVINFO(phandle_target) = { 1157\t.name\t\t= "target", 1158\t.plat\t\t= &dtv_phandle_target, 1159\t.plat_size\t= sizeof(dtv_phandle_target), 1160\t.parent_idx\t= -1, 1161}; 1162 1163''', data) 1164 1165 def test_phandle_bad(self): 1166 """Test a node containing an invalid phandle fails""" 1167 dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts', 1168 capture_stderr=True) 1169 output = tools.get_output_filename('output') 1170 with self.assertRaises(ValueError) as exc: 1171 self.run_test(['struct'], dtb_file, output) 1172 self.assertIn("Cannot parse 'clocks' in node 'phandle-source'", 1173 str(exc.exception)) 1174 1175 def test_phandle_bad2(self): 1176 """Test a phandle target missing its #*-cells property""" 1177 dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts', 1178 capture_stderr=True) 1179 output = tools.get_output_filename('output') 1180 with self.assertRaises(ValueError) as exc: 1181 self.run_test(['struct'], dtb_file, output) 1182 self.assertIn("Node 'phandle-target' has no cells property", 1183 str(exc.exception)) 1184 1185 def test_addresses64(self): 1186 """Test output from a node with a 'reg' property with na=2, ns=2""" 1187 dtb_file = get_dtb_file('dtoc_test_addr64.dts') 1188 output = tools.get_output_filename('output') 1189 self.run_test(['struct'], dtb_file, output) 1190 with open(output) as infile: 1191 data = infile.read() 1192 self._check_strings(HEADER + ''' 1193struct dtd_test1 { 1194\tfdt64_t\t\treg[2]; 1195}; 1196struct dtd_test2 { 1197\tfdt64_t\t\treg[2]; 1198}; 1199struct dtd_test3 { 1200\tfdt64_t\t\treg[4]; 1201}; 1202''', data) 1203 1204 self.run_test(['platdata'], dtb_file, output) 1205 with open(output) as infile: 1206 data = infile.read() 1207 self._check_strings(C_HEADER + ''' 1208/* 1209 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1210 * 1211 * idx driver_info driver 1212 * --- -------------------- -------------------- 1213 * 0: test1 test1 1214 * 1: test2 test2 1215 * 2: test3 test3 1216 * --- -------------------- -------------------- 1217 */ 1218 1219/* Node /test1 index 0 */ 1220static struct dtd_test1 dtv_test1 = { 1221\t.reg\t\t\t= {0x1234, 0x5678}, 1222}; 1223U_BOOT_DRVINFO(test1) = { 1224\t.name\t\t= "test1", 1225\t.plat\t\t= &dtv_test1, 1226\t.plat_size\t= sizeof(dtv_test1), 1227\t.parent_idx\t= -1, 1228}; 1229 1230/* Node /test2 index 1 */ 1231static struct dtd_test2 dtv_test2 = { 1232\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, 1233}; 1234U_BOOT_DRVINFO(test2) = { 1235\t.name\t\t= "test2", 1236\t.plat\t\t= &dtv_test2, 1237\t.plat_size\t= sizeof(dtv_test2), 1238\t.parent_idx\t= -1, 1239}; 1240 1241/* Node /test3 index 2 */ 1242static struct dtd_test3 dtv_test3 = { 1243\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, 1244}; 1245U_BOOT_DRVINFO(test3) = { 1246\t.name\t\t= "test3", 1247\t.plat\t\t= &dtv_test3, 1248\t.plat_size\t= sizeof(dtv_test3), 1249\t.parent_idx\t= -1, 1250}; 1251 1252''', data) 1253 1254 def test_addresses32(self): 1255 """Test output from a node with a 'reg' property with na=1, ns=1""" 1256 dtb_file = get_dtb_file('dtoc_test_addr32.dts') 1257 output = tools.get_output_filename('output') 1258 self.run_test(['struct'], dtb_file, output) 1259 with open(output) as infile: 1260 data = infile.read() 1261 self._check_strings(HEADER + ''' 1262struct dtd_test1 { 1263\tfdt32_t\t\treg[2]; 1264}; 1265struct dtd_test2 { 1266\tfdt32_t\t\treg[4]; 1267}; 1268''', data) 1269 1270 self.run_test(['platdata'], dtb_file, output) 1271 with open(output) as infile: 1272 data = infile.read() 1273 self._check_strings(C_HEADER + ''' 1274/* 1275 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1276 * 1277 * idx driver_info driver 1278 * --- -------------------- -------------------- 1279 * 0: test1 test1 1280 * 1: test2 test2 1281 * --- -------------------- -------------------- 1282 */ 1283 1284/* Node /test1 index 0 */ 1285static struct dtd_test1 dtv_test1 = { 1286\t.reg\t\t\t= {0x1234, 0x5678}, 1287}; 1288U_BOOT_DRVINFO(test1) = { 1289\t.name\t\t= "test1", 1290\t.plat\t\t= &dtv_test1, 1291\t.plat_size\t= sizeof(dtv_test1), 1292\t.parent_idx\t= -1, 1293}; 1294 1295/* Node /test2 index 1 */ 1296static struct dtd_test2 dtv_test2 = { 1297\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, 1298}; 1299U_BOOT_DRVINFO(test2) = { 1300\t.name\t\t= "test2", 1301\t.plat\t\t= &dtv_test2, 1302\t.plat_size\t= sizeof(dtv_test2), 1303\t.parent_idx\t= -1, 1304}; 1305 1306''', data) 1307 1308 def test_addresses64_32(self): 1309 """Test output from a node with a 'reg' property with na=2, ns=1""" 1310 dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') 1311 output = tools.get_output_filename('output') 1312 self.run_test(['struct'], dtb_file, output) 1313 with open(output) as infile: 1314 data = infile.read() 1315 self._check_strings(HEADER + ''' 1316struct dtd_test1 { 1317\tfdt64_t\t\treg[2]; 1318}; 1319struct dtd_test2 { 1320\tfdt64_t\t\treg[2]; 1321}; 1322struct dtd_test3 { 1323\tfdt64_t\t\treg[4]; 1324}; 1325''', data) 1326 1327 self.run_test(['platdata'], dtb_file, output) 1328 with open(output) as infile: 1329 data = infile.read() 1330 self._check_strings(C_HEADER + ''' 1331/* 1332 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1333 * 1334 * idx driver_info driver 1335 * --- -------------------- -------------------- 1336 * 0: test1 test1 1337 * 1: test2 test2 1338 * 2: test3 test3 1339 * --- -------------------- -------------------- 1340 */ 1341 1342/* Node /test1 index 0 */ 1343static struct dtd_test1 dtv_test1 = { 1344\t.reg\t\t\t= {0x123400000000, 0x5678}, 1345}; 1346U_BOOT_DRVINFO(test1) = { 1347\t.name\t\t= "test1", 1348\t.plat\t\t= &dtv_test1, 1349\t.plat_size\t= sizeof(dtv_test1), 1350\t.parent_idx\t= -1, 1351}; 1352 1353/* Node /test2 index 1 */ 1354static struct dtd_test2 dtv_test2 = { 1355\t.reg\t\t\t= {0x1234567890123456, 0x98765432}, 1356}; 1357U_BOOT_DRVINFO(test2) = { 1358\t.name\t\t= "test2", 1359\t.plat\t\t= &dtv_test2, 1360\t.plat_size\t= sizeof(dtv_test2), 1361\t.parent_idx\t= -1, 1362}; 1363 1364/* Node /test3 index 2 */ 1365static struct dtd_test3 dtv_test3 = { 1366\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, 1367}; 1368U_BOOT_DRVINFO(test3) = { 1369\t.name\t\t= "test3", 1370\t.plat\t\t= &dtv_test3, 1371\t.plat_size\t= sizeof(dtv_test3), 1372\t.parent_idx\t= -1, 1373}; 1374 1375''', data) 1376 1377 def test_addresses32_64(self): 1378 """Test output from a node with a 'reg' property with na=1, ns=2""" 1379 dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') 1380 output = tools.get_output_filename('output') 1381 self.run_test(['struct'], dtb_file, output) 1382 with open(output) as infile: 1383 data = infile.read() 1384 self._check_strings(HEADER + ''' 1385struct dtd_test1 { 1386\tfdt64_t\t\treg[2]; 1387}; 1388struct dtd_test2 { 1389\tfdt64_t\t\treg[2]; 1390}; 1391struct dtd_test3 { 1392\tfdt64_t\t\treg[4]; 1393}; 1394''', data) 1395 1396 self.run_test(['platdata'], dtb_file, output) 1397 with open(output) as infile: 1398 data = infile.read() 1399 self._check_strings(C_HEADER + ''' 1400/* 1401 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1402 * 1403 * idx driver_info driver 1404 * --- -------------------- -------------------- 1405 * 0: test1 test1 1406 * 1: test2 test2 1407 * 2: test3 test3 1408 * --- -------------------- -------------------- 1409 */ 1410 1411/* Node /test1 index 0 */ 1412static struct dtd_test1 dtv_test1 = { 1413\t.reg\t\t\t= {0x1234, 0x567800000000}, 1414}; 1415U_BOOT_DRVINFO(test1) = { 1416\t.name\t\t= "test1", 1417\t.plat\t\t= &dtv_test1, 1418\t.plat_size\t= sizeof(dtv_test1), 1419\t.parent_idx\t= -1, 1420}; 1421 1422/* Node /test2 index 1 */ 1423static struct dtd_test2 dtv_test2 = { 1424\t.reg\t\t\t= {0x12345678, 0x9876543210987654}, 1425}; 1426U_BOOT_DRVINFO(test2) = { 1427\t.name\t\t= "test2", 1428\t.plat\t\t= &dtv_test2, 1429\t.plat_size\t= sizeof(dtv_test2), 1430\t.parent_idx\t= -1, 1431}; 1432 1433/* Node /test3 index 2 */ 1434static struct dtd_test3 dtv_test3 = { 1435\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, 1436}; 1437U_BOOT_DRVINFO(test3) = { 1438\t.name\t\t= "test3", 1439\t.plat\t\t= &dtv_test3, 1440\t.plat_size\t= sizeof(dtv_test3), 1441\t.parent_idx\t= -1, 1442}; 1443 1444''', data) 1445 1446 def test_bad_reg(self): 1447 """Test that a reg property with an invalid type generates an error""" 1448 # Capture stderr since dtc will emit warnings for this file 1449 dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True) 1450 output = tools.get_output_filename('output') 1451 with self.assertRaises(ValueError) as exc: 1452 self.run_test(['struct'], dtb_file, output) 1453 self.assertIn("Node 'spl-test' reg property is not an int", 1454 str(exc.exception)) 1455 1456 def test_bad_reg2(self): 1457 """Test that a reg property with an invalid cell count is detected""" 1458 # Capture stderr since dtc will emit warnings for this file 1459 dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True) 1460 output = tools.get_output_filename('output') 1461 with self.assertRaises(ValueError) as exc: 1462 self.run_test(['struct'], dtb_file, output) 1463 self.assertIn( 1464 "Node 'spl-test' (parent '/') reg property has 3 cells which is not a multiple of na + ns = 1 + 1)", 1465 str(exc.exception)) 1466 1467 def test_add_prop(self): 1468 """Test that a subequent node can add a new property to a struct""" 1469 dtb_file = get_dtb_file('dtoc_test_add_prop.dts') 1470 output = tools.get_output_filename('output') 1471 self.run_test(['struct'], dtb_file, output) 1472 with open(output) as infile: 1473 data = infile.read() 1474 self._check_strings(HEADER + ''' 1475struct dtd_sandbox_spl_test { 1476\tfdt32_t\t\tintarray; 1477\tfdt32_t\t\tintval; 1478}; 1479''', data) 1480 1481 self.run_test(['platdata'], dtb_file, output) 1482 with open(output) as infile: 1483 data = infile.read() 1484 self._check_strings(C_HEADER + ''' 1485/* 1486 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1487 * 1488 * idx driver_info driver 1489 * --- -------------------- -------------------- 1490 * 0: spl_test sandbox_spl_test 1491 * 1: spl_test2 sandbox_spl_test 1492 * --- -------------------- -------------------- 1493 */ 1494 1495/* 1496 * Node /spl-test index 0 1497 * driver sandbox_spl_test parent None 1498 */ 1499static struct dtd_sandbox_spl_test dtv_spl_test = { 1500\t.intval\t\t\t= 0x1, 1501}; 1502U_BOOT_DRVINFO(spl_test) = { 1503\t.name\t\t= "sandbox_spl_test", 1504\t.plat\t\t= &dtv_spl_test, 1505\t.plat_size\t= sizeof(dtv_spl_test), 1506\t.parent_idx\t= -1, 1507}; 1508 1509/* 1510 * Node /spl-test2 index 1 1511 * driver sandbox_spl_test parent None 1512 */ 1513static struct dtd_sandbox_spl_test dtv_spl_test2 = { 1514\t.intarray\t\t= 0x5, 1515}; 1516U_BOOT_DRVINFO(spl_test2) = { 1517\t.name\t\t= "sandbox_spl_test", 1518\t.plat\t\t= &dtv_spl_test2, 1519\t.plat_size\t= sizeof(dtv_spl_test2), 1520\t.parent_idx\t= -1, 1521}; 1522 1523''', data) 1524 1525 def test_stdout(self): 1526 """Test output to stdout""" 1527 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1528 with test_util.capture_sys_output() as (stdout, _): 1529 self.run_test(['struct'], dtb_file, None) 1530 self._check_strings(self.struct_text, stdout.getvalue()) 1531 1532 def test_multi_to_file(self): 1533 """Test output of multiple pieces to a single file""" 1534 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1535 output = tools.get_output_filename('output') 1536 self.run_test(['all'], dtb_file, output) 1537 data = tools.read_file(output, binary=False) 1538 self._check_strings( 1539 self.decl_text + self.platdata_text + self.struct_text, data) 1540 1541 def test_no_command(self): 1542 """Test running dtoc without a command""" 1543 with self.assertRaises(ValueError) as exc: 1544 self.run_test([], '', '') 1545 self.assertIn("Please specify a command: struct, platdata", 1546 str(exc.exception)) 1547 1548 def test_bad_command(self): 1549 """Test running dtoc with an invalid command""" 1550 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1551 output = tools.get_output_filename('output') 1552 with self.assertRaises(ValueError) as exc: 1553 self.run_test(['invalid-cmd'], dtb_file, output) 1554 self.assertIn( 1555 "Unknown command 'invalid-cmd': (use: decl, platdata, struct)", 1556 str(exc.exception)) 1557 1558 def test_output_conflict(self): 1559 """Test a conflict between and output dirs and output file""" 1560 with self.assertRaises(ValueError) as exc: 1561 dtb_platdata.run_steps( 1562 ['all'], None, False, 'out', ['cdir'], None, False, 1563 warning_disabled=True, scan=copy_scan()) 1564 self.assertIn("Must specify either output or output_dirs, not both", 1565 str(exc.exception)) 1566 1567 def check_output_dirs(self, instantiate): 1568 # Remove the directory so that files from other tests are not there 1569 tools._remove_output_dir() 1570 tools.prepare_output_dir(None) 1571 1572 # This should create the .dts and .dtb in the output directory 1573 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1574 outdir = tools.get_output_dir() 1575 fnames = glob.glob(outdir + '/*') 1576 self.assertEqual(2, len(fnames)) 1577 1578 dtb_platdata.run_steps( 1579 ['all'], dtb_file, False, None, [outdir], None, instantiate, 1580 warning_disabled=True, scan=copy_scan()) 1581 fnames = glob.glob(outdir + '/*') 1582 return fnames 1583 1584 def test_output_dirs(self): 1585 """Test outputting files to a directory""" 1586 fnames = self.check_output_dirs(False) 1587 self.assertEqual(5, len(fnames)) 1588 1589 leafs = set(os.path.basename(fname) for fname in fnames) 1590 self.assertEqual( 1591 {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb', 1592 'dt-decl.h'}, 1593 leafs) 1594 1595 def test_output_dirs_inst(self): 1596 """Test outputting files to a directory with instantiation""" 1597 fnames = self.check_output_dirs(True) 1598 self.assertEqual(6, len(fnames)) 1599 1600 leafs = set(os.path.basename(fname) for fname in fnames) 1601 self.assertEqual( 1602 {'dt-structs-gen.h', 'source.dts', 'source.dtb', 1603 'dt-uclass.c', 'dt-decl.h', 'dt-device.c'}, 1604 leafs) 1605 1606 def setup_process_test(self): 1607 """Set up a test of process_nodes() 1608 1609 This uses saved_scan but returns a deep copy of it, so it is safe to 1610 modify it in these tests 1611 1612 Returns: 1613 tuple: 1614 DtbPlatdata: object to test 1615 Scanner: scanner to use 1616 """ 1617 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1618 output = tools.get_output_filename('output') 1619 1620 # Take a copy before messing with it 1621 scan = copy_scan() 1622 plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) 1623 plat.scan_dtb() 1624 plat.scan_tree(False) 1625 plat.prepare_nodes() 1626 return plat, scan 1627 1628 def test_process_nodes(self): 1629 """Test processing nodes to add various info""" 1630 plat, scan = self.setup_process_test() 1631 plat.process_nodes(True) 1632 1633 i2c_node = plat._fdt.GetNode('/i2c@0') 1634 pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') 1635 pmic = scan._drivers['sandbox_pmic'] 1636 i2c = scan._drivers['sandbox_i2c'] 1637 self.assertEqual('DM_DEVICE_REF(pmic_at_9)', pmic_node.dev_ref) 1638 self.assertEqual(pmic, pmic_node.driver) 1639 self.assertEqual(i2c_node, pmic_node.parent) 1640 self.assertEqual(i2c, pmic_node.parent_driver) 1641 1642 # The pmic is the only child 1643 self.assertEqual(pmic_node.parent_seq, 0) 1644 self.assertEqual([pmic_node], i2c_node.child_devs) 1645 1646 # Start and end of the list should be the child_head 1647 ref = '&DM_DEVICE_REF(i2c_at_0)->child_head' 1648 self.assertEqual( 1649 {-1: ref, 0: '&DM_DEVICE_REF(pmic_at_9)->sibling_node', 1: ref}, 1650 i2c_node.child_refs) 1651 1652 def test_process_nodes_bad_parent(self): 1653 # Pretend that i2c has a parent (the pmic) and delete that driver 1654 plat, scan = self.setup_process_test() 1655 1656 i2c_node = plat._fdt.GetNode('/i2c@0') 1657 pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') 1658 del scan._drivers['sandbox_pmic'] 1659 i2c_node.parent = pmic_node 1660 1661 # Process twice, the second time to generate an exception 1662 plat.process_nodes(False) 1663 with self.assertRaises(ValueError) as exc: 1664 plat.process_nodes(True) 1665 self.assertIn( 1666 "Cannot parse/find parent driver 'sandbox_pmic' for 'sandbox_i2c", 1667 str(exc.exception)) 1668 1669 def test_process_nodes_bad_node(self): 1670 plat, scan = self.setup_process_test() 1671 1672 # Now remove the pmic driver 1673 del scan._drivers['sandbox_pmic'] 1674 1675 # Process twice, the second time to generate an exception 1676 plat.process_nodes(False) 1677 with self.assertRaises(ValueError) as exc: 1678 plat.process_nodes(True) 1679 self.assertIn("Cannot parse/find driver for 'sandbox_pmic", 1680 str(exc.exception)) 1681 1682 def test_process_nodes_bad_uclass(self): 1683 plat, scan = self.setup_process_test() 1684 1685 self.assertIn('UCLASS_I2C', scan._uclass) 1686 del scan._uclass['UCLASS_I2C'] 1687 with self.assertRaises(ValueError) as exc: 1688 plat.process_nodes(True) 1689 self.assertIn("Cannot parse/find uclass 'UCLASS_I2C' for driver 'sandbox_i2c'", 1690 str(exc.exception)) 1691 1692 def test_process_nodes_used(self): 1693 """Test processing nodes to add various info""" 1694 plat, scan = self.setup_process_test() 1695 plat.process_nodes(True) 1696 1697 pmic = scan._drivers['sandbox_pmic'] 1698 self.assertTrue(pmic.used) 1699 1700 gpio = scan._drivers['sandbox_gpio'] 1701 self.assertFalse(gpio.used) 1702 1703 def test_alias_read(self): 1704 """Test obtaining aliases""" 1705 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1706 output = tools.get_output_filename('output') 1707 plat = self.run_test(['struct'], dtb_file, output) 1708 1709 scan = plat._scan 1710 testfdt_node = plat._fdt.GetNode('/some-bus/test') 1711 test0_node = plat._fdt.GetNode('/some-bus/test0') 1712 self.assertIn('UCLASS_TEST_FDT', scan._uclass) 1713 uc = scan._uclass['UCLASS_TEST_FDT'] 1714 self.assertEqual({1: testfdt_node, 2: test0_node}, 1715 uc.alias_num_to_node) 1716 self.assertEqual({'/some-bus/test': 1, '/some-bus/test0': 2}, 1717 uc.alias_path_to_num) 1718 1719 # Try adding an alias that doesn't exist 1720 self.assertFalse(scan.add_uclass_alias('fred', 3, None)) 1721 1722 # Try adding an alias for a missing node 1723 self.assertIsNone(scan.add_uclass_alias('testfdt', 3, None)) 1724 1725 def test_alias_read_bad(self): 1726 """Test invalid alias property name""" 1727 dtb_file = get_dtb_file('dtoc_test_alias_bad.dts') 1728 output = tools.get_output_filename('output') 1729 with self.assertRaises(ValueError) as exc: 1730 plat = self.run_test(['struct'], dtb_file, output) 1731 self.assertIn("Cannot decode alias 'i2c4-'", str(exc.exception)) 1732 1733 def test_alias_read_bad_path(self): 1734 """Test alias pointing to a non-existent node""" 1735 # This line may produce a warning, so capture it: 1736 # Warning (alias_paths): /aliases:i2c4: aliases property is not a valid 1737 # node (/does/not/exist) 1738 dtb_file = get_dtb_file('dtoc_test_alias_bad_path.dts', True) 1739 1740 output = tools.get_output_filename('output') 1741 with self.assertRaises(ValueError) as exc: 1742 plat = self.run_test(['struct'], dtb_file, output) 1743 self.assertIn("Alias 'i2c4' path '/does/not/exist' not found", 1744 str(exc.exception)) 1745 1746 def test_alias_read_bad_uclass(self): 1747 """Test alias for a uclass that doesn't exist""" 1748 dtb_file = get_dtb_file('dtoc_test_alias_bad_uc.dts') 1749 output = tools.get_output_filename('output') 1750 with test_util.capture_sys_output() as (stdout, _): 1751 plat = self.run_test(['struct'], dtb_file, output) 1752 self.assertEqual("Could not find uclass for alias 'other1'", 1753 stdout.getvalue().strip()) 1754 1755 def test_sequence(self): 1756 """Test assignment of sequence numnbers""" 1757 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1758 output = tools.get_output_filename('output') 1759 plat = self.run_test(['struct'], dtb_file, output) 1760 1761 scan = plat._scan 1762 testfdt = plat._fdt.GetNode('/some-bus/test') 1763 self.assertEqual(1, testfdt.seq) 1764 i2c = plat._fdt.GetNode('/i2c') 1765 1766 # For now this uclass is not compiled in, so no sequence is assigned 1767 self.assertEqual(4, i2c.seq) 1768 spl = plat._fdt.GetNode('/spl-test') 1769 self.assertEqual(0, spl.seq) 1770 1771 def test_process_root(self): 1772 """Test assignment of sequence numnbers""" 1773 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1774 output = tools.get_output_filename('output') 1775 1776 # Take a copy before messing with it 1777 scan = copy_scan() 1778 plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) 1779 plat.scan_dtb() 1780 root = plat._fdt.GetRoot() 1781 1782 plat.scan_tree(False) 1783 self.assertNotIn(root, plat._valid_nodes) 1784 1785 plat.scan_tree(True) 1786 self.assertIn(root, plat._valid_nodes) 1787 self.assertEqual('root_driver', 1788 scan.get_normalized_compat_name(root)[0]) 1789 1790 def test_simple_inst(self): 1791 """Test output from some simple nodes with instantiate enabled""" 1792 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1793 output = tools.get_output_filename('output') 1794 1795 self.run_test(['decl'], dtb_file, output, True) 1796 with open(output) as infile: 1797 data = infile.read() 1798 1799 self._check_strings(self.decl_text_inst, data) 1800 1801 self.run_test(['uclass'], dtb_file, output, True) 1802 with open(output) as infile: 1803 data = infile.read() 1804 1805 self._check_strings(UCLASS_HEADER_COMMON + self.uclass_text_inst, data) 1806 1807 self.run_test(['device'], dtb_file, output, True) 1808 with open(output) as infile: 1809 data = infile.read() 1810 1811 self._check_strings(self.device_text_inst, data) 1812 1813 def test_inst_no_hdr(self): 1814 """Test dealing with a struct tsssshat has no header""" 1815 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1816 output = tools.get_output_filename('output') 1817 1818 # Run it once to set everything up 1819 plat = self.run_test(['decl'], dtb_file, output, True) 1820 scan = plat._scan 1821 1822 # Restart the output file and delete any record of the uclass' struct 1823 plat.setup_output(Ftype.SOURCE, output) 1824 del scan._structs['dm_test_uc_priv'] 1825 1826 # Now generate the uclasses, which should provide a warning 1827 with test_util.capture_sys_output() as (stdout, _): 1828 plat.generate_uclasses() 1829 self.assertEqual( 1830 'Warning: Cannot find header file for struct dm_test_uc_priv', 1831 stdout.getvalue().strip()) 1832 1833 def test_missing_props(self): 1834 """Test detection of a parent node with no properties""" 1835 dtb_file = get_dtb_file('dtoc_test_noprops.dts', capture_stderr=True) 1836 output = tools.get_output_filename('output') 1837 with self.assertRaises(ValueError) as exc: 1838 self.run_test(['struct'], dtb_file, output) 1839 self.assertIn("Parent node '/i2c@0' has no properties - do you need", 1840 str(exc.exception)) 1841 1842 def test_single_reg(self): 1843 """Test detection of a parent node with no properties""" 1844 dtb_file = get_dtb_file('dtoc_test_single_reg.dts') 1845 output = tools.get_output_filename('output') 1846 self.run_test(['struct'], dtb_file, output) 1847 1848 def test_missing_parent(self): 1849 """Test detection of a parent node with no properties""" 1850 dtb_file = get_dtb_file('dtoc_test_noparent.dts', capture_stderr=True) 1851 output = tools.get_output_filename('output') 1852 with self.assertRaises(ValueError) as exc: 1853 self.run_test(['device'], dtb_file, output, instantiate=True) 1854 self.assertIn("Node '/i2c@0/spl-test/pmic@9' requires parent node " 1855 "'/i2c@0/spl-test' but it is not in the valid list", 1856 str(exc.exception)) 1857