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