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 def get_property(self, nodeoffset, prop_name, quiet=()): 402 """Obtains a property by name 403 404 Args: 405 nodeoffset: Offset to the node to check 406 prop_name: Name of property to get 407 quiet: Errors to ignore (empty to raise on all errors) 408 409 Returns: 410 Property object, or None if not found 411 412 Raises: 413 FdtException on error (e.g. invalid prop_offset or device 414 tree format) 415 """ 416 pdata = check_err_null( 417 fdt_get_property(self._fdt, nodeoffset, prop_name), quiet) 418 if isinstance(pdata, (int)): 419 return pdata 420 return Property(pdata[0], pdata[1]) 421 422 @staticmethod 423 def create_empty_tree(size, quiet=()): 424 """Create an empty device tree ready for use 425 426 Args: 427 size: Size of device tree in bytes 428 429 Returns: 430 Fdt object containing the device tree 431 """ 432 data = bytearray(size) 433 err = check_err(fdt_create_empty_tree(data, size), quiet) 434 if err: 435 return err 436 return Fdt(data) 437 438 def open_into(self, size, quiet=()): 439 """Move the device tree into a larger or smaller space 440 441 This creates a new device tree of size @size and moves the existing 442 device tree contents over to that. It can be used to create more space 443 in a device tree. 444 445 Args: 446 size: Required new size of device tree in bytes 447 """ 448 fdt = bytearray(size) 449 fdt[:len(self._fdt)] = self._fdt 450 err = check_err(fdt_open_into(self._fdt, fdt, size), quiet) 451 if err: 452 return err 453 self._fdt = fdt 454 455 def pack(self, quiet=()): 456 """Pack the device tree to remove unused space 457 458 This adjusts the tree in place. 459 460 Args: 461 quiet: Errors to ignore (empty to raise on all errors) 462 463 Raises: 464 FdtException if any error occurs 465 """ 466 err = check_err(fdt_pack(self._fdt), quiet) 467 if err: 468 return err 469 del self._fdt[self.totalsize():] 470 return err 471 472 def getprop(self, nodeoffset, prop_name, quiet=()): 473 """Get a property from a node 474 475 Args: 476 nodeoffset: Node offset containing property to get 477 prop_name: Name of property to get 478 quiet: Errors to ignore (empty to raise on all errors) 479 480 Returns: 481 Value of property as a string, or -ve error number 482 483 Raises: 484 FdtError if any error occurs (e.g. the property is not found) 485 """ 486 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), 487 quiet) 488 if isinstance(pdata, (int)): 489 return pdata 490 return str(pdata[0]) 491 492 def getprop_obj(self, nodeoffset, prop_name, quiet=()): 493 """Get a property from a node as a Property object 494 495 Args: 496 nodeoffset: Node offset containing property to get 497 prop_name: Name of property to get 498 quiet: Errors to ignore (empty to raise on all errors) 499 500 Returns: 501 Property object, or None if not found 502 503 Raises: 504 FdtError if any error occurs (e.g. the property is not found) 505 """ 506 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), 507 quiet) 508 if isinstance(pdata, (int)): 509 return None 510 return Property(prop_name, bytearray(pdata[0])) 511 512 def get_phandle(self, nodeoffset): 513 """Get the phandle of a node 514 515 Args: 516 nodeoffset: Node offset to check 517 518 Returns: 519 phandle of node, or 0 if the node has no phandle or another error 520 occurs 521 """ 522 return fdt_get_phandle(self._fdt, nodeoffset) 523 524 def parent_offset(self, nodeoffset, quiet=()): 525 """Get the offset of a node's parent 526 527 Args: 528 nodeoffset: Node offset to check 529 quiet: Errors to ignore (empty to raise on all errors) 530 531 Returns: 532 The offset of the parent node, if any 533 534 Raises: 535 FdtException if no parent found or other error occurs 536 """ 537 return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) 538 539 def set_name(self, nodeoffset, name, quiet=()): 540 """Set the name of a node 541 542 Args: 543 nodeoffset: Node offset of node to update 544 name: New node name 545 546 Returns: 547 Error code, or 0 if OK 548 549 Raises: 550 FdtException if no parent found or other error occurs 551 """ 552 return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet) 553 554 def setprop(self, nodeoffset, prop_name, val, quiet=()): 555 """Set the value of a property 556 557 Args: 558 nodeoffset: Node offset containing the property to create/update 559 prop_name: Name of property 560 val: Value to write (string or bytearray) 561 quiet: Errors to ignore (empty to raise on all errors) 562 563 Returns: 564 Error code, or 0 if OK 565 566 Raises: 567 FdtException if no parent found or other error occurs 568 """ 569 return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, 570 len(val)), quiet) 571 572 def setprop_u32(self, nodeoffset, prop_name, val, quiet=()): 573 """Set the value of a property 574 575 Args: 576 nodeoffset: Node offset containing the property to create/update 577 prop_name: Name of property 578 val: Value to write (integer) 579 quiet: Errors to ignore (empty to raise on all errors) 580 581 Returns: 582 Error code, or 0 if OK 583 584 Raises: 585 FdtException if no parent found or other error occurs 586 """ 587 return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val), 588 quiet) 589 590 def setprop_u64(self, nodeoffset, prop_name, val, quiet=()): 591 """Set the value of a property 592 593 Args: 594 nodeoffset: Node offset containing the property to create/update 595 prop_name: Name of property 596 val: Value to write (integer) 597 quiet: Errors to ignore (empty to raise on all errors) 598 599 Returns: 600 Error code, or 0 if OK 601 602 Raises: 603 FdtException if no parent found or other error occurs 604 """ 605 return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val), 606 quiet) 607 608 def setprop_str(self, nodeoffset, prop_name, val, quiet=()): 609 """Set the string value of a property 610 611 The property is set to the string, with a nul terminator added 612 613 Args: 614 nodeoffset: Node offset containing the property to create/update 615 prop_name: Name of property 616 val: Value to write (string without nul terminator) 617 quiet: Errors to ignore (empty to raise on all errors) 618 619 Returns: 620 Error code, or 0 if OK 621 622 Raises: 623 FdtException if no parent found or other error occurs 624 """ 625 val += '\0' 626 return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, 627 val, len(val)), quiet) 628 629 def delprop(self, nodeoffset, prop_name): 630 """Delete a property from a node 631 632 Args: 633 nodeoffset: Node offset containing property to delete 634 prop_name: Name of property to delete 635 636 Raises: 637 FdtError if the property does not exist, or another error occurs 638 """ 639 return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) 640 641 def node_offset_by_phandle(self, phandle, quiet=()): 642 """Get the offset of a node with the given phandle 643 644 Args: 645 phandle: Phandle to search for 646 quiet: Errors to ignore (empty to raise on all errors) 647 648 Returns: 649 The offset of node with that phandle, if any 650 651 Raises: 652 FdtException if no node found or other error occurs 653 """ 654 return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) 655 656 def del_node(self, nodeoffset): 657 """Delete a node 658 659 Args: 660 nodeoffset: Node offset containing property to delete 661 662 Raises: 663 FdtError if the node does not exist, or another error occurs 664 """ 665 return check_err(fdt_del_node(self._fdt, nodeoffset)) 666 667 668class Property(bytearray): 669 """Holds a device tree property name and value. 670 671 This holds a copy of a property taken from the device tree. It does not 672 reference the device tree, so if anything changes in the device tree, 673 a Property object will remain valid. 674 675 Properties: 676 name: Property name 677 value: Property value as a bytearray 678 """ 679 def __init__(self, name, value): 680 bytearray.__init__(self, value) 681 self.name = name 682 683 def as_cell(self, fmt): 684 return struct.unpack('>' + fmt, self)[0] 685 686 def as_uint32(self): 687 return self.as_cell('L') 688 689 def as_int32(self): 690 return self.as_cell('l') 691 692 def as_uint64(self): 693 return self.as_cell('Q') 694 695 def as_int64(self): 696 return self.as_cell('q') 697 698 def as_str(self): 699 return self[:-1] 700 701 702class FdtSw(object): 703 """Software interface to create a device tree from scratch 704 705 The methods in this class work by adding to an existing 'partial' device 706 tree buffer of a fixed size created by instantiating this class. When the 707 tree is complete, call finish() to complete the device tree so that it can 708 be used. 709 710 Similarly with nodes, a new node is started with begin_node() and finished 711 with end_node(). 712 713 The context manager functions can be used to make this a bit easier: 714 715 # First create the device tree with a node and property: 716 with FdtSw(small_size) as sw: 717 with sw.AddNode('node'): 718 sw.property_u32('reg', 2) 719 fdt = sw.AsFdt() 720 721 # Now we can use it as a real device tree 722 fdt.setprop_u32(0, 'reg', 3) 723 """ 724 def __init__(self, size, quiet=()): 725 fdtrw = bytearray(size) 726 err = check_err(fdt_create(fdtrw, size)) 727 if err: 728 return err 729 self._fdtrw = fdtrw 730 731 def __enter__(self): 732 """Contact manager to use to create a device tree via software""" 733 return self 734 735 def __exit__(self, type, value, traceback): 736 check_err(fdt_finish(self._fdtrw)) 737 738 def AsFdt(self): 739 """Convert a FdtSw into an Fdt so it can be accessed as normal 740 741 Note that finish() must be called before this function will work. If 742 you are using the context manager (see 'with' code in the FdtSw class 743 comment) then this will happen automatically. 744 745 Returns: 746 Fdt object allowing access to the newly created device tree 747 """ 748 return Fdt(self._fdtrw) 749 750 def resize(self, size, quiet=()): 751 """Resize the buffer to accommodate a larger tree 752 753 Args: 754 size: New size of tree 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 fdt = bytearray(size) 761 fdt[:len(self._fdtrw)] = self._fdtrw 762 err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet) 763 if err: 764 return err 765 self._fdtrw = fdt 766 767 def add_reservemap_entry(self, addr, size, quiet=()): 768 """Add a new memory reserve map entry 769 770 Once finished adding, you must call finish_reservemap(). 771 772 Args: 773 addr: 64-bit start address 774 size: 64-bit size 775 quiet: Errors to ignore (empty to raise on all errors) 776 777 Raises: 778 FdtException if no node found or other error occurs 779 """ 780 return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size), 781 quiet) 782 783 def finish_reservemap(self, quiet=()): 784 """Indicate that there are no more reserve map entries to add 785 786 Args: 787 quiet: Errors to ignore (empty to raise on all errors) 788 789 Raises: 790 FdtException if no node found or other error occurs 791 """ 792 return check_err(fdt_finish_reservemap(self._fdtrw), quiet) 793 794 def begin_node(self, name, quiet=()): 795 """Begin a new node 796 797 Use this before adding properties to the node. Then call end_node() to 798 finish it. You can also use the context manager as shown in the FdtSw 799 class comment. 800 801 Args: 802 name: Name of node to begin 803 quiet: Errors to ignore (empty to raise on all errors) 804 805 Raises: 806 FdtException if no node found or other error occurs 807 """ 808 return check_err(fdt_begin_node(self._fdtrw, name), quiet) 809 810 def property_string(self, name, string, quiet=()): 811 """Add a property with a string value 812 813 The string will be nul-terminated when written to the device tree 814 815 Args: 816 name: Name of property to add 817 string: String value of property 818 quiet: Errors to ignore (empty to raise on all errors) 819 820 Raises: 821 FdtException if no node found or other error occurs 822 """ 823 return check_err(fdt_property_string(self._fdtrw, name, string), quiet) 824 825 def property_u32(self, name, val, quiet=()): 826 """Add a property with a 32-bit value 827 828 Write a single-cell value to the device tree 829 830 Args: 831 name: Name of property to add 832 val: Value of property 833 quiet: Errors to ignore (empty to raise on all errors) 834 835 Raises: 836 FdtException if no node found or other error occurs 837 """ 838 return check_err(fdt_property_u32(self._fdtrw, name, val), quiet) 839 840 def property_u64(self, name, val, quiet=()): 841 """Add a property with a 64-bit value 842 843 Write a double-cell value to the device tree in big-endian format 844 845 Args: 846 name: Name of property to add 847 val: Value of property 848 quiet: Errors to ignore (empty to raise on all errors) 849 850 Raises: 851 FdtException if no node found or other error occurs 852 """ 853 return check_err(fdt_property_u64(self._fdtrw, name, val), quiet) 854 855 def property_cell(self, name, val, quiet=()): 856 """Add a property with a single-cell value 857 858 Write a single-cell value to the device tree 859 860 Args: 861 name: Name of property to add 862 val: Value of property 863 quiet: Errors to ignore (empty to raise on all errors) 864 865 Raises: 866 FdtException if no node found or other error occurs 867 """ 868 return check_err(fdt_property_cell(self._fdtrw, name, val), quiet) 869 870 def property(self, name, val, quiet=()): 871 """Add a property 872 873 Write a new property with the given value to the device tree. The value 874 is taken as is and is not nul-terminated 875 876 Args: 877 name: Name of property to add 878 val: Value of property 879 quiet: Errors to ignore (empty to raise on all errors) 880 881 Raises: 882 FdtException if no node found or other error occurs 883 """ 884 return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet) 885 886 def end_node(self, quiet=()): 887 """End a node 888 889 Use this after adding properties to a node to close it off. You can also 890 use the context manager as shown in the FdtSw class comment. 891 892 Args: 893 quiet: Errors to ignore (empty to raise on all errors) 894 895 Raises: 896 FdtException if no node found or other error occurs 897 """ 898 return check_err(fdt_end_node(self._fdtrw), quiet) 899 900 def finish(self, quiet=()): 901 """Finish writing the device tree 902 903 This closes off the device tree ready for use 904 905 Args: 906 quiet: Errors to ignore (empty to raise on all errors) 907 908 Raises: 909 FdtException if no node found or other error occurs 910 """ 911 return check_err(fdt_finish(self._fdtrw), quiet) 912 913 def AddNode(self, name): 914 """Create a new context for adding a node 915 916 When used in a 'with' clause this starts a new node and finishes it 917 afterward. 918 919 Args: 920 name: Name of node to add 921 """ 922 return NodeAdder(self._fdtrw, name) 923 924 925class NodeAdder(): 926 """Class to provide a node context 927 928 This allows you to add nodes in a more natural way: 929 930 with fdtsw.AddNode('name'): 931 fdtsw.property_string('test', 'value') 932 933 The node is automatically completed with a call to end_node() when the 934 context exits. 935 """ 936 def __init__(self, fdt, name): 937 self._fdt = fdt 938 self._name = name 939 940 def __enter__(self): 941 check_err(fdt_begin_node(self._fdt, self._name)) 942 943 def __exit__(self, type, value, traceback): 944 check_err(fdt_end_node(self._fdt)) 945%} 946 947%rename(fdt_property) fdt_property_func; 948 949typedef int fdt32_t; 950 951%include "libfdt/fdt.h" 952 953%include "typemaps.i" 954 955/* Most functions don't change the device tree, so use a const void * */ 956%typemap(in) (const void *)(const void *fdt) { 957 if (!PyByteArray_Check($input)) { 958 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" 959 "', argument " "$argnum"" of type '" "$type""'"); 960 } 961 $1 = (void *)PyByteArray_AsString($input); 962 fdt = $1; 963 fdt = fdt; /* avoid unused variable warning */ 964} 965 966/* Some functions do change the device tree, so use void * */ 967%typemap(in) (void *)(const void *fdt) { 968 if (!PyByteArray_Check($input)) { 969 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" 970 "', argument " "$argnum"" of type '" "$type""'"); 971 } 972 $1 = PyByteArray_AsString($input); 973 fdt = $1; 974 fdt = fdt; /* avoid unused variable warning */ 975} 976 977/* typemap used for fdt_get_property_by_offset() */ 978%typemap(out) (struct fdt_property *) { 979 PyObject *buff; 980 981 if ($1) { 982 resultobj = PyString_FromString( 983 fdt_string(fdt1, fdt32_to_cpu($1->nameoff))); 984 buff = PyByteArray_FromStringAndSize( 985 (const char *)($1 + 1), fdt32_to_cpu($1->len)); 986 resultobj = SWIG_Python_AppendOutput(resultobj, buff); 987 } 988} 989 990%apply int *OUTPUT { int *lenp }; 991 992/* typemap used for fdt_getprop() */ 993%typemap(out) (const void *) { 994 if (!$1) 995 $result = Py_None; 996 else 997 $result = Py_BuildValue("s#", $1, *arg4); 998} 999 1000/* typemap used for fdt_setprop() */ 1001%typemap(in) (const void *val) { 1002 $1 = PyString_AsString($input); /* char *str */ 1003} 1004 1005/* typemap used for fdt_add_reservemap_entry() */ 1006%typemap(in) uint64_t { 1007 $1 = PyLong_AsUnsignedLong($input); 1008} 1009 1010/* typemaps used for fdt_next_node() */ 1011%typemap(in, numinputs=1) int *depth (int depth) { 1012 depth = (int) PyInt_AsLong($input); 1013 $1 = &depth; 1014} 1015 1016%typemap(argout) int *depth { 1017 PyObject *val = Py_BuildValue("i", *arg$argnum); 1018 resultobj = SWIG_Python_AppendOutput(resultobj, val); 1019} 1020 1021%apply int *depth { int *depth }; 1022 1023/* typemaps for fdt_get_mem_rsv */ 1024%typemap(in, numinputs=0) uint64_t * (uint64_t temp) { 1025 $1 = &temp; 1026} 1027 1028%typemap(argout) uint64_t * { 1029 PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); 1030 if (!result) { 1031 if (PyTuple_GET_SIZE(resultobj) == 0) 1032 resultobj = val; 1033 else 1034 resultobj = SWIG_Python_AppendOutput(resultobj, val); 1035 } 1036} 1037 1038/* We have both struct fdt_property and a function fdt_property() */ 1039%warnfilter(302) fdt_property; 1040 1041/* These are macros in the header so have to be redefined here */ 1042int fdt_magic(const void *fdt); 1043int fdt_totalsize(const void *fdt); 1044int fdt_off_dt_struct(const void *fdt); 1045int fdt_off_dt_strings(const void *fdt); 1046int fdt_off_mem_rsvmap(const void *fdt); 1047int fdt_version(const void *fdt); 1048int fdt_last_comp_version(const void *fdt); 1049int fdt_boot_cpuid_phys(const void *fdt); 1050int fdt_size_dt_strings(const void *fdt); 1051int fdt_size_dt_struct(const void *fdt); 1052int fdt_property_string(void *fdt, const char *name, const char *val); 1053int fdt_property_cell(void *fdt, const char *name, uint32_t val); 1054 1055/* 1056 * This function has a stub since the name fdt_property is used for both a 1057 * function and a struct, which confuses SWIG. 1058 */ 1059int _fdt_property(void *fdt, const char *name, const char *val, int len); 1060 1061%include <../libfdt/libfdt.h> 1062