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): 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 638 Raises: 639 FdtError if the property does not exist, or another error occurs 640 """ 641 return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) 642 643 def del_node(self, nodeoffset): 644 """Delete a node 645 646 Args: 647 nodeoffset: Node offset containing property to delete 648 649 Raises: 650 FdtError if the node does not exist, or another error occurs 651 """ 652 return check_err(fdt_del_node(self._fdt, nodeoffset)) 653 654 655class Property(bytearray): 656 """Holds a device tree property name and value. 657 658 This holds a copy of a property taken from the device tree. It does not 659 reference the device tree, so if anything changes in the device tree, 660 a Property object will remain valid. 661 662 Properties: 663 name: Property name 664 value: Property value as a bytearray 665 """ 666 def __init__(self, name, value): 667 bytearray.__init__(self, value) 668 self.name = name 669 670 def as_cell(self, fmt): 671 return struct.unpack('>' + fmt, self)[0] 672 673 def as_uint32(self): 674 return self.as_cell('L') 675 676 def as_int32(self): 677 return self.as_cell('l') 678 679 def as_uint64(self): 680 return self.as_cell('Q') 681 682 def as_int64(self): 683 return self.as_cell('q') 684 685 def as_str(self): 686 """Unicode is supported by decoding from UTF-8""" 687 if self[-1] != 0: 688 raise ValueError('Property lacks nul termination') 689 if 0 in self[:-1]: 690 raise ValueError('Property contains embedded nul characters') 691 return self[:-1].decode('utf-8') 692 693 694class FdtSw(FdtRo): 695 """Software interface to create a device tree from scratch 696 697 The methods in this class work by adding to an existing 'partial' device 698 tree buffer of a fixed size created by instantiating this class. When the 699 tree is complete, call as_fdt() to obtain a device tree ready to be used. 700 701 Similarly with nodes, a new node is started with begin_node() and finished 702 with end_node(). 703 704 The context manager functions can be used to make this a bit easier: 705 706 # First create the device tree with a node and property: 707 sw = FdtSw() 708 with sw.add_node('node'): 709 sw.property_u32('reg', 2) 710 fdt = sw.as_fdt() 711 712 # Now we can use it as a real device tree 713 fdt.setprop_u32(0, 'reg', 3) 714 715 The size hint provides a starting size for the space to be used by the 716 device tree. This will be increased automatically as needed as new items 717 are added to the tree. 718 """ 719 INC_SIZE = 1024 # Expand size by this much when out of space 720 721 def __init__(self, size_hint=None): 722 """Create a new FdtSw object 723 724 Args: 725 size_hint: A hint as to the initial size to use 726 727 Raises: 728 ValueError if size_hint is negative 729 730 Returns: 731 FdtSw object on success, else integer error code (if not raising) 732 """ 733 if not size_hint: 734 size_hint = self.INC_SIZE 735 fdtsw = bytearray(size_hint) 736 err = check_err(fdt_create(fdtsw, size_hint)) 737 if err: 738 return err 739 self._fdt = fdtsw 740 741 def as_fdt(self): 742 """Convert a FdtSw into an Fdt so it can be accessed as normal 743 744 Creates a new Fdt object from the work-in-progress device tree. This 745 does not call fdt_finish() on the current object, so it is possible to 746 add more nodes/properties and call as_fdt() again to get an updated 747 tree. 748 749 Returns: 750 Fdt object allowing access to the newly created device tree 751 """ 752 fdtsw = bytearray(self._fdt) 753 check_err(fdt_finish(fdtsw)) 754 return Fdt(fdtsw) 755 756 def check_space(self, val): 757 """Check if we need to add more space to the FDT 758 759 This should be called with the error code from an operation. If this is 760 -NOSPACE then the FDT will be expanded to have more space, and True will 761 be returned, indicating that the operation needs to be tried again. 762 763 Args: 764 val: Return value from the operation that was attempted 765 766 Returns: 767 True if the operation must be retried, else False 768 """ 769 if check_err(val, QUIET_NOSPACE) < 0: 770 self.resize(len(self._fdt) + self.INC_SIZE) 771 return True 772 return False 773 774 def resize(self, size): 775 """Resize the buffer to accommodate a larger tree 776 777 Args: 778 size: New size of tree 779 780 Raises: 781 FdtException on any error 782 """ 783 fdt = bytearray(size) 784 err = check_err(fdt_resize(self._fdt, fdt, size)) 785 self._fdt = fdt 786 787 def add_reservemap_entry(self, addr, size): 788 """Add a new memory reserve map entry 789 790 Once finished adding, you must call finish_reservemap(). 791 792 Args: 793 addr: 64-bit start address 794 size: 64-bit size 795 796 Raises: 797 FdtException on any error 798 """ 799 while self.check_space(fdt_add_reservemap_entry(self._fdt, addr, 800 size)): 801 pass 802 803 def finish_reservemap(self): 804 """Indicate that there are no more reserve map entries to add 805 806 Raises: 807 FdtException on any error 808 """ 809 while self.check_space(fdt_finish_reservemap(self._fdt)): 810 pass 811 812 def begin_node(self, name): 813 """Begin a new node 814 815 Use this before adding properties to the node. Then call end_node() to 816 finish it. You can also use the context manager as shown in the FdtSw 817 class comment. 818 819 Args: 820 name: Name of node to begin 821 822 Raises: 823 FdtException on any error 824 """ 825 while self.check_space(fdt_begin_node(self._fdt, name)): 826 pass 827 828 def property_string(self, name, string): 829 """Add a property with a string value 830 831 The string will be nul-terminated when written to the device tree 832 833 Args: 834 name: Name of property to add 835 string: String value of property 836 837 Raises: 838 FdtException on any error 839 """ 840 while self.check_space(fdt_property_string(self._fdt, name, string)): 841 pass 842 843 def property_u32(self, name, val): 844 """Add a property with a 32-bit value 845 846 Write a single-cell value to the device tree 847 848 Args: 849 name: Name of property to add 850 val: Value of property 851 852 Raises: 853 FdtException on any error 854 """ 855 while self.check_space(fdt_property_u32(self._fdt, name, val)): 856 pass 857 858 def property_u64(self, name, val): 859 """Add a property with a 64-bit value 860 861 Write a double-cell value to the device tree in big-endian format 862 863 Args: 864 name: Name of property to add 865 val: Value of property 866 867 Raises: 868 FdtException on any error 869 """ 870 while self.check_space(fdt_property_u64(self._fdt, name, val)): 871 pass 872 873 def property_cell(self, name, val): 874 """Add a property with a single-cell value 875 876 Write a single-cell value to the device tree 877 878 Args: 879 name: Name of property to add 880 val: Value of property 881 quiet: Errors to ignore (empty to raise on all errors) 882 883 Raises: 884 FdtException on any error 885 """ 886 while self.check_space(fdt_property_cell(self._fdt, name, val)): 887 pass 888 889 def property(self, name, val): 890 """Add a property 891 892 Write a new property with the given value to the device tree. The value 893 is taken as is and is not nul-terminated 894 895 Args: 896 name: Name of property to add 897 val: Value of property 898 quiet: Errors to ignore (empty to raise on all errors) 899 900 Raises: 901 FdtException on any error 902 """ 903 while self.check_space(fdt_property_stub(self._fdt, name, val, 904 len(val))): 905 pass 906 907 def end_node(self): 908 """End a node 909 910 Use this after adding properties to a node to close it off. You can also 911 use the context manager as shown in the FdtSw class comment. 912 913 Args: 914 quiet: Errors to ignore (empty to raise on all errors) 915 916 Raises: 917 FdtException on any error 918 """ 919 while self.check_space(fdt_end_node(self._fdt)): 920 pass 921 922 def add_node(self, name): 923 """Create a new context for adding a node 924 925 When used in a 'with' clause this starts a new node and finishes it 926 afterward. 927 928 Args: 929 name: Name of node to add 930 """ 931 return NodeAdder(self, name) 932 933 934class NodeAdder(): 935 """Class to provide a node context 936 937 This allows you to add nodes in a more natural way: 938 939 with fdtsw.add_node('name'): 940 fdtsw.property_string('test', 'value') 941 942 The node is automatically completed with a call to end_node() when the 943 context exits. 944 """ 945 def __init__(self, fdtsw, name): 946 self._fdt = fdtsw 947 self._name = name 948 949 def __enter__(self): 950 self._fdt.begin_node(self._name) 951 952 def __exit__(self, type, value, traceback): 953 self._fdt.end_node() 954%} 955 956%rename(fdt_property) fdt_property_func; 957 958/* 959 * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h 960 * so use the same type here. 961 */ 962typedef uint32_t fdt32_t; 963 964%include "libfdt/fdt.h" 965 966%include "typemaps.i" 967 968/* Most functions don't change the device tree, so use a const void * */ 969%typemap(in) (const void *)(const void *fdt) { 970 if (!PyByteArray_Check($input)) { 971 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" 972 "', argument " "$argnum"" of type '" "$type""'"); 973 } 974 $1 = (void *)PyByteArray_AsString($input); 975 fdt = $1; 976 fdt = fdt; /* avoid unused variable warning */ 977} 978 979/* Some functions do change the device tree, so use void * */ 980%typemap(in) (void *)(const void *fdt) { 981 if (!PyByteArray_Check($input)) { 982 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" 983 "', argument " "$argnum"" of type '" "$type""'"); 984 } 985 $1 = PyByteArray_AsString($input); 986 fdt = $1; 987 fdt = fdt; /* avoid unused variable warning */ 988} 989 990/* typemap used for fdt_get_property_by_offset() */ 991%typemap(out) (struct fdt_property *) { 992 PyObject *buff; 993 994 if ($1) { 995 resultobj = PyString_FromString( 996 fdt_string(fdt1, fdt32_to_cpu($1->nameoff))); 997 buff = PyByteArray_FromStringAndSize( 998 (const char *)($1 + 1), fdt32_to_cpu($1->len)); 999 resultobj = SWIG_Python_AppendOutput(resultobj, buff); 1000 } 1001} 1002 1003%apply int *OUTPUT { int *lenp }; 1004 1005/* typemap used for fdt_getprop() */ 1006%typemap(out) (const void *) { 1007 if (!$1) 1008 $result = Py_None; 1009 else 1010 $result = Py_BuildValue("s#", $1, *arg4); 1011} 1012 1013/* typemap used for fdt_setprop() */ 1014%typemap(in) (const void *val) { 1015 $1 = PyString_AsString($input); /* char *str */ 1016} 1017 1018/* typemap used for fdt_add_reservemap_entry() */ 1019%typemap(in) uint64_t { 1020 $1 = PyLong_AsUnsignedLong($input); 1021} 1022 1023/* typemaps used for fdt_next_node() */ 1024%typemap(in, numinputs=1) int *depth (int depth) { 1025 depth = (int) PyInt_AsLong($input); 1026 $1 = &depth; 1027} 1028 1029%typemap(argout) int *depth { 1030 PyObject *val = Py_BuildValue("i", *arg$argnum); 1031 resultobj = SWIG_Python_AppendOutput(resultobj, val); 1032} 1033 1034%apply int *depth { int *depth }; 1035 1036/* typemaps for fdt_get_mem_rsv */ 1037%typemap(in, numinputs=0) uint64_t * (uint64_t temp) { 1038 $1 = &temp; 1039} 1040 1041%typemap(argout) uint64_t * { 1042 PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); 1043 if (!result) { 1044 if (PyTuple_GET_SIZE(resultobj) == 0) 1045 resultobj = val; 1046 else 1047 resultobj = SWIG_Python_AppendOutput(resultobj, val); 1048 } 1049} 1050 1051/* We have both struct fdt_property and a function fdt_property() */ 1052%warnfilter(302) fdt_property; 1053 1054/* These are macros in the header so have to be redefined here */ 1055uint32_t fdt_magic(const void *fdt); 1056uint32_t fdt_totalsize(const void *fdt); 1057uint32_t fdt_off_dt_struct(const void *fdt); 1058uint32_t fdt_off_dt_strings(const void *fdt); 1059uint32_t fdt_off_mem_rsvmap(const void *fdt); 1060uint32_t fdt_version(const void *fdt); 1061uint32_t fdt_last_comp_version(const void *fdt); 1062uint32_t fdt_boot_cpuid_phys(const void *fdt); 1063uint32_t fdt_size_dt_strings(const void *fdt); 1064uint32_t fdt_size_dt_struct(const void *fdt); 1065 1066int fdt_property_string(void *fdt, const char *name, const char *val); 1067int fdt_property_cell(void *fdt, const char *name, uint32_t val); 1068 1069/* 1070 * This function has a stub since the name fdt_property is used for both a 1071 * function and a struct, which confuses SWIG. 1072 */ 1073int fdt_property_stub(void *fdt, const char *name, const char *val, int len); 1074 1075%include <../libfdt/libfdt.h> 1076