1# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) 2# pylibfdt - Tests for Flat Device Tree manipulation in Python 3# Copyright (C) 2017 Google, Inc. 4# Written by Simon Glass <[email protected]> 5# 6 7import struct 8import sys 9import types 10import unittest 11 12sys.path.insert(0, '../pylibfdt') 13import libfdt 14from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL 15 16TEST_ADDR_1H = 0xdeadbeef 17TEST_ADDR_1L = 0x00000000 18TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L 19TEST_ADDR_1 = 0x8000000000000000 20TEST_SIZE_1H = 0x00000000 21TEST_SIZE_1L = 0x00100000 22TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L 23TEST_ADDR_2H = 0 24TEST_ADDR_2L = 123456789 25TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L 26TEST_SIZE_2H = 0 27TEST_SIZE_2L = 0o10000 28TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L 29 30TEST_VALUE_1 = 0xdeadbeef 31TEST_VALUE_2 = 123456789 32 33TEST_VALUE64_1H = 0xdeadbeef 34TEST_VALUE64_1L = 0x01abcdef 35TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L 36 37PHANDLE_1 = 0x2000 38PHANDLE_2 = 0x2001 39 40TEST_BYTES_1 = b'hello world' 41 42TEST_STRING_1 = 'hello world' 43TEST_STRING_2 = 'hi world' 44TEST_STRING_3 = u'unicode \u01d3' 45 46 47def get_err(err_code): 48 """Convert an error code into an error message 49 50 Args: 51 err_code: Error code value (FDT_ERR_...) 52 53 Returns: 54 String error code 55 """ 56 return 'pylibfdt error %d: %s' % (-err_code, libfdt.strerror(-err_code)) 57 58def _ReadFdt(fname): 59 """Read a device tree file into an Fdt object, ready for use 60 61 Args: 62 fname: Filename to read from 63 64 Returns: 65 Fdt bytearray suitable for passing to libfdt functions 66 """ 67 with open(fname, mode='rb') as f: 68 return libfdt.Fdt(f.read()) 69 70class PyLibfdtBasicTests(unittest.TestCase): 71 """Test class for basic pylibfdt access functions 72 73 Properties: 74 fdt: Device tree file used for testing 75 """ 76 77 def setUp(self): 78 """Read in the device tree we use for testing""" 79 self.fdt = _ReadFdt('test_tree1.dtb') 80 self.fdt2 = _ReadFdt('test_props.dtb') 81 self.fdt3 = _ReadFdt('aliases.dtb') 82 83 def GetPropList(self, node_path): 84 """Read a list of properties from a node 85 86 Args: 87 node_path: Full path to node, e.g. '/subnode@1/subsubnode' 88 89 Returns: 90 List of property names for that node, e.g. ['compatible', 'reg'] 91 """ 92 prop_list = [] 93 node = self.fdt.path_offset(node_path) 94 poffset = self.fdt.first_property_offset(node, QUIET_NOTFOUND) 95 while poffset > 0: 96 prop = self.fdt.get_property_by_offset(poffset) 97 prop_list.append(prop.name) 98 poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND) 99 return prop_list 100 101 def GetSubnodes(self, node_path): 102 """Read a list of subnodes from a node 103 104 Args: 105 node_path: Full path to node, e.g. '/subnode@1/subsubnode' 106 107 Returns: 108 List of subnode names for that node, e.g. ['subsubnode', 'ss1'] 109 """ 110 subnode_list = [] 111 node = self.fdt.path_offset(node_path) 112 offset = self.fdt.first_subnode(node, QUIET_NOTFOUND) 113 while offset > 0: 114 name = self.fdt.get_name(offset) 115 subnode_list.append(name) 116 offset = self.fdt.next_subnode(offset, QUIET_NOTFOUND) 117 return subnode_list 118 119 def testImport(self): 120 """Check that we can import the library correctly""" 121 self.assertEqual(type(libfdt), types.ModuleType) 122 123 def testBadFdt(self): 124 """Check that a filename provided accidentally is not accepted""" 125 with self.assertRaises(FdtException) as e: 126 fdt = libfdt.Fdt(b'a string') 127 self.assertEqual(e.exception.err, -libfdt.BADMAGIC) 128 129 def testSubnodeOffset(self): 130 """check that we can locate a subnode by name""" 131 node1 = self.fdt.path_offset('/subnode@1') 132 self.assertEqual(self.fdt.subnode_offset(0, 'subnode@1'), node1) 133 134 with self.assertRaises(FdtException) as e: 135 self.fdt.subnode_offset(0, 'missing') 136 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 137 138 node2 = self.fdt.path_offset('/subnode@1/subsubnode') 139 self.assertEqual(self.fdt.subnode_offset(node1, 'subsubnode'), node2) 140 141 def testPathOffset(self): 142 """Check that we can find the offset of a node""" 143 self.assertEqual(self.fdt.path_offset('/'), 0) 144 self.assertTrue(self.fdt.path_offset('/subnode@1') > 0) 145 with self.assertRaises(FdtException) as e: 146 self.fdt.path_offset('/wibble') 147 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 148 self.assertEqual(self.fdt.path_offset('/wibble', QUIET_NOTFOUND), 149 -libfdt.NOTFOUND) 150 151 def testPropertyOffset(self): 152 """Walk through all the properties in the root node""" 153 offset = self.fdt.first_property_offset(0) 154 self.assertTrue(offset > 0) 155 for i in range(5): 156 next_offset = self.fdt.next_property_offset(offset) 157 self.assertTrue(next_offset > offset) 158 offset = next_offset 159 self.assertEqual(self.fdt.next_property_offset(offset, QUIET_NOTFOUND), 160 -libfdt.NOTFOUND) 161 162 def testPropertyOffsetExceptions(self): 163 """Check that exceptions are raised as expected""" 164 with self.assertRaises(FdtException) as e: 165 self.fdt.first_property_offset(107) 166 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 167 168 # Quieten the NOTFOUND exception and check that a BADOFFSET 169 # exception is still raised. 170 with self.assertRaises(FdtException) as e: 171 self.fdt.first_property_offset(107, QUIET_NOTFOUND) 172 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 173 with self.assertRaises(FdtException) as e: 174 self.fdt.next_property_offset(107, QUIET_NOTFOUND) 175 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 176 177 # Check that NOTFOUND can be quietened. 178 node = self.fdt.path_offset('/subnode@1/ss1') 179 self.assertEqual(self.fdt.first_property_offset(node, QUIET_NOTFOUND), 180 -libfdt.NOTFOUND) 181 with self.assertRaises(FdtException) as e: 182 self.fdt.first_property_offset(node) 183 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 184 185 def testGetName(self): 186 """Check that we can get the name of a node""" 187 self.assertEqual(self.fdt.get_name(0), '') 188 node = self.fdt.path_offset('/subnode@1/subsubnode') 189 self.assertEqual(self.fdt.get_name(node), 'subsubnode') 190 191 with self.assertRaises(FdtException) as e: 192 self.fdt.get_name(-2) 193 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 194 195 def testGetPropertyByOffset(self): 196 """Check that we can read the name and contents of a property""" 197 root = 0 198 poffset = self.fdt.first_property_offset(root) 199 prop = self.fdt.get_property_by_offset(poffset) 200 self.assertEqual(prop.name, 'compatible') 201 self.assertEqual(prop, b'test_tree1\0') 202 203 with self.assertRaises(FdtException) as e: 204 self.fdt.get_property_by_offset(-2) 205 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 206 self.assertEqual( 207 -libfdt.BADOFFSET, 208 self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET])) 209 210 def testGetProp(self): 211 """Check that we can read the contents of a property by name""" 212 root = self.fdt.path_offset('/') 213 value = self.fdt.getprop(root, "compatible") 214 self.assertEqual(value, b'test_tree1\0') 215 self.assertEqual(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing', 216 QUIET_NOTFOUND)) 217 218 with self.assertRaises(FdtException) as e: 219 self.fdt.getprop(root, 'missing') 220 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 221 222 node = self.fdt.path_offset('/subnode@1/subsubnode') 223 value = self.fdt.getprop(node, "compatible") 224 self.assertEqual(value, b'subsubnode1\0subsubnode\0') 225 226 def testStrError(self): 227 """Check that we can get an error string""" 228 self.assertEqual(libfdt.strerror(-libfdt.NOTFOUND), 229 'FDT_ERR_NOTFOUND') 230 231 def testNextNodeOffset(self): 232 """Check that we can walk through nodes""" 233 node_list = [] 234 node = 0 235 depth = 0 236 while depth >= 0: 237 node_list.append([depth, self.fdt.get_name(node)]) 238 node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,)) 239 self.assertEqual(node_list, [ 240 [0, ''], 241 [1, 'subnode@1'], 242 [2, 'subsubnode'], 243 [2, 'ss1'], 244 [1, 'subnode@2'], 245 [2, 'subsubnode@0'], 246 [2, 'ss2'], 247 ]) 248 249 def testFirstNextSubnodeOffset(self): 250 """Check that we can walk through subnodes""" 251 node_list = [] 252 node = self.fdt.first_subnode(0, QUIET_NOTFOUND) 253 while node >= 0: 254 node_list.append(self.fdt.get_name(node)) 255 node = self.fdt.next_subnode(node, QUIET_NOTFOUND) 256 self.assertEqual(node_list, ['subnode@1', 'subnode@2']) 257 258 def testFirstNextSubnodeOffsetExceptions(self): 259 """Check except handling for first/next subnode functions""" 260 node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND) 261 self.assertEqual(self.fdt.first_subnode(node, QUIET_NOTFOUND), 262 -libfdt.NOTFOUND) 263 with self.assertRaises(FdtException) as e: 264 self.fdt.first_subnode(node) 265 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 266 267 node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND) 268 self.assertEqual(self.fdt.next_subnode(node, QUIET_NOTFOUND), 269 -libfdt.NOTFOUND) 270 with self.assertRaises(FdtException) as e: 271 self.fdt.next_subnode(node) 272 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 273 274 def testDeleteProperty(self): 275 """Test that we can delete a property""" 276 node_name = '/subnode@1' 277 self.assertEqual(self.GetPropList(node_name), 278 ['compatible', 'reg', 'prop-int']) 279 node = self.fdt.path_offset('/%s' % node_name) 280 self.assertEqual(self.fdt.delprop(node, 'reg'), 0) 281 self.assertEqual(self.GetPropList(node_name), 282 ['compatible', 'prop-int']) 283 284 def testHeader(self): 285 """Test that we can access the header values""" 286 self.assertEqual(self.fdt.magic(), 0xd00dfeed) 287 self.assertEqual(self.fdt.totalsize(), len(self.fdt._fdt)) 288 self.assertEqual(self.fdt.off_dt_struct(), 88) 289 self.assertEqual(self.fdt.off_dt_strings(), 652) 290 self.assertEqual(self.fdt.off_mem_rsvmap(), 40) 291 self.assertEqual(self.fdt.version(), 17) 292 self.assertEqual(self.fdt.last_comp_version(), 16) 293 self.assertEqual(self.fdt.boot_cpuid_phys(), 0) 294 self.assertEqual(self.fdt.size_dt_strings(), 105) 295 self.assertEqual(self.fdt.size_dt_struct(), 564) 296 297 def testPack(self): 298 """Test that we can pack the tree after deleting something""" 299 orig_size = self.fdt.totalsize() 300 node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND) 301 self.assertEqual(self.fdt.delprop(node, 'prop-int'), 0) 302 self.assertEqual(orig_size, self.fdt.totalsize()) 303 self.assertEqual(self.fdt.pack(), 0) 304 self.assertTrue(self.fdt.totalsize() < orig_size) 305 self.assertEqual(self.fdt.totalsize(), len(self.fdt.as_bytearray())) 306 307 def testBadPropertyOffset(self): 308 """Test that bad property offsets are detected""" 309 with self.assertRaises(FdtException) as e: 310 self.fdt.get_property_by_offset(13) 311 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 312 with self.assertRaises(FdtException) as e: 313 self.fdt.first_property_offset(3) 314 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 315 with self.assertRaises(FdtException) as e: 316 self.fdt.next_property_offset(3) 317 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 318 319 def testBadPathOffset(self): 320 """Test that bad path names are detected""" 321 with self.assertRaisesRegex(FdtException, get_err(libfdt.BADPATH)): 322 self.fdt.path_offset('not-present') 323 324 def testQuietAll(self): 325 """Check that exceptions can be masked by QUIET_ALL""" 326 self.assertEqual(-libfdt.NOTFOUND, 327 self.fdt.path_offset('/missing', QUIET_ALL)) 328 self.assertEqual(-libfdt.BADOFFSET, 329 self.fdt.get_property_by_offset(13, QUIET_ALL)) 330 self.assertEqual(-libfdt.BADPATH, 331 self.fdt.path_offset('missing', QUIET_ALL)) 332 333 def testIntegers(self): 334 """Check that integers can be passed and returned""" 335 self.assertEqual(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) 336 node2 = self.fdt.path_offset('/subnode@2') 337 self.assertEqual(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) 338 339 def testGetPhandle(self): 340 """Test for the get_phandle() method""" 341 self.assertEqual(0, self.fdt.get_phandle(0)) 342 node2 = self.fdt.path_offset('/subnode@2') 343 self.assertEqual(0x2000, self.fdt.get_phandle(node2)) 344 345 def testGetAlias(self): 346 """Test for the get_alias() method""" 347 self.assertEqual("/subnode@1", self.fdt3.get_alias('s1')) 348 self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1')) 349 self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1')) 350 351 def testGetPath(self): 352 """Test for the get_path() method""" 353 node = self.fdt.path_offset('/subnode@1') 354 node2 = self.fdt.path_offset('/subnode@1/subsubnode') 355 self.assertEqual("/subnode@1", self.fdt.get_path(node)) 356 self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2)) 357 self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2, size_hint=1)) 358 359 with self.assertRaises(FdtException) as e: 360 self.fdt.get_path(-1) 361 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 362 363 self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,))) 364 365 def testParentOffset(self): 366 """Test for the parent_offset() method""" 367 self.assertEqual(-libfdt.NOTFOUND, 368 self.fdt.parent_offset(0, QUIET_NOTFOUND)) 369 with self.assertRaises(FdtException) as e: 370 self.fdt.parent_offset(0) 371 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 372 373 node1 = self.fdt.path_offset('/subnode@2') 374 self.assertEqual(0, self.fdt.parent_offset(node1)) 375 node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') 376 self.assertEqual(node1, self.fdt.parent_offset(node2)) 377 378 def testNodeOffsetByPhandle(self): 379 """Test for the node_offset_by_phandle() method""" 380 self.assertEqual(-libfdt.NOTFOUND, 381 self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND)) 382 node1 = self.fdt.path_offset('/subnode@2') 383 self.assertEqual(node1, self.fdt.node_offset_by_phandle(0x2000)) 384 node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') 385 self.assertEqual(node2, self.fdt.node_offset_by_phandle(0x2001)) 386 387 def get_prop(self, name): 388 return self.fdt2.getprop(0, name) 389 390 def testGetIntProperties(self): 391 """Test that we can access properties as integers""" 392 self.assertEqual(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) 393 self.assertEqual(123, self.get_prop("prop-uint32").as_uint32()) 394 self.assertEqual(-2, self.get_prop("prop-int32").as_int32()) 395 self.assertEqual(9223372036854775807, 396 self.get_prop("prop-uint64").as_uint64()) 397 self.assertEqual(-2, self.get_prop("prop-int64").as_int64()) 398 399 def testGetIntListProperties(self): 400 """Test that we can access properties as integer lists""" 401 self.assertEqual([128, -16, -2], 402 self.get_prop("prop-int32-array").as_int32_list()) 403 self.assertEqual([0x1, 0x98765432, 0xdeadbeef], 404 self.get_prop("prop-uint32-array").as_uint32_list()) 405 self.assertEqual([0x100000000, -2], 406 self.get_prop("prop-int64-array").as_int64_list()) 407 self.assertEqual([0x100000000, 0x1], 408 self.get_prop("prop-uint64-array").as_uint64_list()) 409 410 def testGetStringlistProperties(self): 411 """Test that we can access properties as string list""" 412 node = self.fdt.path_offset('/subnode@1/subsubnode') 413 self.assertEqual(["subsubnode1", "subsubnode"], 414 self.fdt.getprop(node, "compatible").as_stringlist()) 415 self.assertEqual(["this is a placeholder string", "string2"], 416 self.fdt.getprop(node, "placeholder").as_stringlist()) 417 418 def testReserveMap(self): 419 """Test that we can access the memory reserve map""" 420 self.assertEqual(2, self.fdt.num_mem_rsv()) 421 self.assertEqual([ 0xdeadbeef00000000, 0x100000], 422 self.fdt.get_mem_rsv(0)) 423 self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1)) 424 425 def testEmpty(self): 426 """Test that we can create an empty tree""" 427 self.assertEqual(-libfdt.NOSPACE, 428 Fdt.create_empty_tree(1, (libfdt.NOSPACE,))) 429 fdt = Fdt.create_empty_tree(128) 430 self.assertEqual(128, fdt.totalsize()) 431 432 def testOpenInto(self): 433 """Test that we can resize a tree""" 434 fdt = Fdt.create_empty_tree(128) 435 self.assertEqual(128, fdt.totalsize()) 436 fdt.resize(256) 437 self.assertEqual(256, fdt.totalsize()) 438 fdt.pack() 439 self.assertTrue(fdt.totalsize() < 128) 440 441 def testSetProp(self): 442 """Test that we can update and create properties""" 443 node = self.fdt.path_offset('/subnode@1') 444 self.fdt.setprop(node, 'compatible', TEST_BYTES_1) 445 self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'compatible')) 446 447 # Check that this property is missing, and that we don't have space to 448 # add it 449 self.assertEqual(-libfdt.NOTFOUND, 450 self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) 451 self.assertEqual(-libfdt.NOSPACE, 452 self.fdt.setprop(node, 'missing', TEST_BYTES_1, 453 quiet=(libfdt.NOSPACE,))) 454 455 # Expand the device tree so we now have room 456 self.fdt.resize(self.fdt.totalsize() + 50) 457 self.fdt.setprop(node, 'missing', TEST_BYTES_1) 458 self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'missing')) 459 460 def testSetPropU32(self): 461 """Test that we can update and create integer properties""" 462 node = 0 463 prop = 'prop-int' 464 self.fdt.setprop_u32(node, prop, TEST_VALUE_1) 465 self.assertEqual(struct.pack('>I', TEST_VALUE_1), 466 self.fdt.getprop(node, prop)) 467 468 def testSetPropU64(self): 469 """Test that we can update and create integer properties""" 470 node = 0 471 prop = 'prop-int64' 472 self.fdt.setprop_u64(node, prop, TEST_VALUE64_1) 473 self.assertEqual(struct.pack('>Q', TEST_VALUE64_1), 474 self.fdt.getprop(node, prop)) 475 476 def testSetPropStr(self): 477 """Test that we can set a property to a particular string""" 478 node = 0 479 prop = 'prop-str' 480 self.assertEqual(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) 481 self.fdt.setprop_str(node, prop, TEST_STRING_2) 482 self.assertEqual(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) 483 with self.assertRaises(ValueError) as e: 484 self.fdt.getprop(node, 'prop-int').as_str() 485 self.assertIn('lacks nul termination', str(e.exception)) 486 487 node2 = self.fdt.path_offset('/subnode@1/subsubnode') 488 with self.assertRaises(ValueError) as e: 489 self.fdt.getprop(node2, 'compatible').as_str() 490 self.assertIn('embedded nul', str(e.exception)) 491 492 # Expand the device tree so we now have room 493 self.fdt.resize(self.fdt.totalsize() + 50) 494 prop = 'prop-unicode' 495 self.fdt.setprop_str(node, prop, TEST_STRING_3) 496 self.assertEqual(TEST_STRING_3, 497 self.fdt.getprop(node, prop).as_str()) 498 499 def testSetName(self): 500 """Test that we can update a node name""" 501 node = self.fdt.path_offset('/subnode@1') 502 old_val = self.fdt.get_name(node) 503 self.fdt.set_name(node, 'test') 504 self.assertEqual('test', self.fdt.get_name(node)) 505 506 with self.assertRaises(ValueError) as e: 507 self.fdt.set_name(node, 'some\0name') 508 self.assertIn('embedded nul', str(e.exception)) 509 510 with self.assertRaises(ValueError) as e: 511 self.fdt.set_name(node, 'name\0') 512 self.assertIn('embedded nul', str(e.exception)) 513 514 def testAddDeleteNodes(self): 515 """Test that we can add and delete nodes""" 516 node_name = '/subnode@1' 517 self.assertEqual(self.GetSubnodes(node_name), ['subsubnode', 'ss1']) 518 node = self.fdt.path_offset('%s/subsubnode' % node_name) 519 self.assertEqual(self.fdt.del_node(node, 'subsubnode'), 0) 520 self.assertEqual(self.GetSubnodes(node_name), ['ss1']) 521 522 node = self.fdt.path_offset(node_name) 523 offset = self.fdt.add_subnode(node, 'more') 524 self.assertTrue(offset > 0) 525 self.assertEqual(self.GetSubnodes(node_name), ['more', 'ss1']) 526 527 528class PyLibfdtSwTests(unittest.TestCase): 529 """Test class for pylibfdt sequential-write DT creation 530 """ 531 def assertOk(self, err_code): 532 self.assertEqual(0, err_code) 533 534 def testCreate(self): 535 # First check the minimum size and also the FdtSw() constructor 536 with self.assertRaisesRegex(FdtException, get_err(libfdt.NOSPACE)): 537 self.assertEqual(-libfdt.NOSPACE, FdtSw(3)) 538 539 sw = FdtSw() 540 sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1) 541 sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2) 542 sw.finish_reservemap() 543 544 sw.begin_node('') 545 sw.property_string('compatible', 'test_tree1') 546 sw.property_u32('prop-int', TEST_VALUE_1) 547 548 sw.property_u32('prop-int', TEST_VALUE_1) 549 sw.property_u64('prop-int64', TEST_VALUE64_1) 550 sw.property_string('prop-str', TEST_STRING_1) 551 sw.property_u32('#address-cells', 1) 552 sw.property_u32('#size-cells', 0) 553 554 sw.begin_node('subnode@1') 555 sw.property_string('compatible', 'subnode1') 556 sw.property_u32('reg', 1) 557 sw.property_cell('prop-int', TEST_VALUE_1) 558 sw.property('data', b'\x00data\x01') 559 sw.begin_node('subsubnode') 560 sw.property('compatible', b'subsubnode1\0subsubnode') 561 sw.property_cell('prop-int', TEST_VALUE_1) 562 sw.end_node() 563 sw.begin_node('ss1') 564 sw.end_node() 565 sw.end_node() 566 567 for i in range(2, 11): 568 with sw.add_node('subnode@%d' % i): 569 sw.property_u32('reg', 2) 570 sw.property_cell('linux,phandle', PHANDLE_1) 571 sw.property_cell('prop-int', TEST_VALUE_2) 572 sw.property_u32('#address-cells', 1) 573 sw.property_u32('#size-cells', 0) 574 with sw.add_node('subsubnode@0'): 575 sw.property_u32('reg', 0) 576 sw.property_cell('phandle', PHANDLE_2) 577 sw.property('compatible', b'subsubnode2\0subsubnode') 578 sw.property_cell('prop-int', TEST_VALUE_2) 579 with sw.add_node('ss2'): 580 pass 581 sw.end_node() 582 583 fdt = sw.as_fdt() 584 self.assertEqual(2, fdt.num_mem_rsv()) 585 self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0)) 586 587 # Make sure we can add a few more things 588 with sw.add_node('another'): 589 sw.property_u32('reg', 3) 590 591 # Make sure we can read from the tree too 592 node = sw.path_offset('/subnode@1') 593 self.assertEqual(b'subnode1\0', sw.getprop(node, 'compatible')) 594 595 # Make sure we did at least two resizes 596 self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2) 597 598 599class PyLibfdtRoTests(unittest.TestCase): 600 """Test class for read-only pylibfdt access functions 601 602 This just tests a few simple cases. Most of the tests are in 603 PyLibfdtBasicTests. 604 605 Properties: 606 fdt: Device tree file used for testing 607 """ 608 609 def setUp(self): 610 """Read in the device tree we use for testing""" 611 with open('test_tree1.dtb', mode='rb') as f: 612 self.fdt = libfdt.FdtRo(f.read()) 613 614 def testAccess(self): 615 """Basic sanity check for the FdtRo class""" 616 node = self.fdt.path_offset('/subnode@1') 617 self.assertEqual(b'subnode1\0', 618 self.fdt.getprop(node, 'compatible')) 619 node = self.fdt.first_subnode(node) 620 self.assertEqual(b'this is a placeholder string\0string2\0', 621 self.fdt.getprop(node, 'placeholder')) 622 623 624if __name__ == "__main__": 625 unittest.main() 626