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