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 <sjg@chromium.org> 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 358 with self.assertRaises(FdtException) as e: 359 self.fdt.get_path(-1) 360 self.assertEqual(e.exception.err, -libfdt.BADOFFSET) 361 362 self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,))) 363 364 def testParentOffset(self): 365 """Test for the parent_offset() method""" 366 self.assertEqual(-libfdt.NOTFOUND, 367 self.fdt.parent_offset(0, QUIET_NOTFOUND)) 368 with self.assertRaises(FdtException) as e: 369 self.fdt.parent_offset(0) 370 self.assertEqual(e.exception.err, -libfdt.NOTFOUND) 371 372 node1 = self.fdt.path_offset('/subnode@2') 373 self.assertEqual(0, self.fdt.parent_offset(node1)) 374 node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') 375 self.assertEqual(node1, self.fdt.parent_offset(node2)) 376 377 def testNodeOffsetByPhandle(self): 378 """Test for the node_offset_by_phandle() method""" 379 self.assertEqual(-libfdt.NOTFOUND, 380 self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND)) 381 node1 = self.fdt.path_offset('/subnode@2') 382 self.assertEqual(node1, self.fdt.node_offset_by_phandle(0x2000)) 383 node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') 384 self.assertEqual(node2, self.fdt.node_offset_by_phandle(0x2001)) 385 386 def get_prop(self, name): 387 return self.fdt2.getprop(0, name) 388 389 def testGetIntProperties(self): 390 """Test that we can access properties as integers""" 391 self.assertEqual(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) 392 self.assertEqual(123, self.get_prop("prop-uint32").as_uint32()) 393 self.assertEqual(-2, self.get_prop("prop-int32").as_int32()) 394 self.assertEqual(9223372036854775807, 395 self.get_prop("prop-uint64").as_uint64()) 396 self.assertEqual(-2, self.get_prop("prop-int64").as_int64()) 397 398 def testGetIntListProperties(self): 399 """Test that we can access properties as integer lists""" 400 self.assertEqual([128, -16, -2], 401 self.get_prop("prop-int32-array").as_int32_list()) 402 self.assertEqual([0x1, 0x98765432, 0xdeadbeef], 403 self.get_prop("prop-uint32-array").as_uint32_list()) 404 self.assertEqual([0x100000000, -2], 405 self.get_prop("prop-int64-array").as_int64_list()) 406 self.assertEqual([0x100000000, 0x1], 407 self.get_prop("prop-uint64-array").as_uint64_list()) 408 409 def testGetStringlistProperties(self): 410 """Test that we can access properties as string list""" 411 node = self.fdt.path_offset('/subnode@1/subsubnode') 412 self.assertEqual(["subsubnode1", "subsubnode"], 413 self.fdt.getprop(node, "compatible").as_stringlist()) 414 self.assertEqual(["this is a placeholder string", "string2"], 415 self.fdt.getprop(node, "placeholder").as_stringlist()) 416 417 def testReserveMap(self): 418 """Test that we can access the memory reserve map""" 419 self.assertEqual(2, self.fdt.num_mem_rsv()) 420 self.assertEqual([ 0xdeadbeef00000000, 0x100000], 421 self.fdt.get_mem_rsv(0)) 422 self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1)) 423 424 def testEmpty(self): 425 """Test that we can create an empty tree""" 426 self.assertEqual(-libfdt.NOSPACE, 427 Fdt.create_empty_tree(1, (libfdt.NOSPACE,))) 428 fdt = Fdt.create_empty_tree(128) 429 self.assertEqual(128, fdt.totalsize()) 430 431 def testOpenInto(self): 432 """Test that we can resize a tree""" 433 fdt = Fdt.create_empty_tree(128) 434 self.assertEqual(128, fdt.totalsize()) 435 fdt.resize(256) 436 self.assertEqual(256, fdt.totalsize()) 437 fdt.pack() 438 self.assertTrue(fdt.totalsize() < 128) 439 440 def testSetProp(self): 441 """Test that we can update and create properties""" 442 node = self.fdt.path_offset('/subnode@1') 443 self.fdt.setprop(node, 'compatible', TEST_BYTES_1) 444 self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'compatible')) 445 446 # Check that this property is missing, and that we don't have space to 447 # add it 448 self.assertEqual(-libfdt.NOTFOUND, 449 self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) 450 self.assertEqual(-libfdt.NOSPACE, 451 self.fdt.setprop(node, 'missing', TEST_BYTES_1, 452 quiet=(libfdt.NOSPACE,))) 453 454 # Expand the device tree so we now have room 455 self.fdt.resize(self.fdt.totalsize() + 50) 456 self.fdt.setprop(node, 'missing', TEST_BYTES_1) 457 self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'missing')) 458 459 def testSetPropU32(self): 460 """Test that we can update and create integer properties""" 461 node = 0 462 prop = 'prop-int' 463 self.fdt.setprop_u32(node, prop, TEST_VALUE_1) 464 self.assertEqual(struct.pack('>I', TEST_VALUE_1), 465 self.fdt.getprop(node, prop)) 466 467 def testSetPropU64(self): 468 """Test that we can update and create integer properties""" 469 node = 0 470 prop = 'prop-int64' 471 self.fdt.setprop_u64(node, prop, TEST_VALUE64_1) 472 self.assertEqual(struct.pack('>Q', TEST_VALUE64_1), 473 self.fdt.getprop(node, prop)) 474 475 def testSetPropStr(self): 476 """Test that we can set a property to a particular string""" 477 node = 0 478 prop = 'prop-str' 479 self.assertEqual(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) 480 self.fdt.setprop_str(node, prop, TEST_STRING_2) 481 self.assertEqual(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) 482 with self.assertRaises(ValueError) as e: 483 self.fdt.getprop(node, 'prop-int').as_str() 484 self.assertIn('lacks nul termination', str(e.exception)) 485 486 node2 = self.fdt.path_offset('/subnode@1/subsubnode') 487 with self.assertRaises(ValueError) as e: 488 self.fdt.getprop(node2, 'compatible').as_str() 489 self.assertIn('embedded nul', str(e.exception)) 490 491 # Expand the device tree so we now have room 492 self.fdt.resize(self.fdt.totalsize() + 50) 493 prop = 'prop-unicode' 494 self.fdt.setprop_str(node, prop, TEST_STRING_3) 495 self.assertEqual(TEST_STRING_3, 496 self.fdt.getprop(node, prop).as_str()) 497 498 def testSetName(self): 499 """Test that we can update a node name""" 500 node = self.fdt.path_offset('/subnode@1') 501 old_val = self.fdt.get_name(node) 502 self.fdt.set_name(node, 'test') 503 self.assertEqual('test', self.fdt.get_name(node)) 504 505 with self.assertRaises(ValueError) as e: 506 self.fdt.set_name(node, 'some\0name') 507 self.assertIn('embedded nul', str(e.exception)) 508 509 with self.assertRaises(ValueError) as e: 510 self.fdt.set_name(node, 'name\0') 511 self.assertIn('embedded nul', str(e.exception)) 512 513 def testAddDeleteNodes(self): 514 """Test that we can add and delete nodes""" 515 node_name = '/subnode@1' 516 self.assertEqual(self.GetSubnodes(node_name), ['subsubnode', 'ss1']) 517 node = self.fdt.path_offset('%s/subsubnode' % node_name) 518 self.assertEqual(self.fdt.del_node(node, 'subsubnode'), 0) 519 self.assertEqual(self.GetSubnodes(node_name), ['ss1']) 520 521 node = self.fdt.path_offset(node_name) 522 offset = self.fdt.add_subnode(node, 'more') 523 self.assertTrue(offset > 0) 524 self.assertEqual(self.GetSubnodes(node_name), ['more', 'ss1']) 525 526 527class PyLibfdtSwTests(unittest.TestCase): 528 """Test class for pylibfdt sequential-write DT creation 529 """ 530 def assertOk(self, err_code): 531 self.assertEqual(0, err_code) 532 533 def testCreate(self): 534 # First check the minimum size and also the FdtSw() constructor 535 with self.assertRaisesRegex(FdtException, get_err(libfdt.NOSPACE)): 536 self.assertEqual(-libfdt.NOSPACE, FdtSw(3)) 537 538 sw = FdtSw() 539 sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1) 540 sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2) 541 sw.finish_reservemap() 542 543 sw.begin_node('') 544 sw.property_string('compatible', 'test_tree1') 545 sw.property_u32('prop-int', TEST_VALUE_1) 546 547 sw.property_u32('prop-int', TEST_VALUE_1) 548 sw.property_u64('prop-int64', TEST_VALUE64_1) 549 sw.property_string('prop-str', TEST_STRING_1) 550 sw.property_u32('#address-cells', 1) 551 sw.property_u32('#size-cells', 0) 552 553 sw.begin_node('subnode@1') 554 sw.property_string('compatible', 'subnode1') 555 sw.property_u32('reg', 1) 556 sw.property_cell('prop-int', TEST_VALUE_1) 557 sw.property('data', b'\x00data\x01') 558 sw.begin_node('subsubnode') 559 sw.property('compatible', b'subsubnode1\0subsubnode') 560 sw.property_cell('prop-int', TEST_VALUE_1) 561 sw.end_node() 562 sw.begin_node('ss1') 563 sw.end_node() 564 sw.end_node() 565 566 for i in range(2, 11): 567 with sw.add_node('subnode@%d' % i): 568 sw.property_u32('reg', 2) 569 sw.property_cell('linux,phandle', PHANDLE_1) 570 sw.property_cell('prop-int', TEST_VALUE_2) 571 sw.property_u32('#address-cells', 1) 572 sw.property_u32('#size-cells', 0) 573 with sw.add_node('subsubnode@0'): 574 sw.property_u32('reg', 0) 575 sw.property_cell('phandle', PHANDLE_2) 576 sw.property('compatible', b'subsubnode2\0subsubnode') 577 sw.property_cell('prop-int', TEST_VALUE_2) 578 with sw.add_node('ss2'): 579 pass 580 sw.end_node() 581 582 fdt = sw.as_fdt() 583 self.assertEqual(2, fdt.num_mem_rsv()) 584 self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0)) 585 586 # Make sure we can add a few more things 587 with sw.add_node('another'): 588 sw.property_u32('reg', 3) 589 590 # Make sure we can read from the tree too 591 node = sw.path_offset('/subnode@1') 592 self.assertEqual(b'subnode1\0', sw.getprop(node, 'compatible')) 593 594 # Make sure we did at least two resizes 595 self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2) 596 597 598class PyLibfdtRoTests(unittest.TestCase): 599 """Test class for read-only pylibfdt access functions 600 601 This just tests a few simple cases. Most of the tests are in 602 PyLibfdtBasicTests. 603 604 Properties: 605 fdt: Device tree file used for testing 606 """ 607 608 def setUp(self): 609 """Read in the device tree we use for testing""" 610 with open('test_tree1.dtb', mode='rb') as f: 611 self.fdt = libfdt.FdtRo(f.read()) 612 613 def testAccess(self): 614 """Basic sanity check for the FdtRo class""" 615 node = self.fdt.path_offset('/subnode@1') 616 self.assertEqual(b'subnode1\0', 617 self.fdt.getprop(node, 'compatible')) 618 node = self.fdt.first_subnode(node) 619 self.assertEqual(b'this is a placeholder string\0string2\0', 620 self.fdt.getprop(node, 'placeholder')) 621 622 623if __name__ == "__main__": 624 unittest.main() 625