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 terminal 30from u_boot_pylib import test_util 31from u_boot_pylib import tools 32 33DTOC_DIR = pathlib.Path(__file__).parent 34TEST_DATA_DIR = DTOC_DIR / 'test/' 35 36 37HEADER = '''/* 38 * DO NOT MODIFY 39 * 40 * Defines the structs used to hold devicetree data. 41 * This was generated by dtoc from a .dtb (device tree binary) file. 42 */ 43 44#include <stdbool.h> 45#include <linux/libfdt.h>''' 46 47DECL_HEADER = '''/* 48 * DO NOT MODIFY 49 * 50 * Declares externs for all device/uclass instances. 51 * This was generated by dtoc from a .dtb (device tree binary) file. 52 */ 53''' 54 55C_HEADER_PRE = '''/* 56 * DO NOT MODIFY 57 * 58 * Declares the U_BOOT_DRIVER() records and platform data. 59 * This was generated by dtoc from a .dtb (device tree binary) file. 60 */ 61''' 62 63C_HEADER = C_HEADER_PRE + ''' 64/* Allow use of U_BOOT_DRVINFO() in this file */ 65#define DT_PLAT_C 66 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 <dm.h> 421#include <dt-structs.h> 422 423/* 424 * uclass declarations, ordered by 'struct uclass' linker_list idx: 425 * 0: i2c 426 * 1: misc 427 * 2: root 428 * 3: testbus 429 * 4: testfdt 430 * 431 * Sequence numbers allocated in each uclass: 432 * i2c: UCLASS_I2C 433 * 4: /i2c 434 * misc: UCLASS_MISC 435 * 0: /spl-test 436 * 1: /spl-test3 437 * root: UCLASS_ROOT 438 * 0: / 439 * testbus: UCLASS_TEST_BUS 440 * 2: /some-bus 441 * testfdt: UCLASS_TEST_FDT 442 * 1: /some-bus/test 443 * 2: /some-bus/test0 444 */ 445 446struct list_head uclass_head = { 447 .prev = &DM_UCLASS_REF(testfdt)->sibling_node, 448 .next = &DM_UCLASS_REF(i2c)->sibling_node, 449}; 450 451DM_UCLASS_INST(i2c) = { 452 .uc_drv = DM_UCLASS_DRIVER_REF(i2c), 453 .sibling_node = { 454 .prev = &uclass_head, 455 .next = &DM_UCLASS_REF(misc)->sibling_node, 456 }, 457 .dev_head = { 458 .prev = &DM_DEVICE_REF(i2c)->uclass_node, 459 .next = &DM_DEVICE_REF(i2c)->uclass_node, 460 }, 461}; 462 463DM_UCLASS_INST(misc) = { 464 .uc_drv = DM_UCLASS_DRIVER_REF(misc), 465 .sibling_node = { 466 .prev = &DM_UCLASS_REF(i2c)->sibling_node, 467 .next = &DM_UCLASS_REF(root)->sibling_node, 468 }, 469 .dev_head = { 470 .prev = &DM_DEVICE_REF(spl_test3)->uclass_node, 471 .next = &DM_DEVICE_REF(spl_test)->uclass_node, 472 }, 473}; 474 475DM_UCLASS_INST(root) = { 476 .uc_drv = DM_UCLASS_DRIVER_REF(root), 477 .sibling_node = { 478 .prev = &DM_UCLASS_REF(misc)->sibling_node, 479 .next = &DM_UCLASS_REF(testbus)->sibling_node, 480 }, 481 .dev_head = { 482 .prev = &DM_DEVICE_REF(root)->uclass_node, 483 .next = &DM_DEVICE_REF(root)->uclass_node, 484 }, 485}; 486 487DM_UCLASS_INST(testbus) = { 488 .uc_drv = DM_UCLASS_DRIVER_REF(testbus), 489 .sibling_node = { 490 .prev = &DM_UCLASS_REF(root)->sibling_node, 491 .next = &DM_UCLASS_REF(testfdt)->sibling_node, 492 }, 493 .dev_head = { 494 .prev = &DM_DEVICE_REF(some_bus)->uclass_node, 495 .next = &DM_DEVICE_REF(some_bus)->uclass_node, 496 }, 497}; 498 499#include <dm/test.h> 500u8 _testfdt_priv_[sizeof(struct dm_test_uc_priv)] 501 __attribute__ ((section (".priv_data"))); 502DM_UCLASS_INST(testfdt) = { 503 .priv_ = _testfdt_priv_, 504 .uc_drv = DM_UCLASS_DRIVER_REF(testfdt), 505 .sibling_node = { 506 .prev = &DM_UCLASS_REF(testbus)->sibling_node, 507 .next = &uclass_head, 508 }, 509 .dev_head = { 510 .prev = &DM_DEVICE_REF(test0)->uclass_node, 511 .next = &DM_DEVICE_REF(test)->uclass_node, 512 }, 513}; 514 515''' 516 device_text_inst = '''/* 517 * DO NOT MODIFY 518 * 519 * Declares the DM_DEVICE_INST() records. 520 * This was generated by dtoc from a .dtb (device tree binary) file. 521 */ 522 523#include <dm.h> 524#include <dt-structs.h> 525 526/* 527 * udevice declarations, ordered by 'struct udevice' linker_list position: 528 * 529 * idx udevice driver 530 * --- -------------------- -------------------- 531 * 0: i2c sandbox_i2c 532 * 1: root root_driver 533 * 2: some_bus denx_u_boot_test_bus 534 * 3: spl_test sandbox_spl_test 535 * 4: spl_test3 sandbox_spl_test 536 * 5: test denx_u_boot_fdt_test 537 * 6: test0 denx_u_boot_fdt_test 538 * --- -------------------- -------------------- 539 */ 540 541/* 542 * Node /i2c index 0 543 * driver sandbox_i2c parent root_driver 544*/ 545static struct dtd_sandbox_i2c dtv_i2c = { 546\t.intval\t\t\t= 0x3, 547}; 548 549#include <asm/i2c.h> 550u8 _sandbox_i2c_priv_i2c[sizeof(struct sandbox_i2c_priv)] 551\t__attribute__ ((section (".priv_data"))); 552#include <i2c.h> 553u8 _sandbox_i2c_uc_priv_i2c[sizeof(struct dm_i2c_bus)] 554\t__attribute__ ((section (".priv_data"))); 555 556DM_DEVICE_INST(i2c) = { 557\t.driver\t\t= DM_DRIVER_REF(sandbox_i2c), 558\t.name\t\t= "sandbox_i2c", 559\t.plat_\t\t= &dtv_i2c, 560\t.priv_\t\t= _sandbox_i2c_priv_i2c, 561\t.uclass\t\t= DM_UCLASS_REF(i2c), 562\t.uclass_priv_ = _sandbox_i2c_uc_priv_i2c, 563\t.uclass_node\t= { 564\t\t.prev = &DM_UCLASS_REF(i2c)->dev_head, 565\t\t.next = &DM_UCLASS_REF(i2c)->dev_head, 566\t}, 567\t.child_head\t= { 568\t\t.prev = &DM_DEVICE_REF(i2c)->child_head, 569\t\t.next = &DM_DEVICE_REF(i2c)->child_head, 570\t}, 571\t.sibling_node\t= { 572\t\t.prev = &DM_DEVICE_REF(root)->child_head, 573\t\t.next = &DM_DEVICE_REF(some_bus)->sibling_node, 574\t}, 575\t.seq_ = 4, 576}; 577 578/* 579 * Node / index 1 580 * driver root_driver parent None 581*/ 582static struct dtd_root_driver dtv_root = { 583}; 584 585DM_DEVICE_INST(root) = { 586\t.driver\t\t= DM_DRIVER_REF(root_driver), 587\t.name\t\t= "root_driver", 588\t.plat_\t\t= &dtv_root, 589\t.uclass\t\t= DM_UCLASS_REF(root), 590\t.uclass_node\t= { 591\t\t.prev = &DM_UCLASS_REF(root)->dev_head, 592\t\t.next = &DM_UCLASS_REF(root)->dev_head, 593\t}, 594\t.child_head\t= { 595\t\t.prev = &DM_DEVICE_REF(spl_test3)->sibling_node, 596\t\t.next = &DM_DEVICE_REF(i2c)->sibling_node, 597\t}, 598\t.seq_ = 0, 599}; 600 601/* 602 * Node /some-bus index 2 603 * driver denx_u_boot_test_bus parent root_driver 604*/ 605 606#include <dm/test.h> 607struct dm_test_pdata __attribute__ ((section (".priv_data"))) 608\t_denx_u_boot_test_bus_plat_some_bus = { 609\t.dtplat = { 610\t\t.ping_add\t\t= 0x4, 611\t\t.ping_expect\t\t= 0x4, 612\t\t.reg\t\t\t= {0x3, 0x1}, 613\t}, 614}; 615#include <dm/test.h> 616u8 _denx_u_boot_test_bus_priv_some_bus[sizeof(struct dm_test_priv)] 617\t__attribute__ ((section (".priv_data"))); 618#include <dm/test.h> 619u8 _denx_u_boot_test_bus_ucplat_some_bus[sizeof(struct dm_test_uclass_plat)] 620\t__attribute__ ((section (".priv_data"))); 621#include <dm/test.h> 622u8 _denx_u_boot_test_bus_uc_priv_some_bus[sizeof(struct dm_test_uclass_priv)] 623 __attribute__ ((section (".priv_data"))); 624#include <test.h> 625 626DM_DEVICE_INST(some_bus) = { 627\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_test_bus), 628\t.name\t\t= "denx_u_boot_test_bus", 629\t.plat_\t\t= &_denx_u_boot_test_bus_plat_some_bus, 630\t.uclass_plat_\t= _denx_u_boot_test_bus_ucplat_some_bus, 631\t.driver_data\t= DM_TEST_TYPE_FIRST, 632\t.priv_\t\t= _denx_u_boot_test_bus_priv_some_bus, 633\t.uclass\t\t= DM_UCLASS_REF(testbus), 634\t.uclass_priv_ = _denx_u_boot_test_bus_uc_priv_some_bus, 635\t.uclass_node\t= { 636\t\t.prev = &DM_UCLASS_REF(testbus)->dev_head, 637\t\t.next = &DM_UCLASS_REF(testbus)->dev_head, 638\t}, 639\t.child_head\t= { 640\t\t.prev = &DM_DEVICE_REF(test0)->sibling_node, 641\t\t.next = &DM_DEVICE_REF(test)->sibling_node, 642\t}, 643\t.sibling_node\t= { 644\t\t.prev = &DM_DEVICE_REF(i2c)->sibling_node, 645\t\t.next = &DM_DEVICE_REF(spl_test)->sibling_node, 646\t}, 647\t.seq_ = 2, 648}; 649 650/* 651 * Node /spl-test index 3 652 * driver sandbox_spl_test parent root_driver 653*/ 654static struct dtd_sandbox_spl_test dtv_spl_test = { 655\t.boolval\t\t= true, 656\t.intval\t\t\t= 0x1, 657}; 658 659DM_DEVICE_INST(spl_test) = { 660\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test), 661\t.name\t\t= "sandbox_spl_test", 662\t.plat_\t\t= &dtv_spl_test, 663\t.uclass\t\t= DM_UCLASS_REF(misc), 664\t.uclass_node\t= { 665\t\t.prev = &DM_UCLASS_REF(misc)->dev_head, 666\t\t.next = &DM_DEVICE_REF(spl_test3)->uclass_node, 667\t}, 668\t.child_head\t= { 669\t\t.prev = &DM_DEVICE_REF(spl_test)->child_head, 670\t\t.next = &DM_DEVICE_REF(spl_test)->child_head, 671\t}, 672\t.sibling_node\t= { 673\t\t.prev = &DM_DEVICE_REF(some_bus)->sibling_node, 674\t\t.next = &DM_DEVICE_REF(spl_test3)->sibling_node, 675\t}, 676\t.seq_ = 0, 677}; 678 679/* 680 * Node /spl-test3 index 4 681 * driver sandbox_spl_test parent root_driver 682*/ 683static struct dtd_sandbox_spl_test dtv_spl_test3 = { 684\t.longbytearray\t\t= {0x90a0b0c, 0xd0e0f10}, 685\t.stringarray\t\t= "one", 686}; 687 688DM_DEVICE_INST(spl_test3) = { 689\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test), 690\t.name\t\t= "sandbox_spl_test", 691\t.plat_\t\t= &dtv_spl_test3, 692\t.uclass\t\t= DM_UCLASS_REF(misc), 693\t.uclass_node\t= { 694\t\t.prev = &DM_DEVICE_REF(spl_test)->uclass_node, 695\t\t.next = &DM_UCLASS_REF(misc)->dev_head, 696\t}, 697\t.child_head\t= { 698\t\t.prev = &DM_DEVICE_REF(spl_test3)->child_head, 699\t\t.next = &DM_DEVICE_REF(spl_test3)->child_head, 700\t}, 701\t.sibling_node\t= { 702\t\t.prev = &DM_DEVICE_REF(spl_test)->sibling_node, 703\t\t.next = &DM_DEVICE_REF(root)->child_head, 704\t}, 705\t.seq_ = 1, 706}; 707 708/* 709 * Node /some-bus/test index 5 710 * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus 711*/ 712 713#include <dm/test.h> 714struct dm_test_pdata __attribute__ ((section (".priv_data"))) 715\t_denx_u_boot_fdt_test_plat_test = { 716\t.dtplat = { 717\t\t.ping_add\t\t= 0x5, 718\t\t.ping_expect\t\t= 0x5, 719\t\t.reg\t\t\t= {0x5}, 720\t}, 721}; 722#include <dm/test.h> 723u8 _denx_u_boot_fdt_test_priv_test[sizeof(struct dm_test_priv)] 724\t__attribute__ ((section (".priv_data"))); 725#include <dm/test.h> 726u8 _denx_u_boot_fdt_test_parent_plat_test[sizeof(struct dm_test_parent_plat)] 727\t__attribute__ ((section (".priv_data"))); 728#include <dm/test.h> 729u8 _denx_u_boot_fdt_test_parent_priv_test[sizeof(struct dm_test_parent_data)] 730\t__attribute__ ((section (".priv_data"))); 731 732DM_DEVICE_INST(test) = { 733\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test), 734\t.name\t\t= "denx_u_boot_fdt_test", 735\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test, 736\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test, 737\t.driver_data\t= DM_TEST_TYPE_FIRST, 738\t.parent\t\t= DM_DEVICE_REF(some_bus), 739\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test, 740\t.uclass\t\t= DM_UCLASS_REF(testfdt), 741\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test, 742\t.uclass_node\t= { 743\t\t.prev = &DM_UCLASS_REF(testfdt)->dev_head, 744\t\t.next = &DM_DEVICE_REF(test0)->uclass_node, 745\t}, 746\t.child_head\t= { 747\t\t.prev = &DM_DEVICE_REF(test)->child_head, 748\t\t.next = &DM_DEVICE_REF(test)->child_head, 749\t}, 750\t.sibling_node\t= { 751\t\t.prev = &DM_DEVICE_REF(some_bus)->child_head, 752\t\t.next = &DM_DEVICE_REF(test0)->sibling_node, 753\t}, 754\t.seq_ = 1, 755}; 756 757/* 758 * Node /some-bus/test0 index 6 759 * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus 760*/ 761 762#include <dm/test.h> 763struct dm_test_pdata __attribute__ ((section (".priv_data"))) 764\t_denx_u_boot_fdt_test_plat_test0 = { 765\t.dtplat = { 766\t}, 767}; 768#include <dm/test.h> 769u8 _denx_u_boot_fdt_test_priv_test0[sizeof(struct dm_test_priv)] 770\t__attribute__ ((section (".priv_data"))); 771#include <dm/test.h> 772u8 _denx_u_boot_fdt_test_parent_plat_test0[sizeof(struct dm_test_parent_plat)] 773\t__attribute__ ((section (".priv_data"))); 774#include <dm/test.h> 775u8 _denx_u_boot_fdt_test_parent_priv_test0[sizeof(struct dm_test_parent_data)] 776\t__attribute__ ((section (".priv_data"))); 777 778DM_DEVICE_INST(test0) = { 779\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test), 780\t.name\t\t= "denx_u_boot_fdt_test", 781\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test0, 782\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test0, 783\t.driver_data\t= DM_TEST_TYPE_SECOND, 784\t.parent\t\t= DM_DEVICE_REF(some_bus), 785\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test0, 786\t.uclass\t\t= DM_UCLASS_REF(testfdt), 787\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test0, 788\t.uclass_node\t= { 789\t\t.prev = &DM_DEVICE_REF(test)->uclass_node, 790\t\t.next = &DM_UCLASS_REF(testfdt)->dev_head, 791\t}, 792\t.child_head\t= { 793\t\t.prev = &DM_DEVICE_REF(test0)->child_head, 794\t\t.next = &DM_DEVICE_REF(test0)->child_head, 795\t}, 796\t.sibling_node\t= { 797\t\t.prev = &DM_DEVICE_REF(test)->sibling_node, 798\t\t.next = &DM_DEVICE_REF(some_bus)->child_head, 799\t}, 800\t.seq_ = 2, 801}; 802 803''' 804 805 def test_simple(self): 806 """Test output from some simple nodes with various types of data""" 807 dtb_file = get_dtb_file('dtoc_test_simple.dts') 808 output = tools.get_output_filename('output') 809 self.run_test(['struct'], dtb_file, output) 810 with open(output) as infile: 811 data = infile.read() 812 813 self._check_strings(self.struct_text, data) 814 815 self.run_test(['platdata'], dtb_file, output) 816 with open(output) as infile: 817 data = infile.read() 818 819 self._check_strings(self.platdata_text, data) 820 821 self.run_test(['decl'], dtb_file, output) 822 with open(output) as infile: 823 data = infile.read() 824 825 self._check_strings(self.decl_text, data) 826 827 # Try the 'all' command 828 self.run_test(['all'], dtb_file, output) 829 data = tools.read_file(output, binary=False) 830 self._check_strings( 831 self.decl_text + self.platdata_text + self.struct_text, data) 832 833 def test_driver_alias(self): 834 """Test output from a device tree file with a driver alias""" 835 dtb_file = get_dtb_file('dtoc_test_driver_alias.dts') 836 output = tools.get_output_filename('output') 837 self.run_test(['struct'], dtb_file, output) 838 with open(output) as infile: 839 data = infile.read() 840 self._check_strings(HEADER + ''' 841struct dtd_sandbox_gpio { 842\tconst char *\tgpio_bank_name; 843\tbool\t\tgpio_controller; 844\tfdt32_t\t\tsandbox_gpio_count; 845}; 846''', data) 847 848 self.run_test(['platdata'], dtb_file, output) 849 with open(output) as infile: 850 data = infile.read() 851 self._check_strings(C_HEADER + ''' 852/* 853 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 854 * 855 * idx driver_info driver 856 * --- -------------------- -------------------- 857 * 0: gpios_at_0 sandbox_gpio 858 * --- -------------------- -------------------- 859 */ 860 861/* 862 * Node /gpios@0 index 0 863 * driver sandbox_gpio parent None 864 */ 865static struct dtd_sandbox_gpio dtv_gpios_at_0 = { 866\t.gpio_bank_name\t\t= "a", 867\t.gpio_controller\t= true, 868\t.sandbox_gpio_count\t= 0x14, 869}; 870U_BOOT_DRVINFO(gpios_at_0) = { 871\t.name\t\t= "sandbox_gpio", 872\t.plat\t\t= &dtv_gpios_at_0, 873\t.plat_size\t= sizeof(dtv_gpios_at_0), 874\t.parent_idx\t= -1, 875}; 876 877''', data) 878 879 def test_invalid_driver(self): 880 """Test output from a device tree file with an invalid driver""" 881 dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts') 882 output = tools.get_output_filename('output') 883 with terminal.capture() as _: 884 dtb_platdata.run_steps( 885 ['struct'], dtb_file, False, output, [], None, False, 886 scan=copy_scan()) 887 with open(output) as infile: 888 data = infile.read() 889 self._check_strings(HEADER + ''' 890struct dtd_invalid { 891}; 892''', data) 893 894 with terminal.capture() as _: 895 dtb_platdata.run_steps( 896 ['platdata'], dtb_file, False, output, [], None, False, 897 scan=copy_scan()) 898 with open(output) as infile: 899 data = infile.read() 900 self._check_strings(C_HEADER + ''' 901/* 902 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 903 * 904 * idx driver_info driver 905 * --- -------------------- -------------------- 906 * 0: spl_test invalid 907 * --- -------------------- -------------------- 908 */ 909 910/* Node /spl-test index 0 */ 911static struct dtd_invalid dtv_spl_test = { 912}; 913U_BOOT_DRVINFO(spl_test) = { 914\t.name\t\t= "invalid", 915\t.plat\t\t= &dtv_spl_test, 916\t.plat_size\t= sizeof(dtv_spl_test), 917\t.parent_idx\t= -1, 918}; 919 920''', data) 921 922 def test_phandle(self): 923 """Test output from a node containing a phandle reference""" 924 dtb_file = get_dtb_file('dtoc_test_phandle.dts') 925 output = tools.get_output_filename('output') 926 self.run_test(['struct'], dtb_file, output) 927 with open(output) as infile: 928 data = infile.read() 929 self._check_strings(HEADER + ''' 930struct dtd_source { 931\tstruct phandle_2_arg clocks[4]; 932\tunsigned char phandle_name_offset[13]; 933}; 934struct dtd_target { 935\tfdt32_t\t\tintval; 936}; 937''', data) 938 939 self.run_test(['platdata'], dtb_file, output) 940 with open(output) as infile: 941 data = infile.read() 942 self._check_strings(C_HEADER + ''' 943/* 944 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 945 * 946 * idx driver_info driver 947 * --- -------------------- -------------------- 948 * 0: phandle2_target target 949 * 1: phandle3_target target 950 * 2: phandle_source source 951 * 3: phandle_source2 source 952 * 4: phandle_target target 953 * --- -------------------- -------------------- 954 */ 955 956/* Node /phandle2-target index 0 */ 957static struct dtd_target dtv_phandle2_target = { 958\t.intval\t\t\t= 0x1, 959}; 960U_BOOT_DRVINFO(phandle2_target) = { 961\t.name\t\t= "target", 962\t.plat\t\t= &dtv_phandle2_target, 963\t.plat_size\t= sizeof(dtv_phandle2_target), 964\t.parent_idx\t= -1, 965}; 966 967/* Node /phandle3-target index 1 */ 968static struct dtd_target dtv_phandle3_target = { 969\t.intval\t\t\t= 0x2, 970}; 971U_BOOT_DRVINFO(phandle3_target) = { 972\t.name\t\t= "target", 973\t.plat\t\t= &dtv_phandle3_target, 974\t.plat_size\t= sizeof(dtv_phandle3_target), 975\t.parent_idx\t= -1, 976}; 977 978/* Node /phandle-source index 2 */ 979static struct dtd_source dtv_phandle_source = { 980\t.clocks\t\t\t= { 981\t\t\t{4, {}}, 982\t\t\t{0, {11}}, 983\t\t\t{1, {12, 13}}, 984\t\t\t{4, {}},}, 985\t.phandle_name_offset = {0x0, 0x0, 0x0, 0x3, 0x66, 0x72, 0x65, 0x64, 986\t\t0x0, 0x0, 0x0, 0x0, 0x7b}, 987}; 988U_BOOT_DRVINFO(phandle_source) = { 989\t.name\t\t= "source", 990\t.plat\t\t= &dtv_phandle_source, 991\t.plat_size\t= sizeof(dtv_phandle_source), 992\t.parent_idx\t= -1, 993}; 994 995/* Node /phandle-source2 index 3 */ 996static struct dtd_source dtv_phandle_source2 = { 997\t.clocks\t\t\t= { 998\t\t\t{4, {}},}, 999}; 1000U_BOOT_DRVINFO(phandle_source2) = { 1001\t.name\t\t= "source", 1002\t.plat\t\t= &dtv_phandle_source2, 1003\t.plat_size\t= sizeof(dtv_phandle_source2), 1004\t.parent_idx\t= -1, 1005}; 1006 1007/* Node /phandle-target index 4 */ 1008static struct dtd_target dtv_phandle_target = { 1009\t.intval\t\t\t= 0x0, 1010}; 1011U_BOOT_DRVINFO(phandle_target) = { 1012\t.name\t\t= "target", 1013\t.plat\t\t= &dtv_phandle_target, 1014\t.plat_size\t= sizeof(dtv_phandle_target), 1015\t.parent_idx\t= -1, 1016}; 1017 1018''', data) 1019 1020 def test_phandle_single(self): 1021 """Test output from a node containing a phandle reference""" 1022 dtb_file = get_dtb_file('dtoc_test_phandle_single.dts') 1023 output = tools.get_output_filename('output') 1024 self.run_test(['struct'], dtb_file, output) 1025 with open(output) as infile: 1026 data = infile.read() 1027 self._check_strings(HEADER + ''' 1028struct dtd_source { 1029\tstruct phandle_0_arg clocks[1]; 1030}; 1031struct dtd_target { 1032\tfdt32_t\t\tintval; 1033}; 1034''', data) 1035 1036 def test_phandle_reorder(self): 1037 """Test that phandle targets are generated before their references""" 1038 dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts') 1039 output = tools.get_output_filename('output') 1040 self.run_test(['platdata'], dtb_file, output) 1041 with open(output) as infile: 1042 data = infile.read() 1043 self._check_strings(C_HEADER + ''' 1044/* 1045 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1046 * 1047 * idx driver_info driver 1048 * --- -------------------- -------------------- 1049 * 0: phandle_source2 source 1050 * 1: phandle_target target 1051 * --- -------------------- -------------------- 1052 */ 1053 1054/* Node /phandle-source2 index 0 */ 1055static struct dtd_source dtv_phandle_source2 = { 1056\t.clocks\t\t\t= { 1057\t\t\t{1, {}},}, 1058}; 1059U_BOOT_DRVINFO(phandle_source2) = { 1060\t.name\t\t= "source", 1061\t.plat\t\t= &dtv_phandle_source2, 1062\t.plat_size\t= sizeof(dtv_phandle_source2), 1063\t.parent_idx\t= -1, 1064}; 1065 1066/* Node /phandle-target index 1 */ 1067static struct dtd_target dtv_phandle_target = { 1068}; 1069U_BOOT_DRVINFO(phandle_target) = { 1070\t.name\t\t= "target", 1071\t.plat\t\t= &dtv_phandle_target, 1072\t.plat_size\t= sizeof(dtv_phandle_target), 1073\t.parent_idx\t= -1, 1074}; 1075 1076''', data) 1077 1078 def test_phandle_cd_gpio(self): 1079 """Test that phandle targets are generated when unsing cd-gpios""" 1080 dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts') 1081 output = tools.get_output_filename('output') 1082 dtb_platdata.run_steps( 1083 ['platdata'], dtb_file, False, output, [], None, False, 1084 warning_disabled=True, scan=copy_scan()) 1085 with open(output) as infile: 1086 data = infile.read() 1087 self._check_strings(C_HEADER + ''' 1088/* 1089 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1090 * 1091 * idx driver_info driver 1092 * --- -------------------- -------------------- 1093 * 0: phandle2_target target 1094 * 1: phandle3_target target 1095 * 2: phandle_source source 1096 * 3: phandle_source2 source 1097 * 4: phandle_target target 1098 * --- -------------------- -------------------- 1099 */ 1100 1101/* Node /phandle2-target index 0 */ 1102static struct dtd_target dtv_phandle2_target = { 1103\t.intval\t\t\t= 0x1, 1104}; 1105U_BOOT_DRVINFO(phandle2_target) = { 1106\t.name\t\t= "target", 1107\t.plat\t\t= &dtv_phandle2_target, 1108\t.plat_size\t= sizeof(dtv_phandle2_target), 1109\t.parent_idx\t= -1, 1110}; 1111 1112/* Node /phandle3-target index 1 */ 1113static struct dtd_target dtv_phandle3_target = { 1114\t.intval\t\t\t= 0x2, 1115}; 1116U_BOOT_DRVINFO(phandle3_target) = { 1117\t.name\t\t= "target", 1118\t.plat\t\t= &dtv_phandle3_target, 1119\t.plat_size\t= sizeof(dtv_phandle3_target), 1120\t.parent_idx\t= -1, 1121}; 1122 1123/* Node /phandle-source index 2 */ 1124static struct dtd_source dtv_phandle_source = { 1125\t.cd_gpios\t\t= { 1126\t\t\t{4, {}}, 1127\t\t\t{0, {11}}, 1128\t\t\t{1, {12, 13}}, 1129\t\t\t{4, {}},}, 1130}; 1131U_BOOT_DRVINFO(phandle_source) = { 1132\t.name\t\t= "source", 1133\t.plat\t\t= &dtv_phandle_source, 1134\t.plat_size\t= sizeof(dtv_phandle_source), 1135\t.parent_idx\t= -1, 1136}; 1137 1138/* Node /phandle-source2 index 3 */ 1139static struct dtd_source dtv_phandle_source2 = { 1140\t.cd_gpios\t\t= { 1141\t\t\t{4, {}},}, 1142}; 1143U_BOOT_DRVINFO(phandle_source2) = { 1144\t.name\t\t= "source", 1145\t.plat\t\t= &dtv_phandle_source2, 1146\t.plat_size\t= sizeof(dtv_phandle_source2), 1147\t.parent_idx\t= -1, 1148}; 1149 1150/* Node /phandle-target index 4 */ 1151static struct dtd_target dtv_phandle_target = { 1152\t.intval\t\t\t= 0x0, 1153}; 1154U_BOOT_DRVINFO(phandle_target) = { 1155\t.name\t\t= "target", 1156\t.plat\t\t= &dtv_phandle_target, 1157\t.plat_size\t= sizeof(dtv_phandle_target), 1158\t.parent_idx\t= -1, 1159}; 1160 1161''', data) 1162 1163 def test_phandle_bad(self): 1164 """Test a node containing an invalid phandle fails""" 1165 dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts', 1166 capture_stderr=True) 1167 output = tools.get_output_filename('output') 1168 with self.assertRaises(ValueError) as exc: 1169 self.run_test(['struct'], dtb_file, output) 1170 self.assertIn("Cannot parse 'clocks' in node 'phandle-source'", 1171 str(exc.exception)) 1172 1173 def test_phandle_bad2(self): 1174 """Test a phandle target missing its #*-cells property""" 1175 dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts', 1176 capture_stderr=True) 1177 output = tools.get_output_filename('output') 1178 with self.assertRaises(ValueError) as exc: 1179 self.run_test(['struct'], dtb_file, output) 1180 self.assertIn("Node 'phandle-target' has no cells property", 1181 str(exc.exception)) 1182 1183 def test_addresses64(self): 1184 """Test output from a node with a 'reg' property with na=2, ns=2""" 1185 dtb_file = get_dtb_file('dtoc_test_addr64.dts') 1186 output = tools.get_output_filename('output') 1187 self.run_test(['struct'], dtb_file, output) 1188 with open(output) as infile: 1189 data = infile.read() 1190 self._check_strings(HEADER + ''' 1191struct dtd_test1 { 1192\tfdt64_t\t\treg[2]; 1193}; 1194struct dtd_test2 { 1195\tfdt64_t\t\treg[2]; 1196}; 1197struct dtd_test3 { 1198\tfdt64_t\t\treg[4]; 1199}; 1200''', data) 1201 1202 self.run_test(['platdata'], dtb_file, output) 1203 with open(output) as infile: 1204 data = infile.read() 1205 self._check_strings(C_HEADER + ''' 1206/* 1207 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1208 * 1209 * idx driver_info driver 1210 * --- -------------------- -------------------- 1211 * 0: test1 test1 1212 * 1: test2 test2 1213 * 2: test3 test3 1214 * --- -------------------- -------------------- 1215 */ 1216 1217/* Node /test1 index 0 */ 1218static struct dtd_test1 dtv_test1 = { 1219\t.reg\t\t\t= {0x1234, 0x5678}, 1220}; 1221U_BOOT_DRVINFO(test1) = { 1222\t.name\t\t= "test1", 1223\t.plat\t\t= &dtv_test1, 1224\t.plat_size\t= sizeof(dtv_test1), 1225\t.parent_idx\t= -1, 1226}; 1227 1228/* Node /test2 index 1 */ 1229static struct dtd_test2 dtv_test2 = { 1230\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, 1231}; 1232U_BOOT_DRVINFO(test2) = { 1233\t.name\t\t= "test2", 1234\t.plat\t\t= &dtv_test2, 1235\t.plat_size\t= sizeof(dtv_test2), 1236\t.parent_idx\t= -1, 1237}; 1238 1239/* Node /test3 index 2 */ 1240static struct dtd_test3 dtv_test3 = { 1241\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, 1242}; 1243U_BOOT_DRVINFO(test3) = { 1244\t.name\t\t= "test3", 1245\t.plat\t\t= &dtv_test3, 1246\t.plat_size\t= sizeof(dtv_test3), 1247\t.parent_idx\t= -1, 1248}; 1249 1250''', data) 1251 1252 def test_addresses32(self): 1253 """Test output from a node with a 'reg' property with na=1, ns=1""" 1254 dtb_file = get_dtb_file('dtoc_test_addr32.dts') 1255 output = tools.get_output_filename('output') 1256 self.run_test(['struct'], dtb_file, output) 1257 with open(output) as infile: 1258 data = infile.read() 1259 self._check_strings(HEADER + ''' 1260struct dtd_test1 { 1261\tfdt32_t\t\treg[2]; 1262}; 1263struct dtd_test2 { 1264\tfdt32_t\t\treg[4]; 1265}; 1266''', data) 1267 1268 self.run_test(['platdata'], dtb_file, output) 1269 with open(output) as infile: 1270 data = infile.read() 1271 self._check_strings(C_HEADER + ''' 1272/* 1273 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1274 * 1275 * idx driver_info driver 1276 * --- -------------------- -------------------- 1277 * 0: test1 test1 1278 * 1: test2 test2 1279 * --- -------------------- -------------------- 1280 */ 1281 1282/* Node /test1 index 0 */ 1283static struct dtd_test1 dtv_test1 = { 1284\t.reg\t\t\t= {0x1234, 0x5678}, 1285}; 1286U_BOOT_DRVINFO(test1) = { 1287\t.name\t\t= "test1", 1288\t.plat\t\t= &dtv_test1, 1289\t.plat_size\t= sizeof(dtv_test1), 1290\t.parent_idx\t= -1, 1291}; 1292 1293/* Node /test2 index 1 */ 1294static struct dtd_test2 dtv_test2 = { 1295\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, 1296}; 1297U_BOOT_DRVINFO(test2) = { 1298\t.name\t\t= "test2", 1299\t.plat\t\t= &dtv_test2, 1300\t.plat_size\t= sizeof(dtv_test2), 1301\t.parent_idx\t= -1, 1302}; 1303 1304''', data) 1305 1306 def test_addresses64_32(self): 1307 """Test output from a node with a 'reg' property with na=2, ns=1""" 1308 dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') 1309 output = tools.get_output_filename('output') 1310 self.run_test(['struct'], dtb_file, output) 1311 with open(output) as infile: 1312 data = infile.read() 1313 self._check_strings(HEADER + ''' 1314struct dtd_test1 { 1315\tfdt64_t\t\treg[2]; 1316}; 1317struct dtd_test2 { 1318\tfdt64_t\t\treg[2]; 1319}; 1320struct dtd_test3 { 1321\tfdt64_t\t\treg[4]; 1322}; 1323''', data) 1324 1325 self.run_test(['platdata'], dtb_file, output) 1326 with open(output) as infile: 1327 data = infile.read() 1328 self._check_strings(C_HEADER + ''' 1329/* 1330 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1331 * 1332 * idx driver_info driver 1333 * --- -------------------- -------------------- 1334 * 0: test1 test1 1335 * 1: test2 test2 1336 * 2: test3 test3 1337 * --- -------------------- -------------------- 1338 */ 1339 1340/* Node /test1 index 0 */ 1341static struct dtd_test1 dtv_test1 = { 1342\t.reg\t\t\t= {0x123400000000, 0x5678}, 1343}; 1344U_BOOT_DRVINFO(test1) = { 1345\t.name\t\t= "test1", 1346\t.plat\t\t= &dtv_test1, 1347\t.plat_size\t= sizeof(dtv_test1), 1348\t.parent_idx\t= -1, 1349}; 1350 1351/* Node /test2 index 1 */ 1352static struct dtd_test2 dtv_test2 = { 1353\t.reg\t\t\t= {0x1234567890123456, 0x98765432}, 1354}; 1355U_BOOT_DRVINFO(test2) = { 1356\t.name\t\t= "test2", 1357\t.plat\t\t= &dtv_test2, 1358\t.plat_size\t= sizeof(dtv_test2), 1359\t.parent_idx\t= -1, 1360}; 1361 1362/* Node /test3 index 2 */ 1363static struct dtd_test3 dtv_test3 = { 1364\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, 1365}; 1366U_BOOT_DRVINFO(test3) = { 1367\t.name\t\t= "test3", 1368\t.plat\t\t= &dtv_test3, 1369\t.plat_size\t= sizeof(dtv_test3), 1370\t.parent_idx\t= -1, 1371}; 1372 1373''', data) 1374 1375 def test_addresses32_64(self): 1376 """Test output from a node with a 'reg' property with na=1, ns=2""" 1377 dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') 1378 output = tools.get_output_filename('output') 1379 self.run_test(['struct'], dtb_file, output) 1380 with open(output) as infile: 1381 data = infile.read() 1382 self._check_strings(HEADER + ''' 1383struct dtd_test1 { 1384\tfdt64_t\t\treg[2]; 1385}; 1386struct dtd_test2 { 1387\tfdt64_t\t\treg[2]; 1388}; 1389struct dtd_test3 { 1390\tfdt64_t\t\treg[4]; 1391}; 1392''', data) 1393 1394 self.run_test(['platdata'], dtb_file, output) 1395 with open(output) as infile: 1396 data = infile.read() 1397 self._check_strings(C_HEADER + ''' 1398/* 1399 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1400 * 1401 * idx driver_info driver 1402 * --- -------------------- -------------------- 1403 * 0: test1 test1 1404 * 1: test2 test2 1405 * 2: test3 test3 1406 * --- -------------------- -------------------- 1407 */ 1408 1409/* Node /test1 index 0 */ 1410static struct dtd_test1 dtv_test1 = { 1411\t.reg\t\t\t= {0x1234, 0x567800000000}, 1412}; 1413U_BOOT_DRVINFO(test1) = { 1414\t.name\t\t= "test1", 1415\t.plat\t\t= &dtv_test1, 1416\t.plat_size\t= sizeof(dtv_test1), 1417\t.parent_idx\t= -1, 1418}; 1419 1420/* Node /test2 index 1 */ 1421static struct dtd_test2 dtv_test2 = { 1422\t.reg\t\t\t= {0x12345678, 0x9876543210987654}, 1423}; 1424U_BOOT_DRVINFO(test2) = { 1425\t.name\t\t= "test2", 1426\t.plat\t\t= &dtv_test2, 1427\t.plat_size\t= sizeof(dtv_test2), 1428\t.parent_idx\t= -1, 1429}; 1430 1431/* Node /test3 index 2 */ 1432static struct dtd_test3 dtv_test3 = { 1433\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, 1434}; 1435U_BOOT_DRVINFO(test3) = { 1436\t.name\t\t= "test3", 1437\t.plat\t\t= &dtv_test3, 1438\t.plat_size\t= sizeof(dtv_test3), 1439\t.parent_idx\t= -1, 1440}; 1441 1442''', data) 1443 1444 def test_bad_reg(self): 1445 """Test that a reg property with an invalid type generates an error""" 1446 # Capture stderr since dtc will emit warnings for this file 1447 dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True) 1448 output = tools.get_output_filename('output') 1449 with self.assertRaises(ValueError) as exc: 1450 self.run_test(['struct'], dtb_file, output) 1451 self.assertIn("Node 'spl-test' reg property is not an int", 1452 str(exc.exception)) 1453 1454 def test_bad_reg2(self): 1455 """Test that a reg property with an invalid cell count is detected""" 1456 # Capture stderr since dtc will emit warnings for this file 1457 dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True) 1458 output = tools.get_output_filename('output') 1459 with self.assertRaises(ValueError) as exc: 1460 self.run_test(['struct'], dtb_file, output) 1461 self.assertIn( 1462 "Node 'spl-test' (parent '/') reg property has 3 cells which is not a multiple of na + ns = 1 + 1)", 1463 str(exc.exception)) 1464 1465 def test_add_prop(self): 1466 """Test that a subequent node can add a new property to a struct""" 1467 dtb_file = get_dtb_file('dtoc_test_add_prop.dts') 1468 output = tools.get_output_filename('output') 1469 self.run_test(['struct'], dtb_file, output) 1470 with open(output) as infile: 1471 data = infile.read() 1472 self._check_strings(HEADER + ''' 1473struct dtd_sandbox_spl_test { 1474\tfdt32_t\t\tintarray; 1475\tfdt32_t\t\tintval; 1476}; 1477''', data) 1478 1479 self.run_test(['platdata'], dtb_file, output) 1480 with open(output) as infile: 1481 data = infile.read() 1482 self._check_strings(C_HEADER + ''' 1483/* 1484 * driver_info declarations, ordered by 'struct driver_info' linker_list idx: 1485 * 1486 * idx driver_info driver 1487 * --- -------------------- -------------------- 1488 * 0: spl_test sandbox_spl_test 1489 * 1: spl_test2 sandbox_spl_test 1490 * --- -------------------- -------------------- 1491 */ 1492 1493/* 1494 * Node /spl-test index 0 1495 * driver sandbox_spl_test parent None 1496 */ 1497static struct dtd_sandbox_spl_test dtv_spl_test = { 1498\t.intval\t\t\t= 0x1, 1499}; 1500U_BOOT_DRVINFO(spl_test) = { 1501\t.name\t\t= "sandbox_spl_test", 1502\t.plat\t\t= &dtv_spl_test, 1503\t.plat_size\t= sizeof(dtv_spl_test), 1504\t.parent_idx\t= -1, 1505}; 1506 1507/* 1508 * Node /spl-test2 index 1 1509 * driver sandbox_spl_test parent None 1510 */ 1511static struct dtd_sandbox_spl_test dtv_spl_test2 = { 1512\t.intarray\t\t= 0x5, 1513}; 1514U_BOOT_DRVINFO(spl_test2) = { 1515\t.name\t\t= "sandbox_spl_test", 1516\t.plat\t\t= &dtv_spl_test2, 1517\t.plat_size\t= sizeof(dtv_spl_test2), 1518\t.parent_idx\t= -1, 1519}; 1520 1521''', data) 1522 1523 def test_stdout(self): 1524 """Test output to stdout""" 1525 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1526 with terminal.capture() as (stdout, _): 1527 self.run_test(['struct'], dtb_file, None) 1528 self._check_strings(self.struct_text, stdout.getvalue()) 1529 1530 def test_multi_to_file(self): 1531 """Test output of multiple pieces to a single file""" 1532 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1533 output = tools.get_output_filename('output') 1534 self.run_test(['all'], dtb_file, output) 1535 data = tools.read_file(output, binary=False) 1536 self._check_strings( 1537 self.decl_text + self.platdata_text + self.struct_text, data) 1538 1539 def test_no_command(self): 1540 """Test running dtoc without a command""" 1541 with self.assertRaises(ValueError) as exc: 1542 self.run_test([], '', '') 1543 self.assertIn("Please specify a command: struct, platdata", 1544 str(exc.exception)) 1545 1546 def test_bad_command(self): 1547 """Test running dtoc with an invalid command""" 1548 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1549 output = tools.get_output_filename('output') 1550 with self.assertRaises(ValueError) as exc: 1551 self.run_test(['invalid-cmd'], dtb_file, output) 1552 self.assertIn( 1553 "Unknown command 'invalid-cmd': (use: decl, platdata, struct)", 1554 str(exc.exception)) 1555 1556 def test_output_conflict(self): 1557 """Test a conflict between and output dirs and output file""" 1558 with self.assertRaises(ValueError) as exc: 1559 dtb_platdata.run_steps( 1560 ['all'], None, False, 'out', ['cdir'], None, False, 1561 warning_disabled=True, scan=copy_scan()) 1562 self.assertIn("Must specify either output or output_dirs, not both", 1563 str(exc.exception)) 1564 1565 def check_output_dirs(self, instantiate): 1566 # Remove the directory so that files from other tests are not there 1567 tools._remove_output_dir() 1568 tools.prepare_output_dir(None) 1569 1570 # This should create the .dts and .dtb in the output directory 1571 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1572 outdir = tools.get_output_dir() 1573 fnames = glob.glob(outdir + '/*') 1574 self.assertEqual(2, len(fnames)) 1575 1576 dtb_platdata.run_steps( 1577 ['all'], dtb_file, False, None, [outdir], None, instantiate, 1578 warning_disabled=True, scan=copy_scan()) 1579 fnames = glob.glob(outdir + '/*') 1580 return fnames 1581 1582 def test_output_dirs(self): 1583 """Test outputting files to a directory""" 1584 fnames = self.check_output_dirs(False) 1585 self.assertEqual(5, len(fnames)) 1586 1587 leafs = set(os.path.basename(fname) for fname in fnames) 1588 self.assertEqual( 1589 {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb', 1590 'dt-decl.h'}, 1591 leafs) 1592 1593 def test_output_dirs_inst(self): 1594 """Test outputting files to a directory with instantiation""" 1595 fnames = self.check_output_dirs(True) 1596 self.assertEqual(6, len(fnames)) 1597 1598 leafs = set(os.path.basename(fname) for fname in fnames) 1599 self.assertEqual( 1600 {'dt-structs-gen.h', 'source.dts', 'source.dtb', 1601 'dt-uclass.c', 'dt-decl.h', 'dt-device.c'}, 1602 leafs) 1603 1604 def setup_process_test(self): 1605 """Set up a test of process_nodes() 1606 1607 This uses saved_scan but returns a deep copy of it, so it is safe to 1608 modify it in these tests 1609 1610 Returns: 1611 tuple: 1612 DtbPlatdata: object to test 1613 Scanner: scanner to use 1614 """ 1615 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1616 output = tools.get_output_filename('output') 1617 1618 # Take a copy before messing with it 1619 scan = copy_scan() 1620 plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) 1621 plat.scan_dtb() 1622 plat.scan_tree(False) 1623 plat.prepare_nodes() 1624 return plat, scan 1625 1626 def test_process_nodes(self): 1627 """Test processing nodes to add various info""" 1628 plat, scan = self.setup_process_test() 1629 plat.process_nodes(True) 1630 1631 i2c_node = plat._fdt.GetNode('/i2c@0') 1632 pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') 1633 pmic = scan._drivers['sandbox_pmic'] 1634 i2c = scan._drivers['sandbox_i2c'] 1635 self.assertEqual('DM_DEVICE_REF(pmic_at_9)', pmic_node.dev_ref) 1636 self.assertEqual(pmic, pmic_node.driver) 1637 self.assertEqual(i2c_node, pmic_node.parent) 1638 self.assertEqual(i2c, pmic_node.parent_driver) 1639 1640 # The pmic is the only child 1641 self.assertEqual(pmic_node.parent_seq, 0) 1642 self.assertEqual([pmic_node], i2c_node.child_devs) 1643 1644 # Start and end of the list should be the child_head 1645 ref = '&DM_DEVICE_REF(i2c_at_0)->child_head' 1646 self.assertEqual( 1647 {-1: ref, 0: '&DM_DEVICE_REF(pmic_at_9)->sibling_node', 1: ref}, 1648 i2c_node.child_refs) 1649 1650 def test_process_nodes_bad_parent(self): 1651 # Pretend that i2c has a parent (the pmic) and delete that driver 1652 plat, scan = self.setup_process_test() 1653 1654 i2c_node = plat._fdt.GetNode('/i2c@0') 1655 pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') 1656 del scan._drivers['sandbox_pmic'] 1657 i2c_node.parent = pmic_node 1658 1659 # Process twice, the second time to generate an exception 1660 plat.process_nodes(False) 1661 with self.assertRaises(ValueError) as exc: 1662 plat.process_nodes(True) 1663 self.assertIn( 1664 "Cannot parse/find parent driver 'sandbox_pmic' for 'sandbox_i2c", 1665 str(exc.exception)) 1666 1667 def test_process_nodes_bad_node(self): 1668 plat, scan = self.setup_process_test() 1669 1670 # Now remove the pmic driver 1671 del scan._drivers['sandbox_pmic'] 1672 1673 # Process twice, the second time to generate an exception 1674 plat.process_nodes(False) 1675 with self.assertRaises(ValueError) as exc: 1676 plat.process_nodes(True) 1677 self.assertIn("Cannot parse/find driver for 'sandbox_pmic", 1678 str(exc.exception)) 1679 1680 def test_process_nodes_bad_uclass(self): 1681 plat, scan = self.setup_process_test() 1682 1683 self.assertIn('UCLASS_I2C', scan._uclass) 1684 del scan._uclass['UCLASS_I2C'] 1685 with self.assertRaises(ValueError) as exc: 1686 plat.process_nodes(True) 1687 self.assertIn("Cannot parse/find uclass 'UCLASS_I2C' for driver 'sandbox_i2c'", 1688 str(exc.exception)) 1689 1690 def test_process_nodes_used(self): 1691 """Test processing nodes to add various info""" 1692 plat, scan = self.setup_process_test() 1693 plat.process_nodes(True) 1694 1695 pmic = scan._drivers['sandbox_pmic'] 1696 self.assertTrue(pmic.used) 1697 1698 gpio = scan._drivers['sandbox_gpio'] 1699 self.assertFalse(gpio.used) 1700 1701 def test_alias_read(self): 1702 """Test obtaining aliases""" 1703 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1704 output = tools.get_output_filename('output') 1705 plat = self.run_test(['struct'], dtb_file, output) 1706 1707 scan = plat._scan 1708 testfdt_node = plat._fdt.GetNode('/some-bus/test') 1709 test0_node = plat._fdt.GetNode('/some-bus/test0') 1710 self.assertIn('UCLASS_TEST_FDT', scan._uclass) 1711 uc = scan._uclass['UCLASS_TEST_FDT'] 1712 self.assertEqual({1: testfdt_node, 2: test0_node}, 1713 uc.alias_num_to_node) 1714 self.assertEqual({'/some-bus/test': 1, '/some-bus/test0': 2}, 1715 uc.alias_path_to_num) 1716 1717 # Try adding an alias that doesn't exist 1718 self.assertFalse(scan.add_uclass_alias('fred', 3, None)) 1719 1720 # Try adding an alias for a missing node 1721 self.assertIsNone(scan.add_uclass_alias('testfdt', 3, None)) 1722 1723 def test_alias_read_bad(self): 1724 """Test invalid alias property name""" 1725 dtb_file = get_dtb_file('dtoc_test_alias_bad.dts') 1726 output = tools.get_output_filename('output') 1727 with self.assertRaises(ValueError) as exc: 1728 plat = self.run_test(['struct'], dtb_file, output) 1729 self.assertIn("Cannot decode alias 'i2c4-'", str(exc.exception)) 1730 1731 def test_alias_read_bad_path(self): 1732 """Test alias pointing to a non-existent node""" 1733 # This line may produce a warning, so capture it: 1734 # Warning (alias_paths): /aliases:i2c4: aliases property is not a valid 1735 # node (/does/not/exist) 1736 dtb_file = get_dtb_file('dtoc_test_alias_bad_path.dts', True) 1737 1738 output = tools.get_output_filename('output') 1739 with self.assertRaises(ValueError) as exc: 1740 plat = self.run_test(['struct'], dtb_file, output) 1741 self.assertIn("Alias 'i2c4' path '/does/not/exist' not found", 1742 str(exc.exception)) 1743 1744 def test_alias_read_bad_uclass(self): 1745 """Test alias for a uclass that doesn't exist""" 1746 dtb_file = get_dtb_file('dtoc_test_alias_bad_uc.dts') 1747 output = tools.get_output_filename('output') 1748 with terminal.capture() as (stdout, _): 1749 plat = self.run_test(['struct'], dtb_file, output) 1750 self.assertEqual("Could not find uclass for alias 'other1'", 1751 stdout.getvalue().strip()) 1752 1753 def test_sequence(self): 1754 """Test assignment of sequence numnbers""" 1755 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1756 output = tools.get_output_filename('output') 1757 plat = self.run_test(['struct'], dtb_file, output) 1758 1759 scan = plat._scan 1760 testfdt = plat._fdt.GetNode('/some-bus/test') 1761 self.assertEqual(1, testfdt.seq) 1762 i2c = plat._fdt.GetNode('/i2c') 1763 1764 # For now this uclass is not compiled in, so no sequence is assigned 1765 self.assertEqual(4, i2c.seq) 1766 spl = plat._fdt.GetNode('/spl-test') 1767 self.assertEqual(0, spl.seq) 1768 1769 def test_process_root(self): 1770 """Test assignment of sequence numnbers""" 1771 dtb_file = get_dtb_file('dtoc_test_simple.dts') 1772 output = tools.get_output_filename('output') 1773 1774 # Take a copy before messing with it 1775 scan = copy_scan() 1776 plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) 1777 plat.scan_dtb() 1778 root = plat._fdt.GetRoot() 1779 1780 plat.scan_tree(False) 1781 self.assertNotIn(root, plat._valid_nodes) 1782 1783 plat.scan_tree(True) 1784 self.assertIn(root, plat._valid_nodes) 1785 self.assertEqual('root_driver', 1786 scan.get_normalized_compat_name(root)[0]) 1787 1788 def test_simple_inst(self): 1789 """Test output from some simple nodes with instantiate enabled""" 1790 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1791 output = tools.get_output_filename('output') 1792 1793 self.run_test(['decl'], dtb_file, output, True) 1794 with open(output) as infile: 1795 data = infile.read() 1796 1797 self._check_strings(self.decl_text_inst, data) 1798 1799 self.run_test(['uclass'], dtb_file, output, True) 1800 with open(output) as infile: 1801 data = infile.read() 1802 1803 self._check_strings(UCLASS_HEADER_COMMON + self.uclass_text_inst, data) 1804 1805 self.run_test(['device'], dtb_file, output, True) 1806 with open(output) as infile: 1807 data = infile.read() 1808 1809 self._check_strings(self.device_text_inst, data) 1810 1811 def test_inst_no_hdr(self): 1812 """Test dealing with a struct tsssshat has no header""" 1813 dtb_file = get_dtb_file('dtoc_test_inst.dts') 1814 output = tools.get_output_filename('output') 1815 1816 # Run it once to set everything up 1817 plat = self.run_test(['decl'], dtb_file, output, True) 1818 scan = plat._scan 1819 1820 # Restart the output file and delete any record of the uclass' struct 1821 plat.setup_output(Ftype.SOURCE, output) 1822 del scan._structs['dm_test_uc_priv'] 1823 1824 # Now generate the uclasses, which should provide a warning 1825 with terminal.capture() as (stdout, _): 1826 plat.generate_uclasses() 1827 self.assertEqual( 1828 'Warning: Cannot find header file for struct dm_test_uc_priv', 1829 stdout.getvalue().strip()) 1830 1831 def test_missing_props(self): 1832 """Test detection of a parent node with no properties""" 1833 dtb_file = get_dtb_file('dtoc_test_noprops.dts', capture_stderr=True) 1834 output = tools.get_output_filename('output') 1835 with self.assertRaises(ValueError) as exc: 1836 self.run_test(['struct'], dtb_file, output) 1837 self.assertIn("Parent node '/i2c@0' has no properties - do you need", 1838 str(exc.exception)) 1839 1840 def test_single_reg(self): 1841 """Test detection of a parent node with no properties""" 1842 dtb_file = get_dtb_file('dtoc_test_single_reg.dts') 1843 output = tools.get_output_filename('output') 1844 self.run_test(['struct'], dtb_file, output) 1845 1846 def test_missing_parent(self): 1847 """Test detection of a parent node with no properties""" 1848 dtb_file = get_dtb_file('dtoc_test_noparent.dts', capture_stderr=True) 1849 output = tools.get_output_filename('output') 1850 with self.assertRaises(ValueError) as exc: 1851 self.run_test(['device'], dtb_file, output, instantiate=True) 1852 self.assertIn("Node '/i2c@0/spl-test/pmic@9' requires parent node " 1853 "'/i2c@0/spl-test' but it is not in the valid list", 1854 str(exc.exception)) 1855