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