1/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ 2/* 3 * pylibfdt - Flat Device Tree manipulation in Python 4 * Copyright (C) 2017 Google, Inc. 5 * Written by Simon Glass <sjg@chromium.org> 6 */ 7 8%module libfdt 9 10%include <stdint.i> 11 12%{ 13#define SWIG_FILE_WITH_INIT 14#include "libfdt.h" 15 16/* 17 * We rename this function here to avoid problems with swig, since we also have 18 * a struct called fdt_property. That struct causes swig to create a class in 19 * libfdt.py called fdt_property(), which confuses things. 20 */ 21static int _fdt_property(void *fdt, const char *name, const char *val, int len) 22{ 23 return fdt_property(fdt, name, val, len); 24} 25 26%} 27 28%pythoncode %{ 29 30import struct 31 32# Error codes, corresponding to FDT_ERR_... in libfdt.h 33(NOTFOUND, 34 EXISTS, 35 NOSPACE, 36 BADOFFSET, 37 BADPATH, 38 BADPHANDLE, 39 BADSTATE, 40 TRUNCATED, 41 BADMAGIC, 42 BADVERSION, 43 BADSTRUCTURE, 44 BADLAYOUT, 45 INTERNAL, 46 BADNCELLS, 47 BADVALUE, 48 BADOVERLAY, 49 NOPHANDLES) = QUIET_ALL = range(1, 18) 50# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions 51# altogether. All # functions passed this value will return an error instead 52# of raising an exception. 53 54# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors, 55# instead of raising an exception. 56QUIET_NOTFOUND = (NOTFOUND,) 57 58 59class FdtException(Exception): 60 """An exception caused by an error such as one of the codes above""" 61 def __init__(self, err): 62 self.err = err 63 64 def __str__(self): 65 return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err)) 66 67def strerror(fdt_err): 68 """Get the string for an error number 69 70 Args: 71 fdt_err: Error number (-ve) 72 73 Returns: 74 String containing the associated error 75 """ 76 return fdt_strerror(fdt_err) 77 78def check_err(val, quiet=()): 79 """Raise an error if the return value is -ve 80 81 This is used to check for errors returned by libfdt C functions. 82 83 Args: 84 val: Return value from a libfdt function 85 quiet: Errors to ignore (empty to raise on all errors) 86 87 Returns: 88 val if val >= 0 89 90 Raises 91 FdtException if val < 0 92 """ 93 if val < 0: 94 if -val not in quiet: 95 raise FdtException(val) 96 return val 97 98def check_err_null(val, quiet=()): 99 """Raise an error if the return value is NULL 100 101 This is used to check for a NULL return value from certain libfdt C 102 functions 103 104 Args: 105 val: Return value from a libfdt function 106 quiet: Errors to ignore (empty to raise on all errors) 107 108 Returns: 109 val if val is a list, None if not 110 111 Raises 112 FdtException if val indicates an error was reported and the error 113 is not in @quiet. 114 """ 115 # Normally a list is returned which contains the data and its length. 116 # If we get just an integer error code, it means the function failed. 117 if not isinstance(val, list): 118 if -val not in quiet: 119 raise FdtException(val) 120 return val 121 122 123class Fdt: 124 """Device tree class, supporting all operations 125 126 The Fdt object is created is created from a device tree binary file, 127 e.g. with something like: 128 129 fdt = Fdt(open("filename.dtb").read()) 130 131 Operations can then be performed using the methods in this class. Each 132 method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). 133 134 All methods raise an FdtException if an error occurs. To avoid this 135 behaviour a 'quiet' parameter is provided for some functions. This 136 defaults to empty, but you can pass a list of errors that you expect. 137 If one of these errors occurs, the function will return an error number 138 (e.g. -NOTFOUND). 139 """ 140 def __init__(self, data): 141 self._fdt = bytearray(data) 142 check_err(fdt_check_header(self._fdt)); 143 144 def as_bytearray(self): 145 """Get the device tree contents as a bytearray 146 147 This can be passed directly to libfdt functions that access a 148 const void * for the device tree. 149 150 Returns: 151 bytearray containing the device tree 152 """ 153 return bytearray(self._fdt) 154 155 def next_node(self, nodeoffset, depth, quiet=()): 156 """Find the next subnode 157 158 Args: 159 nodeoffset: Node offset of previous node 160 depth: On input, the depth of the node at nodeoffset. On output, the 161 depth of the returned node 162 quiet: Errors to ignore (empty to raise on all errors) 163 164 Returns: 165 The offset of the next node, if any 166 167 Raises: 168 FdtException if no more nodes found or other error occurs 169 """ 170 return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet) 171 172 def first_subnode(self, nodeoffset, quiet=()): 173 """Find the first subnode of a parent node 174 175 Args: 176 nodeoffset: Node offset of parent node 177 quiet: Errors to ignore (empty to raise on all errors) 178 179 Returns: 180 The offset of the first subnode, if any 181 182 Raises: 183 FdtException if no subnodes found or other error occurs 184 """ 185 return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) 186 187 def next_subnode(self, nodeoffset, quiet=()): 188 """Find the next subnode 189 190 Args: 191 nodeoffset: Node offset of previous subnode 192 quiet: Errors to ignore (empty to raise on all errors) 193 194 Returns: 195 The offset of the next subnode, if any 196 197 Raises: 198 FdtException if no more subnodes found or other error occurs 199 """ 200 return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) 201 202 def magic(self): 203 """Return the magic word from the header 204 205 Returns: 206 Magic word 207 """ 208 return fdt_magic(self._fdt) & 0xffffffff 209 210 def totalsize(self): 211 """Return the total size of the device tree 212 213 Returns: 214 Total tree size in bytes 215 """ 216 return check_err(fdt_totalsize(self._fdt)) 217 218 def off_dt_struct(self): 219 """Return the start of the device-tree struct area 220 221 Returns: 222 Start offset of struct area 223 """ 224 return check_err(fdt_off_dt_struct(self._fdt)) 225 226 def off_dt_strings(self): 227 """Return the start of the device-tree string area 228 229 Returns: 230 Start offset of string area 231 """ 232 return check_err(fdt_off_dt_strings(self._fdt)) 233 234 def off_mem_rsvmap(self): 235 """Return the start of the memory reserve map 236 237 Returns: 238 Start offset of memory reserve map 239 """ 240 return check_err(fdt_off_mem_rsvmap(self._fdt)) 241 242 def version(self): 243 """Return the version of the device tree 244 245 Returns: 246 Version number of the device tree 247 """ 248 return check_err(fdt_version(self._fdt)) 249 250 def last_comp_version(self): 251 """Return the last compatible version of the device tree 252 253 Returns: 254 Last compatible version number of the device tree 255 """ 256 return check_err(fdt_last_comp_version(self._fdt)) 257 258 def boot_cpuid_phys(self): 259 """Return the physical boot CPU ID 260 261 Returns: 262 Physical boot CPU ID 263 """ 264 return check_err(fdt_boot_cpuid_phys(self._fdt)) 265 266 def size_dt_strings(self): 267 """Return the start of the device-tree string area 268 269 Returns: 270 Start offset of string area 271 """ 272 return check_err(fdt_size_dt_strings(self._fdt)) 273 274 def size_dt_struct(self): 275 """Return the start of the device-tree struct area 276 277 Returns: 278 Start offset of struct area 279 """ 280 return check_err(fdt_size_dt_struct(self._fdt)) 281 282 def num_mem_rsv(self, quiet=()): 283 """Return the number of memory reserve-map records 284 285 Returns: 286 Number of memory reserve-map records 287 """ 288 return check_err(fdt_num_mem_rsv(self._fdt), quiet) 289 290 def get_mem_rsv(self, index, quiet=()): 291 """Return the indexed memory reserve-map record 292 293 Args: 294 index: Record to return (0=first) 295 296 Returns: 297 Number of memory reserve-map records 298 """ 299 return check_err(fdt_get_mem_rsv(self._fdt, index), quiet) 300 301 def subnode_offset(self, parentoffset, name, quiet=()): 302 """Get the offset of a named subnode 303 304 Args: 305 parentoffset: Offset of the parent node to check 306 name: Name of the required subnode, e.g. 'subnode@1' 307 quiet: Errors to ignore (empty to raise on all errors) 308 309 Returns: 310 The node offset of the found node, if any 311 312 Raises 313 FdtException if there is no node with that name, or other error 314 """ 315 return check_err(fdt_subnode_offset(self._fdt, parentoffset, name), 316 quiet) 317 318 def path_offset(self, path, quiet=()): 319 """Get the offset for a given path 320 321 Args: 322 path: Path to the required node, e.g. '/node@3/subnode@1' 323 quiet: Errors to ignore (empty to raise on all errors) 324 325 Returns: 326 Node offset 327 328 Raises 329 FdtException if the path is not valid or not found 330 """ 331 return check_err(fdt_path_offset(self._fdt, path), quiet) 332 333 def get_name(self, nodeoffset): 334 """Get the name of a node 335 336 Args: 337 nodeoffset: Offset of node to check 338 339 Returns: 340 Node name 341 342 Raises: 343 FdtException on error (e.g. nodeoffset is invalid) 344 """ 345 return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] 346 347 def first_property_offset(self, nodeoffset, quiet=()): 348 """Get the offset of the first property in a node offset 349 350 Args: 351 nodeoffset: Offset to the node to check 352 quiet: Errors to ignore (empty to raise on all errors) 353 354 Returns: 355 Offset of the first property 356 357 Raises 358 FdtException if the associated node has no properties, or some 359 other error occurred 360 """ 361 return check_err(fdt_first_property_offset(self._fdt, nodeoffset), 362 quiet) 363 364 def next_property_offset(self, prop_offset, quiet=()): 365 """Get the next property in a node 366 367 Args: 368 prop_offset: Offset of the previous property 369 quiet: Errors to ignore (empty to raise on all errors) 370 371 Returns: 372 Offset of the next property 373 374 Raises: 375 FdtException if the associated node has no more properties, or 376 some other error occurred 377 """ 378 return check_err(fdt_next_property_offset(self._fdt, prop_offset), 379 quiet) 380 381 def get_property_by_offset(self, prop_offset, quiet=()): 382 """Obtains a property that can be examined 383 384 Args: 385 prop_offset: Offset of property (e.g. from first_property_offset()) 386 quiet: Errors to ignore (empty to raise on all errors) 387 388 Returns: 389 Property object, or None if not found 390 391 Raises: 392 FdtException on error (e.g. invalid prop_offset or device 393 tree format) 394 """ 395 pdata = check_err_null( 396 fdt_get_property_by_offset(self._fdt, prop_offset), quiet) 397 if isinstance(pdata, (int)): 398 return pdata 399 return Property(pdata[0], pdata[1]) 400 401 @staticmethod 402 def create_empty_tree(size, quiet=()): 403 """Create an empty device tree ready for use 404 405 Args: 406 size: Size of device tree in bytes 407 408 Returns: 409 Fdt object containing the device tree 410 """ 411 data = bytearray(size) 412 err = check_err(fdt_create_empty_tree(data, size), quiet) 413 if err: 414 return err 415 return Fdt(data) 416 417 def open_into(self, size, quiet=()): 418 """Move the device tree into a larger or smaller space 419 420 This creates a new device tree of size @size and moves the existing 421 device tree contents over to that. It can be used to create more space 422 in a device tree. 423 424 Args: 425 size: Required new size of device tree in bytes 426 """ 427 fdt = bytearray(size) 428 fdt[:len(self._fdt)] = self._fdt 429 err = check_err(fdt_open_into(self._fdt, fdt, size), quiet) 430 if err: 431 return err 432 self._fdt = fdt 433 434 def pack(self, quiet=()): 435 """Pack the device tree to remove unused space 436 437 This adjusts the tree in place. 438 439 Args: 440 quiet: Errors to ignore (empty to raise on all errors) 441 442 Raises: 443 FdtException if any error occurs 444 """ 445 err = check_err(fdt_pack(self._fdt), quiet) 446 if err: 447 return err 448 del self._fdt[self.totalsize():] 449 return err 450 451 def getprop(self, nodeoffset, prop_name, quiet=()): 452 """Get a property from a node 453 454 Args: 455 nodeoffset: Node offset containing property to get 456 prop_name: Name of property to get 457 quiet: Errors to ignore (empty to raise on all errors) 458 459 Returns: 460 Value of property as a string, or -ve error number 461 462 Raises: 463 FdtError if any error occurs (e.g. the property is not found) 464 """ 465 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), 466 quiet) 467 if isinstance(pdata, (int)): 468 return pdata 469 return str(pdata[0]) 470 471 def getprop_obj(self, nodeoffset, prop_name, quiet=()): 472 """Get a property from a node as a Property object 473 474 Args: 475 nodeoffset: Node offset containing property to get 476 prop_name: Name of property to get 477 quiet: Errors to ignore (empty to raise on all errors) 478 479 Returns: 480 Property object, or None if not found 481 482 Raises: 483 FdtError if any error occurs (e.g. the property is not found) 484 """ 485 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), 486 quiet) 487 if isinstance(pdata, (int)): 488 return None 489 return Property(prop_name, bytearray(pdata[0])) 490 491 def get_phandle(self, nodeoffset): 492 """Get the phandle of a node 493 494 Args: 495 nodeoffset: Node offset to check 496 497 Returns: 498 phandle of node, or 0 if the node has no phandle or another error 499 occurs 500 """ 501 return fdt_get_phandle(self._fdt, nodeoffset) 502 503 def parent_offset(self, nodeoffset, quiet=()): 504 """Get the offset of a node's parent 505 506 Args: 507 nodeoffset: Node offset to check 508 quiet: Errors to ignore (empty to raise on all errors) 509 510 Returns: 511 The offset of the parent node, if any 512 513 Raises: 514 FdtException if no parent found or other error occurs 515 """ 516 return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) 517 518 def set_name(self, nodeoffset, name, quiet=()): 519 """Set the name of a node 520 521 Args: 522 nodeoffset: Node offset of node to update 523 name: New node name 524 525 Returns: 526 Error code, or 0 if OK 527 528 Raises: 529 FdtException if no parent found or other error occurs 530 """ 531 return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet) 532 533 def setprop(self, nodeoffset, prop_name, val, quiet=()): 534 """Set the value of a property 535 536 Args: 537 nodeoffset: Node offset containing the property to create/update 538 prop_name: Name of property 539 val: Value to write (string or bytearray) 540 quiet: Errors to ignore (empty to raise on all errors) 541 542 Returns: 543 Error code, or 0 if OK 544 545 Raises: 546 FdtException if no parent found or other error occurs 547 """ 548 return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, 549 len(val)), quiet) 550 551 def setprop_u32(self, nodeoffset, prop_name, val, quiet=()): 552 """Set the value of a property 553 554 Args: 555 nodeoffset: Node offset containing the property to create/update 556 prop_name: Name of property 557 val: Value to write (integer) 558 quiet: Errors to ignore (empty to raise on all errors) 559 560 Returns: 561 Error code, or 0 if OK 562 563 Raises: 564 FdtException if no parent found or other error occurs 565 """ 566 return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val), 567 quiet) 568 569 def setprop_u64(self, nodeoffset, prop_name, val, quiet=()): 570 """Set the value of a property 571 572 Args: 573 nodeoffset: Node offset containing the property to create/update 574 prop_name: Name of property 575 val: Value to write (integer) 576 quiet: Errors to ignore (empty to raise on all errors) 577 578 Returns: 579 Error code, or 0 if OK 580 581 Raises: 582 FdtException if no parent found or other error occurs 583 """ 584 return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val), 585 quiet) 586 587 def setprop_str(self, nodeoffset, prop_name, val, quiet=()): 588 """Set the string value of a property 589 590 The property is set to the string, with a nul terminator added 591 592 Args: 593 nodeoffset: Node offset containing the property to create/update 594 prop_name: Name of property 595 val: Value to write (string without nul terminator) 596 quiet: Errors to ignore (empty to raise on all errors) 597 598 Returns: 599 Error code, or 0 if OK 600 601 Raises: 602 FdtException if no parent found or other error occurs 603 """ 604 val += '\0' 605 return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, 606 val, len(val)), quiet) 607 608 def delprop(self, nodeoffset, prop_name): 609 """Delete a property from a node 610 611 Args: 612 nodeoffset: Node offset containing property to delete 613 prop_name: Name of property to delete 614 615 Raises: 616 FdtError if the property does not exist, or another error occurs 617 """ 618 return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) 619 620 def node_offset_by_phandle(self, phandle, quiet=()): 621 """Get the offset of a node with the given phandle 622 623 Args: 624 phandle: Phandle to search for 625 quiet: Errors to ignore (empty to raise on all errors) 626 627 Returns: 628 The offset of node with that phandle, if any 629 630 Raises: 631 FdtException if no node found or other error occurs 632 """ 633 return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) 634 635 636class Property(bytearray): 637 """Holds a device tree property name and value. 638 639 This holds a copy of a property taken from the device tree. It does not 640 reference the device tree, so if anything changes in the device tree, 641 a Property object will remain valid. 642 643 Properties: 644 name: Property name 645 value: Property value as a bytearray 646 """ 647 def __init__(self, name, value): 648 bytearray.__init__(self, value) 649 self.name = name 650 651 def as_cell(self, fmt): 652 return struct.unpack('>' + fmt, self)[0] 653 654 def as_uint32(self): 655 return self.as_cell('L') 656 657 def as_int32(self): 658 return self.as_cell('l') 659 660 def as_uint64(self): 661 return self.as_cell('Q') 662 663 def as_int64(self): 664 return self.as_cell('q') 665 666 def as_str(self): 667 return self[:-1] 668 669 670class FdtSw(object): 671 """Software interface to create a device tree from scratch 672 673 The methods in this class work by adding to an existing 'partial' device 674 tree buffer of a fixed size created by instantiating this class. When the 675 tree is complete, call finish() to complete the device tree so that it can 676 be used. 677 678 Similarly with nodes, a new node is started with begin_node() and finished 679 with end_node(). 680 681 The context manager functions can be used to make this a bit easier: 682 683 # First create the device tree with a node and property: 684 with FdtSw(small_size) as sw: 685 with sw.AddNode('node'): 686 sw.property_u32('reg', 2) 687 fdt = sw.AsFdt() 688 689 # Now we can use it as a real device tree 690 fdt.setprop_u32(0, 'reg', 3) 691 """ 692 def __init__(self, size, quiet=()): 693 fdtrw = bytearray(size) 694 err = check_err(fdt_create(fdtrw, size)) 695 if err: 696 return err 697 self._fdtrw = fdtrw 698 699 def __enter__(self): 700 """Contact manager to use to create a device tree via software""" 701 return self 702 703 def __exit__(self, type, value, traceback): 704 check_err(fdt_finish(self._fdtrw)) 705 706 def AsFdt(self): 707 """Convert a FdtSw into an Fdt so it can be accessed as normal 708 709 Note that finish() must be called before this function will work. If 710 you are using the context manager (see 'with' code in the FdtSw class 711 comment) then this will happen automatically. 712 713 Returns: 714 Fdt object allowing access to the newly created device tree 715 """ 716 return Fdt(self._fdtrw) 717 718 def resize(self, size, quiet=()): 719 """Resize the buffer to accommodate a larger tree 720 721 Args: 722 size: New size of tree 723 quiet: Errors to ignore (empty to raise on all errors) 724 725 Raises: 726 FdtException if no node found or other error occurs 727 """ 728 fdt = bytearray(size) 729 fdt[:len(self._fdtrw)] = self._fdtrw 730 err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet) 731 if err: 732 return err 733 self._fdtrw = fdt 734 735 def add_reservemap_entry(self, addr, size, quiet=()): 736 """Add a new memory reserve map entry 737 738 Once finished adding, you must call finish_reservemap(). 739 740 Args: 741 addr: 64-bit start address 742 size: 64-bit size 743 quiet: Errors to ignore (empty to raise on all errors) 744 745 Raises: 746 FdtException if no node found or other error occurs 747 """ 748 return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size), 749 quiet) 750 751 def finish_reservemap(self, quiet=()): 752 """Indicate that there are no more reserve map entries to add 753 754 Args: 755 quiet: Errors to ignore (empty to raise on all errors) 756 757 Raises: 758 FdtException if no node found or other error occurs 759 """ 760 return check_err(fdt_finish_reservemap(self._fdtrw), quiet) 761 762 def begin_node(self, name, quiet=()): 763 """Begin a new node 764 765 Use this before adding properties to the node. Then call end_node() to 766 finish it. You can also use the context manager as shown in the FdtSw 767 class comment. 768 769 Args: 770 name: Name of node to begin 771 quiet: Errors to ignore (empty to raise on all errors) 772 773 Raises: 774 FdtException if no node found or other error occurs 775 """ 776 return check_err(fdt_begin_node(self._fdtrw, name), quiet) 777 778 def property_string(self, name, string, quiet=()): 779 """Add a property with a string value 780 781 The string will be nul-terminated when written to the device tree 782 783 Args: 784 name: Name of property to add 785 string: String value of property 786 quiet: Errors to ignore (empty to raise on all errors) 787 788 Raises: 789 FdtException if no node found or other error occurs 790 """ 791 return check_err(fdt_property_string(self._fdtrw, name, string), quiet) 792 793 def property_u32(self, name, val, quiet=()): 794 """Add a property with a 32-bit value 795 796 Write a single-cell value to the device tree 797 798 Args: 799 name: Name of property to add 800 val: Value of property 801 quiet: Errors to ignore (empty to raise on all errors) 802 803 Raises: 804 FdtException if no node found or other error occurs 805 """ 806 return check_err(fdt_property_u32(self._fdtrw, name, val), quiet) 807 808 def property_u64(self, name, val, quiet=()): 809 """Add a property with a 64-bit value 810 811 Write a double-cell value to the device tree in big-endian format 812 813 Args: 814 name: Name of property to add 815 val: Value of property 816 quiet: Errors to ignore (empty to raise on all errors) 817 818 Raises: 819 FdtException if no node found or other error occurs 820 """ 821 return check_err(fdt_property_u64(self._fdtrw, name, val), quiet) 822 823 def property_cell(self, name, val, quiet=()): 824 """Add a property with a single-cell value 825 826 Write a single-cell value to the device tree 827 828 Args: 829 name: Name of property to add 830 val: Value of property 831 quiet: Errors to ignore (empty to raise on all errors) 832 833 Raises: 834 FdtException if no node found or other error occurs 835 """ 836 return check_err(fdt_property_cell(self._fdtrw, name, val), quiet) 837 838 def property(self, name, val, quiet=()): 839 """Add a property 840 841 Write a new property with the given value to the device tree. The value 842 is taken as is and is not nul-terminated 843 844 Args: 845 name: Name of property to add 846 val: Value of property 847 quiet: Errors to ignore (empty to raise on all errors) 848 849 Raises: 850 FdtException if no node found or other error occurs 851 """ 852 return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet) 853 854 def end_node(self, quiet=()): 855 """End a node 856 857 Use this after adding properties to a node to close it off. You can also 858 use the context manager as shown in the FdtSw class comment. 859 860 Args: 861 quiet: Errors to ignore (empty to raise on all errors) 862 863 Raises: 864 FdtException if no node found or other error occurs 865 """ 866 return check_err(fdt_end_node(self._fdtrw), quiet) 867 868 def finish(self, quiet=()): 869 """Finish writing the device tree 870 871 This closes off the device tree ready for use 872 873 Args: 874 quiet: Errors to ignore (empty to raise on all errors) 875 876 Raises: 877 FdtException if no node found or other error occurs 878 """ 879 return check_err(fdt_finish(self._fdtrw), quiet) 880 881 def AddNode(self, name): 882 """Create a new context for adding a node 883 884 When used in a 'with' clause this starts a new node and finishes it 885 afterward. 886 887 Args: 888 name: Name of node to add 889 """ 890 return NodeAdder(self._fdtrw, name) 891 892 893class NodeAdder(): 894 """Class to provide a node context 895 896 This allows you to add nodes in a more natural way: 897 898 with fdtsw.AddNode('name'): 899 fdtsw.property_string('test', 'value') 900 901 The node is automatically completed with a call to end_node() when the 902 context exits. 903 """ 904 def __init__(self, fdt, name): 905 self._fdt = fdt 906 self._name = name 907 908 def __enter__(self): 909 check_err(fdt_begin_node(self._fdt, self._name)) 910 911 def __exit__(self, type, value, traceback): 912 check_err(fdt_end_node(self._fdt)) 913%} 914 915%rename(fdt_property) fdt_property_func; 916 917typedef int fdt32_t; 918 919%include "libfdt/fdt.h" 920 921%include "typemaps.i" 922 923/* Most functions don't change the device tree, so use a const void * */ 924%typemap(in) (const void *)(const void *fdt) { 925 if (!PyByteArray_Check($input)) { 926 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" 927 "', argument " "$argnum"" of type '" "$type""'"); 928 } 929 $1 = (void *)PyByteArray_AsString($input); 930 fdt = $1; 931 fdt = fdt; /* avoid unused variable warning */ 932} 933 934/* Some functions do change the device tree, so use void * */ 935%typemap(in) (void *)(const void *fdt) { 936 if (!PyByteArray_Check($input)) { 937 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" 938 "', argument " "$argnum"" of type '" "$type""'"); 939 } 940 $1 = PyByteArray_AsString($input); 941 fdt = $1; 942 fdt = fdt; /* avoid unused variable warning */ 943} 944 945/* typemap used for fdt_get_property_by_offset() */ 946%typemap(out) (struct fdt_property *) { 947 PyObject *buff; 948 949 if ($1) { 950 resultobj = PyString_FromString( 951 fdt_string(fdt1, fdt32_to_cpu($1->nameoff))); 952 buff = PyByteArray_FromStringAndSize( 953 (const char *)($1 + 1), fdt32_to_cpu($1->len)); 954 resultobj = SWIG_Python_AppendOutput(resultobj, buff); 955 } 956} 957 958%apply int *OUTPUT { int *lenp }; 959 960/* typemap used for fdt_getprop() */ 961%typemap(out) (const void *) { 962 if (!$1) 963 $result = Py_None; 964 else 965 $result = Py_BuildValue("s#", $1, *arg4); 966} 967 968/* typemap used for fdt_setprop() */ 969%typemap(in) (const void *val) { 970 $1 = PyString_AsString($input); /* char *str */ 971} 972 973/* typemap used for fdt_add_reservemap_entry() */ 974%typemap(in) uint64_t { 975 $1 = PyLong_AsUnsignedLong($input); 976} 977 978/* typemaps used for fdt_next_node() */ 979%typemap(in, numinputs=1) int *depth (int depth) { 980 depth = (int) PyInt_AsLong($input); 981 $1 = &depth; 982} 983 984%typemap(argout) int *depth { 985 PyObject *val = Py_BuildValue("i", *arg$argnum); 986 resultobj = SWIG_Python_AppendOutput(resultobj, val); 987} 988 989%apply int *depth { int *depth }; 990 991/* typemaps for fdt_get_mem_rsv */ 992%typemap(in, numinputs=0) uint64_t * (uint64_t temp) { 993 $1 = &temp; 994} 995 996%typemap(argout) uint64_t * { 997 PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); 998 if (!result) { 999 if (PyTuple_GET_SIZE(resultobj) == 0) 1000 resultobj = val; 1001 else 1002 resultobj = SWIG_Python_AppendOutput(resultobj, val); 1003 } 1004} 1005 1006/* We have both struct fdt_property and a function fdt_property() */ 1007%warnfilter(302) fdt_property; 1008 1009/* These are macros in the header so have to be redefined here */ 1010int fdt_magic(const void *fdt); 1011int fdt_totalsize(const void *fdt); 1012int fdt_off_dt_struct(const void *fdt); 1013int fdt_off_dt_strings(const void *fdt); 1014int fdt_off_mem_rsvmap(const void *fdt); 1015int fdt_version(const void *fdt); 1016int fdt_last_comp_version(const void *fdt); 1017int fdt_boot_cpuid_phys(const void *fdt); 1018int fdt_size_dt_strings(const void *fdt); 1019int fdt_size_dt_struct(const void *fdt); 1020int fdt_property_string(void *fdt, const char *name, const char *val); 1021int fdt_property_cell(void *fdt, const char *name, uint32_t val); 1022 1023/* 1024 * This function has a stub since the name fdt_property is used for both a 1025 * function and a struct, which confuses SWIG. 1026 */ 1027int _fdt_property(void *fdt, const char *name, const char *val, int len); 1028 1029%include <../libfdt/libfdt.h> 1030