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