1# 2# Copyright (c) 2012 The Chromium OS Authors. 3# 4# SPDX-License-Identifier: GPL-2.0+ 5# 6 7"""Tests for the dtb_platdata module 8 9This includes unit tests for some functions and functional tests for 10""" 11 12import collections 13import os 14import struct 15import unittest 16 17import dtb_platdata 18from dtb_platdata import conv_name_to_c 19from dtb_platdata import get_compat_name 20from dtb_platdata import get_value 21from dtb_platdata import tab_to 22import fdt 23import fdt_util 24import tools 25 26our_path = os.path.dirname(os.path.realpath(__file__)) 27 28 29def get_dtb_file(dts_fname): 30 """Compile a .dts file to a .dtb 31 32 Args: 33 dts_fname: Filename of .dts file in the current directory 34 35 Returns: 36 Filename of compiled file in output directory 37 """ 38 return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname)) 39 40 41class TestDtoc(unittest.TestCase): 42 """Tests for dtoc""" 43 @classmethod 44 def setUpClass(cls): 45 tools.PrepareOutputDir(None) 46 47 @classmethod 48 def tearDownClass(cls): 49 tools._RemoveOutputDir() 50 51 def test_name(self): 52 """Test conversion of device tree names to C identifiers""" 53 self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12')) 54 self.assertEqual('vendor_clock_frequency', 55 conv_name_to_c('vendor,clock-frequency')) 56 self.assertEqual('rockchip_rk3399_sdhci_5_1', 57 conv_name_to_c('rockchip,rk3399-sdhci-5.1')) 58 59 def test_tab_to(self): 60 """Test operation of tab_to() function""" 61 self.assertEqual('fred ', tab_to(0, 'fred')) 62 self.assertEqual('fred\t', tab_to(1, 'fred')) 63 self.assertEqual('fred was here ', tab_to(1, 'fred was here')) 64 self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here')) 65 self.assertEqual('exactly8 ', tab_to(1, 'exactly8')) 66 self.assertEqual('exactly8\t', tab_to(2, 'exactly8')) 67 68 def test_get_value(self): 69 """Test operation of get_value() function""" 70 self.assertEqual('0x45', 71 get_value(fdt.TYPE_INT, struct.pack('>I', 0x45))) 72 self.assertEqual('0x45', 73 get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45))) 74 self.assertEqual('0x0', 75 get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45))) 76 self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test')) 77 self.assertEqual('true', get_value(fdt.TYPE_BOOL, None)) 78 79 def test_get_compat_name(self): 80 """Test operation of get_compat_name() function""" 81 Prop = collections.namedtuple('Prop', ['value']) 82 Node = collections.namedtuple('Node', ['props']) 83 84 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1']) 85 node = Node({'compatible': prop}) 86 self.assertEqual(('rockchip_rk3399_sdhci_5_1', ['arasan_sdhci_5_1']), 87 get_compat_name(node)) 88 89 prop = Prop(['rockchip,rk3399-sdhci-5.1']) 90 node = Node({'compatible': prop}) 91 self.assertEqual(('rockchip_rk3399_sdhci_5_1', []), 92 get_compat_name(node)) 93 94 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third']) 95 node = Node({'compatible': prop}) 96 self.assertEqual(('rockchip_rk3399_sdhci_5_1', 97 ['arasan_sdhci_5_1', 'third']), 98 get_compat_name(node)) 99 100 def test_empty_file(self): 101 """Test output from a device tree file with no nodes""" 102 dtb_file = get_dtb_file('dtoc_test_empty.dts') 103 output = tools.GetOutputFilename('output') 104 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 105 with open(output) as infile: 106 lines = infile.read().splitlines() 107 self.assertEqual(['#include <stdbool.h>', '#include <libfdt.h>'], lines) 108 109 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 110 with open(output) as infile: 111 lines = infile.read().splitlines() 112 self.assertEqual(['#include <common.h>', '#include <dm.h>', 113 '#include <dt-structs.h>', ''], lines) 114 115 def test_simple(self): 116 """Test output from some simple nodes with various types of data""" 117 dtb_file = get_dtb_file('dtoc_test_simple.dts') 118 output = tools.GetOutputFilename('output') 119 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 120 with open(output) as infile: 121 data = infile.read() 122 self.assertEqual('''#include <stdbool.h> 123#include <libfdt.h> 124struct dtd_sandbox_spl_test { 125\tbool\t\tboolval; 126\tunsigned char\tbytearray[3]; 127\tunsigned char\tbyteval; 128\tfdt32_t\t\tintarray[4]; 129\tfdt32_t\t\tintval; 130\tunsigned char\tlongbytearray[9]; 131\tconst char *\tstringarray[3]; 132\tconst char *\tstringval; 133}; 134struct dtd_sandbox_spl_test_2 { 135}; 136''', data) 137 138 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 139 with open(output) as infile: 140 data = infile.read() 141 self.assertEqual('''#include <common.h> 142#include <dm.h> 143#include <dt-structs.h> 144 145static struct dtd_sandbox_spl_test dtv_spl_test = { 146\t.bytearray\t\t= {0x6, 0x0, 0x0}, 147\t.byteval\t\t= 0x5, 148\t.intval\t\t\t= 0x1, 149\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 150\t\t0x11}, 151\t.stringval\t\t= "message", 152\t.boolval\t\t= true, 153\t.intarray\t\t= {0x2, 0x3, 0x4, 0x0}, 154\t.stringarray\t\t= {"multi-word", "message", ""}, 155}; 156U_BOOT_DEVICE(spl_test) = { 157\t.name\t\t= "sandbox_spl_test", 158\t.platdata\t= &dtv_spl_test, 159\t.platdata_size\t= sizeof(dtv_spl_test), 160}; 161 162static struct dtd_sandbox_spl_test dtv_spl_test2 = { 163\t.bytearray\t\t= {0x1, 0x23, 0x34}, 164\t.byteval\t\t= 0x8, 165\t.intval\t\t\t= 0x3, 166\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 167\t\t0x0}, 168\t.stringval\t\t= "message2", 169\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, 170\t.stringarray\t\t= {"another", "multi-word", "message"}, 171}; 172U_BOOT_DEVICE(spl_test2) = { 173\t.name\t\t= "sandbox_spl_test", 174\t.platdata\t= &dtv_spl_test2, 175\t.platdata_size\t= sizeof(dtv_spl_test2), 176}; 177 178static struct dtd_sandbox_spl_test dtv_spl_test3 = { 179\t.stringarray\t\t= {"one", "", ""}, 180}; 181U_BOOT_DEVICE(spl_test3) = { 182\t.name\t\t= "sandbox_spl_test", 183\t.platdata\t= &dtv_spl_test3, 184\t.platdata_size\t= sizeof(dtv_spl_test3), 185}; 186 187static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { 188}; 189U_BOOT_DEVICE(spl_test4) = { 190\t.name\t\t= "sandbox_spl_test_2", 191\t.platdata\t= &dtv_spl_test4, 192\t.platdata_size\t= sizeof(dtv_spl_test4), 193}; 194 195''', data) 196 197 def test_phandle(self): 198 """Test output from a node containing a phandle reference""" 199 dtb_file = get_dtb_file('dtoc_test_phandle.dts') 200 output = tools.GetOutputFilename('output') 201 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 202 with open(output) as infile: 203 data = infile.read() 204 self.assertEqual('''#include <stdbool.h> 205#include <libfdt.h> 206struct dtd_source { 207\tstruct phandle_2_cell clocks[1]; 208}; 209struct dtd_target { 210\tfdt32_t\t\tintval; 211}; 212''', data) 213 214 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 215 with open(output) as infile: 216 data = infile.read() 217 self.assertEqual('''#include <common.h> 218#include <dm.h> 219#include <dt-structs.h> 220 221static struct dtd_target dtv_phandle_target = { 222\t.intval\t\t\t= 0x1, 223}; 224U_BOOT_DEVICE(phandle_target) = { 225\t.name\t\t= "target", 226\t.platdata\t= &dtv_phandle_target, 227\t.platdata_size\t= sizeof(dtv_phandle_target), 228}; 229 230static struct dtd_source dtv_phandle_source = { 231\t.clocks\t\t\t= {{&dtv_phandle_target, 1}}, 232}; 233U_BOOT_DEVICE(phandle_source) = { 234\t.name\t\t= "source", 235\t.platdata\t= &dtv_phandle_source, 236\t.platdata_size\t= sizeof(dtv_phandle_source), 237}; 238 239''', data) 240 241 def test_aliases(self): 242 """Test output from a node with multiple compatible strings""" 243 dtb_file = get_dtb_file('dtoc_test_aliases.dts') 244 output = tools.GetOutputFilename('output') 245 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 246 with open(output) as infile: 247 data = infile.read() 248 self.assertEqual('''#include <stdbool.h> 249#include <libfdt.h> 250struct dtd_compat1 { 251\tfdt32_t\t\tintval; 252}; 253#define dtd_compat2_1_fred dtd_compat1 254#define dtd_compat3 dtd_compat1 255''', data) 256 257 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 258 with open(output) as infile: 259 data = infile.read() 260 self.assertEqual('''#include <common.h> 261#include <dm.h> 262#include <dt-structs.h> 263 264static struct dtd_compat1 dtv_spl_test = { 265\t.intval\t\t\t= 0x1, 266}; 267U_BOOT_DEVICE(spl_test) = { 268\t.name\t\t= "compat1", 269\t.platdata\t= &dtv_spl_test, 270\t.platdata_size\t= sizeof(dtv_spl_test), 271}; 272 273''', data) 274 275 def test_addresses64(self): 276 """Test output from a node with a 'reg' property with na=2, ns=2""" 277 dtb_file = get_dtb_file('dtoc_test_addr64.dts') 278 output = tools.GetOutputFilename('output') 279 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 280 with open(output) as infile: 281 data = infile.read() 282 self.assertEqual('''#include <stdbool.h> 283#include <libfdt.h> 284struct dtd_test1 { 285\tfdt64_t\t\treg[2]; 286}; 287struct dtd_test2 { 288\tfdt64_t\t\treg[2]; 289}; 290struct dtd_test3 { 291\tfdt64_t\t\treg[4]; 292}; 293''', data) 294 295 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 296 with open(output) as infile: 297 data = infile.read() 298 self.assertEqual('''#include <common.h> 299#include <dm.h> 300#include <dt-structs.h> 301 302static struct dtd_test1 dtv_test1 = { 303\t.reg\t\t\t= {0x1234, 0x5678}, 304}; 305U_BOOT_DEVICE(test1) = { 306\t.name\t\t= "test1", 307\t.platdata\t= &dtv_test1, 308\t.platdata_size\t= sizeof(dtv_test1), 309}; 310 311static struct dtd_test2 dtv_test2 = { 312\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, 313}; 314U_BOOT_DEVICE(test2) = { 315\t.name\t\t= "test2", 316\t.platdata\t= &dtv_test2, 317\t.platdata_size\t= sizeof(dtv_test2), 318}; 319 320static struct dtd_test3 dtv_test3 = { 321\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, 322}; 323U_BOOT_DEVICE(test3) = { 324\t.name\t\t= "test3", 325\t.platdata\t= &dtv_test3, 326\t.platdata_size\t= sizeof(dtv_test3), 327}; 328 329''', data) 330 331 def test_addresses32(self): 332 """Test output from a node with a 'reg' property with na=1, ns=1""" 333 dtb_file = get_dtb_file('dtoc_test_addr32.dts') 334 output = tools.GetOutputFilename('output') 335 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 336 with open(output) as infile: 337 data = infile.read() 338 self.assertEqual('''#include <stdbool.h> 339#include <libfdt.h> 340struct dtd_test1 { 341\tfdt32_t\t\treg[2]; 342}; 343struct dtd_test2 { 344\tfdt32_t\t\treg[4]; 345}; 346''', data) 347 348 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 349 with open(output) as infile: 350 data = infile.read() 351 self.assertEqual('''#include <common.h> 352#include <dm.h> 353#include <dt-structs.h> 354 355static struct dtd_test1 dtv_test1 = { 356\t.reg\t\t\t= {0x1234, 0x5678}, 357}; 358U_BOOT_DEVICE(test1) = { 359\t.name\t\t= "test1", 360\t.platdata\t= &dtv_test1, 361\t.platdata_size\t= sizeof(dtv_test1), 362}; 363 364static struct dtd_test2 dtv_test2 = { 365\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, 366}; 367U_BOOT_DEVICE(test2) = { 368\t.name\t\t= "test2", 369\t.platdata\t= &dtv_test2, 370\t.platdata_size\t= sizeof(dtv_test2), 371}; 372 373''', data) 374 375 def test_addresses64_32(self): 376 """Test output from a node with a 'reg' property with na=2, ns=1""" 377 dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') 378 output = tools.GetOutputFilename('output') 379 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 380 with open(output) as infile: 381 data = infile.read() 382 self.assertEqual('''#include <stdbool.h> 383#include <libfdt.h> 384struct dtd_test1 { 385\tfdt64_t\t\treg[2]; 386}; 387struct dtd_test2 { 388\tfdt64_t\t\treg[2]; 389}; 390struct dtd_test3 { 391\tfdt64_t\t\treg[4]; 392}; 393''', data) 394 395 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 396 with open(output) as infile: 397 data = infile.read() 398 self.assertEqual('''#include <common.h> 399#include <dm.h> 400#include <dt-structs.h> 401 402static struct dtd_test1 dtv_test1 = { 403\t.reg\t\t\t= {0x123400000000, 0x5678}, 404}; 405U_BOOT_DEVICE(test1) = { 406\t.name\t\t= "test1", 407\t.platdata\t= &dtv_test1, 408\t.platdata_size\t= sizeof(dtv_test1), 409}; 410 411static struct dtd_test2 dtv_test2 = { 412\t.reg\t\t\t= {0x1234567890123456, 0x98765432}, 413}; 414U_BOOT_DEVICE(test2) = { 415\t.name\t\t= "test2", 416\t.platdata\t= &dtv_test2, 417\t.platdata_size\t= sizeof(dtv_test2), 418}; 419 420static struct dtd_test3 dtv_test3 = { 421\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, 422}; 423U_BOOT_DEVICE(test3) = { 424\t.name\t\t= "test3", 425\t.platdata\t= &dtv_test3, 426\t.platdata_size\t= sizeof(dtv_test3), 427}; 428 429''', data) 430 431 def test_addresses32_64(self): 432 """Test output from a node with a 'reg' property with na=1, ns=2""" 433 dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') 434 output = tools.GetOutputFilename('output') 435 dtb_platdata.run_steps(['struct'], dtb_file, False, output) 436 with open(output) as infile: 437 data = infile.read() 438 self.assertEqual('''#include <stdbool.h> 439#include <libfdt.h> 440struct dtd_test1 { 441\tfdt64_t\t\treg[2]; 442}; 443struct dtd_test2 { 444\tfdt64_t\t\treg[2]; 445}; 446struct dtd_test3 { 447\tfdt64_t\t\treg[4]; 448}; 449''', data) 450 451 dtb_platdata.run_steps(['platdata'], dtb_file, False, output) 452 with open(output) as infile: 453 data = infile.read() 454 self.assertEqual('''#include <common.h> 455#include <dm.h> 456#include <dt-structs.h> 457 458static struct dtd_test1 dtv_test1 = { 459\t.reg\t\t\t= {0x1234, 0x567800000000}, 460}; 461U_BOOT_DEVICE(test1) = { 462\t.name\t\t= "test1", 463\t.platdata\t= &dtv_test1, 464\t.platdata_size\t= sizeof(dtv_test1), 465}; 466 467static struct dtd_test2 dtv_test2 = { 468\t.reg\t\t\t= {0x12345678, 0x9876543210987654}, 469}; 470U_BOOT_DEVICE(test2) = { 471\t.name\t\t= "test2", 472\t.platdata\t= &dtv_test2, 473\t.platdata_size\t= sizeof(dtv_test2), 474}; 475 476static struct dtd_test3 dtv_test3 = { 477\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, 478}; 479U_BOOT_DEVICE(test3) = { 480\t.name\t\t= "test3", 481\t.platdata\t= &dtv_test3, 482\t.platdata_size\t= sizeof(dtv_test3), 483}; 484 485''', data) 486