14549e789STom Rini/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
215b97f5cSMasahiro Yamada/*
315b97f5cSMasahiro Yamada * pylibfdt - Flat Device Tree manipulation in Python
415b97f5cSMasahiro Yamada * Copyright (C) 2017 Google, Inc.
515b97f5cSMasahiro Yamada * Written by Simon Glass <sjg@chromium.org>
615b97f5cSMasahiro Yamada */
715b97f5cSMasahiro Yamada
815b97f5cSMasahiro Yamada%module libfdt
915b97f5cSMasahiro Yamada
1015b97f5cSMasahiro Yamada%include <stdint.i>
1115b97f5cSMasahiro Yamada
1215b97f5cSMasahiro Yamada%{
1315b97f5cSMasahiro Yamada#define SWIG_FILE_WITH_INIT
1415b97f5cSMasahiro Yamada#include "libfdt.h"
153def0cf2SSimon Glass
163def0cf2SSimon Glass/*
173def0cf2SSimon Glass * We rename this function here to avoid problems with swig, since we also have
183def0cf2SSimon Glass * a struct called fdt_property. That struct causes swig to create a class in
193def0cf2SSimon Glass * libfdt.py called fdt_property(), which confuses things.
203def0cf2SSimon Glass */
21*50c59522SSimon Glassstatic int fdt_property_stub(void *fdt, const char *name, const char *val,
22*50c59522SSimon Glass                             int len)
233def0cf2SSimon Glass{
243def0cf2SSimon Glass    return fdt_property(fdt, name, val, len);
253def0cf2SSimon Glass}
263def0cf2SSimon Glass
2715b97f5cSMasahiro Yamada%}
2815b97f5cSMasahiro Yamada
2915b97f5cSMasahiro Yamada%pythoncode %{
3015b97f5cSMasahiro Yamada
3115b97f5cSMasahiro Yamadaimport struct
3215b97f5cSMasahiro Yamada
3315b97f5cSMasahiro Yamada# Error codes, corresponding to FDT_ERR_... in libfdt.h
3415b97f5cSMasahiro Yamada(NOTFOUND,
3515b97f5cSMasahiro Yamada        EXISTS,
3615b97f5cSMasahiro Yamada        NOSPACE,
3715b97f5cSMasahiro Yamada        BADOFFSET,
3815b97f5cSMasahiro Yamada        BADPATH,
3915b97f5cSMasahiro Yamada        BADPHANDLE,
4015b97f5cSMasahiro Yamada        BADSTATE,
4115b97f5cSMasahiro Yamada        TRUNCATED,
4215b97f5cSMasahiro Yamada        BADMAGIC,
4315b97f5cSMasahiro Yamada        BADVERSION,
4415b97f5cSMasahiro Yamada        BADSTRUCTURE,
4515b97f5cSMasahiro Yamada        BADLAYOUT,
4615b97f5cSMasahiro Yamada        INTERNAL,
4715b97f5cSMasahiro Yamada        BADNCELLS,
4815b97f5cSMasahiro Yamada        BADVALUE,
4915b97f5cSMasahiro Yamada        BADOVERLAY,
5015b97f5cSMasahiro Yamada        NOPHANDLES) = QUIET_ALL = range(1, 18)
5115b97f5cSMasahiro Yamada# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
5215b97f5cSMasahiro Yamada# altogether. All # functions passed this value will return an error instead
5315b97f5cSMasahiro Yamada# of raising an exception.
5415b97f5cSMasahiro Yamada
5515b97f5cSMasahiro Yamada# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
5615b97f5cSMasahiro Yamada# instead of raising an exception.
5715b97f5cSMasahiro YamadaQUIET_NOTFOUND = (NOTFOUND,)
58*50c59522SSimon GlassQUIET_NOSPACE = (NOSPACE,)
5915b97f5cSMasahiro Yamada
6015b97f5cSMasahiro Yamada
6115b97f5cSMasahiro Yamadaclass FdtException(Exception):
6215b97f5cSMasahiro Yamada    """An exception caused by an error such as one of the codes above"""
6315b97f5cSMasahiro Yamada    def __init__(self, err):
6415b97f5cSMasahiro Yamada        self.err = err
6515b97f5cSMasahiro Yamada
6615b97f5cSMasahiro Yamada    def __str__(self):
6715b97f5cSMasahiro Yamada        return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
6815b97f5cSMasahiro Yamada
6915b97f5cSMasahiro Yamadadef strerror(fdt_err):
7015b97f5cSMasahiro Yamada    """Get the string for an error number
7115b97f5cSMasahiro Yamada
7215b97f5cSMasahiro Yamada    Args:
7315b97f5cSMasahiro Yamada        fdt_err: Error number (-ve)
7415b97f5cSMasahiro Yamada
7515b97f5cSMasahiro Yamada    Returns:
7615b97f5cSMasahiro Yamada        String containing the associated error
7715b97f5cSMasahiro Yamada    """
7815b97f5cSMasahiro Yamada    return fdt_strerror(fdt_err)
7915b97f5cSMasahiro Yamada
8015b97f5cSMasahiro Yamadadef check_err(val, quiet=()):
8115b97f5cSMasahiro Yamada    """Raise an error if the return value is -ve
8215b97f5cSMasahiro Yamada
8315b97f5cSMasahiro Yamada    This is used to check for errors returned by libfdt C functions.
8415b97f5cSMasahiro Yamada
8515b97f5cSMasahiro Yamada    Args:
8615b97f5cSMasahiro Yamada        val: Return value from a libfdt function
8715b97f5cSMasahiro Yamada        quiet: Errors to ignore (empty to raise on all errors)
8815b97f5cSMasahiro Yamada
8915b97f5cSMasahiro Yamada    Returns:
9015b97f5cSMasahiro Yamada        val if val >= 0
9115b97f5cSMasahiro Yamada
9215b97f5cSMasahiro Yamada    Raises
9315b97f5cSMasahiro Yamada        FdtException if val < 0
9415b97f5cSMasahiro Yamada    """
9515b97f5cSMasahiro Yamada    if val < 0:
9615b97f5cSMasahiro Yamada        if -val not in quiet:
9715b97f5cSMasahiro Yamada            raise FdtException(val)
9815b97f5cSMasahiro Yamada    return val
9915b97f5cSMasahiro Yamada
10015b97f5cSMasahiro Yamadadef check_err_null(val, quiet=()):
10115b97f5cSMasahiro Yamada    """Raise an error if the return value is NULL
10215b97f5cSMasahiro Yamada
10315b97f5cSMasahiro Yamada    This is used to check for a NULL return value from certain libfdt C
10415b97f5cSMasahiro Yamada    functions
10515b97f5cSMasahiro Yamada
10615b97f5cSMasahiro Yamada    Args:
10715b97f5cSMasahiro Yamada        val: Return value from a libfdt function
10815b97f5cSMasahiro Yamada        quiet: Errors to ignore (empty to raise on all errors)
10915b97f5cSMasahiro Yamada
11015b97f5cSMasahiro Yamada    Returns:
11115b97f5cSMasahiro Yamada        val if val is a list, None if not
11215b97f5cSMasahiro Yamada
11315b97f5cSMasahiro Yamada    Raises
11415b97f5cSMasahiro Yamada        FdtException if val indicates an error was reported and the error
11515b97f5cSMasahiro Yamada        is not in @quiet.
11615b97f5cSMasahiro Yamada    """
11715b97f5cSMasahiro Yamada    # Normally a list is returned which contains the data and its length.
11815b97f5cSMasahiro Yamada    # If we get just an integer error code, it means the function failed.
11915b97f5cSMasahiro Yamada    if not isinstance(val, list):
12015b97f5cSMasahiro Yamada        if -val not in quiet:
12115b97f5cSMasahiro Yamada            raise FdtException(val)
12215b97f5cSMasahiro Yamada    return val
12315b97f5cSMasahiro Yamada
124*50c59522SSimon Glassclass FdtRo(object):
125*50c59522SSimon Glass    """Class for a read-only device-tree
1263def0cf2SSimon Glass
127*50c59522SSimon Glass    This is a base class used by FdtRw (read-write access) and FdtSw
128*50c59522SSimon Glass    (sequential-write access). It implements read-only access to the
129*50c59522SSimon Glass    device tree.
13015b97f5cSMasahiro Yamada
131*50c59522SSimon Glass    Here are the three classes and when you should use them:
13215b97f5cSMasahiro Yamada
133*50c59522SSimon Glass        FdtRo - read-only access to an existing FDT
134*50c59522SSimon Glass        FdtRw - read-write access to an existing FDT (most common case)
135*50c59522SSimon Glass        FdtSw - for creating a new FDT, as well as allowing read-only access
13615b97f5cSMasahiro Yamada    """
13715b97f5cSMasahiro Yamada    def __init__(self, data):
13815b97f5cSMasahiro Yamada        self._fdt = bytearray(data)
13915b97f5cSMasahiro Yamada        check_err(fdt_check_header(self._fdt));
14015b97f5cSMasahiro Yamada
1413def0cf2SSimon Glass    def as_bytearray(self):
1423def0cf2SSimon Glass        """Get the device tree contents as a bytearray
1433def0cf2SSimon Glass
1443def0cf2SSimon Glass        This can be passed directly to libfdt functions that access a
1453def0cf2SSimon Glass        const void * for the device tree.
1463def0cf2SSimon Glass
1473def0cf2SSimon Glass        Returns:
1483def0cf2SSimon Glass            bytearray containing the device tree
1493def0cf2SSimon Glass        """
1503def0cf2SSimon Glass        return bytearray(self._fdt)
1513def0cf2SSimon Glass
1523def0cf2SSimon Glass    def next_node(self, nodeoffset, depth, quiet=()):
1533def0cf2SSimon Glass        """Find the next subnode
1543def0cf2SSimon Glass
1553def0cf2SSimon Glass        Args:
1563def0cf2SSimon Glass            nodeoffset: Node offset of previous node
157*50c59522SSimon Glass            depth: The depth of the node at nodeoffset. This is used to
158*50c59522SSimon Glass                calculate the depth of the returned node
1593def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
1603def0cf2SSimon Glass
1613def0cf2SSimon Glass        Returns:
162*50c59522SSimon Glass            Typle:
163*50c59522SSimon Glass                Offset of the next node, if any, else a -ve error
164*50c59522SSimon Glass                Depth of the returned node, if any, else undefined
1653def0cf2SSimon Glass
1663def0cf2SSimon Glass        Raises:
1673def0cf2SSimon Glass            FdtException if no more nodes found or other error occurs
1683def0cf2SSimon Glass        """
1693def0cf2SSimon Glass        return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet)
1703def0cf2SSimon Glass
1713def0cf2SSimon Glass    def first_subnode(self, nodeoffset, quiet=()):
1723def0cf2SSimon Glass        """Find the first subnode of a parent node
1733def0cf2SSimon Glass
1743def0cf2SSimon Glass        Args:
1753def0cf2SSimon Glass            nodeoffset: Node offset of parent node
1763def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
1773def0cf2SSimon Glass
1783def0cf2SSimon Glass        Returns:
1793def0cf2SSimon Glass            The offset of the first subnode, if any
1803def0cf2SSimon Glass
1813def0cf2SSimon Glass        Raises:
1823def0cf2SSimon Glass            FdtException if no subnodes found or other error occurs
1833def0cf2SSimon Glass        """
1843def0cf2SSimon Glass        return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
1853def0cf2SSimon Glass
1863def0cf2SSimon Glass    def next_subnode(self, nodeoffset, quiet=()):
1873def0cf2SSimon Glass        """Find the next subnode
1883def0cf2SSimon Glass
1893def0cf2SSimon Glass        Args:
1903def0cf2SSimon Glass            nodeoffset: Node offset of previous subnode
1913def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
1923def0cf2SSimon Glass
1933def0cf2SSimon Glass        Returns:
1943def0cf2SSimon Glass            The offset of the next subnode, if any
1953def0cf2SSimon Glass
1963def0cf2SSimon Glass        Raises:
1973def0cf2SSimon Glass            FdtException if no more subnodes found or other error occurs
1983def0cf2SSimon Glass        """
1993def0cf2SSimon Glass        return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
2003def0cf2SSimon Glass
2013def0cf2SSimon Glass    def magic(self):
2023def0cf2SSimon Glass        """Return the magic word from the header
2033def0cf2SSimon Glass
2043def0cf2SSimon Glass        Returns:
2053def0cf2SSimon Glass            Magic word
2063def0cf2SSimon Glass        """
207*50c59522SSimon Glass        return fdt_magic(self._fdt)
2083def0cf2SSimon Glass
2093def0cf2SSimon Glass    def totalsize(self):
2103def0cf2SSimon Glass        """Return the total size of the device tree
2113def0cf2SSimon Glass
2123def0cf2SSimon Glass        Returns:
2133def0cf2SSimon Glass            Total tree size in bytes
2143def0cf2SSimon Glass        """
215*50c59522SSimon Glass        return fdt_totalsize(self._fdt)
2163def0cf2SSimon Glass
2173def0cf2SSimon Glass    def off_dt_struct(self):
2183def0cf2SSimon Glass        """Return the start of the device-tree struct area
2193def0cf2SSimon Glass
2203def0cf2SSimon Glass        Returns:
2213def0cf2SSimon Glass            Start offset of struct area
2223def0cf2SSimon Glass        """
223*50c59522SSimon Glass        return fdt_off_dt_struct(self._fdt)
2243def0cf2SSimon Glass
2253def0cf2SSimon Glass    def off_dt_strings(self):
2263def0cf2SSimon Glass        """Return the start of the device-tree string area
2273def0cf2SSimon Glass
2283def0cf2SSimon Glass        Returns:
2293def0cf2SSimon Glass            Start offset of string area
2303def0cf2SSimon Glass        """
231*50c59522SSimon Glass        return fdt_off_dt_strings(self._fdt)
2323def0cf2SSimon Glass
2333def0cf2SSimon Glass    def off_mem_rsvmap(self):
2343def0cf2SSimon Glass        """Return the start of the memory reserve map
2353def0cf2SSimon Glass
2363def0cf2SSimon Glass        Returns:
2373def0cf2SSimon Glass            Start offset of memory reserve map
2383def0cf2SSimon Glass        """
239*50c59522SSimon Glass        return fdt_off_mem_rsvmap(self._fdt)
2403def0cf2SSimon Glass
2413def0cf2SSimon Glass    def version(self):
2423def0cf2SSimon Glass        """Return the version of the device tree
2433def0cf2SSimon Glass
2443def0cf2SSimon Glass        Returns:
2453def0cf2SSimon Glass            Version number of the device tree
2463def0cf2SSimon Glass        """
247*50c59522SSimon Glass        return fdt_version(self._fdt)
2483def0cf2SSimon Glass
2493def0cf2SSimon Glass    def last_comp_version(self):
2503def0cf2SSimon Glass        """Return the last compatible version of the device tree
2513def0cf2SSimon Glass
2523def0cf2SSimon Glass        Returns:
2533def0cf2SSimon Glass            Last compatible version number of the device tree
2543def0cf2SSimon Glass        """
255*50c59522SSimon Glass        return fdt_last_comp_version(self._fdt)
2563def0cf2SSimon Glass
2573def0cf2SSimon Glass    def boot_cpuid_phys(self):
2583def0cf2SSimon Glass        """Return the physical boot CPU ID
2593def0cf2SSimon Glass
2603def0cf2SSimon Glass        Returns:
2613def0cf2SSimon Glass            Physical boot CPU ID
2623def0cf2SSimon Glass        """
263*50c59522SSimon Glass        return fdt_boot_cpuid_phys(self._fdt)
2643def0cf2SSimon Glass
2653def0cf2SSimon Glass    def size_dt_strings(self):
2663def0cf2SSimon Glass        """Return the start of the device-tree string area
2673def0cf2SSimon Glass
2683def0cf2SSimon Glass        Returns:
2693def0cf2SSimon Glass            Start offset of string area
2703def0cf2SSimon Glass        """
271*50c59522SSimon Glass        return fdt_size_dt_strings(self._fdt)
2723def0cf2SSimon Glass
2733def0cf2SSimon Glass    def size_dt_struct(self):
2743def0cf2SSimon Glass        """Return the start of the device-tree struct area
2753def0cf2SSimon Glass
2763def0cf2SSimon Glass        Returns:
2773def0cf2SSimon Glass            Start offset of struct area
2783def0cf2SSimon Glass        """
279*50c59522SSimon Glass        return fdt_size_dt_struct(self._fdt)
2803def0cf2SSimon Glass
2813def0cf2SSimon Glass    def num_mem_rsv(self, quiet=()):
2823def0cf2SSimon Glass        """Return the number of memory reserve-map records
2833def0cf2SSimon Glass
2843def0cf2SSimon Glass        Returns:
2853def0cf2SSimon Glass            Number of memory reserve-map records
2863def0cf2SSimon Glass        """
2873def0cf2SSimon Glass        return check_err(fdt_num_mem_rsv(self._fdt), quiet)
2883def0cf2SSimon Glass
2893def0cf2SSimon Glass    def get_mem_rsv(self, index, quiet=()):
2903def0cf2SSimon Glass        """Return the indexed memory reserve-map record
2913def0cf2SSimon Glass
2923def0cf2SSimon Glass        Args:
2933def0cf2SSimon Glass            index: Record to return (0=first)
2943def0cf2SSimon Glass
2953def0cf2SSimon Glass        Returns:
2963def0cf2SSimon Glass            Number of memory reserve-map records
2973def0cf2SSimon Glass        """
2983def0cf2SSimon Glass        return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
2993def0cf2SSimon Glass
30015b97f5cSMasahiro Yamada    def subnode_offset(self, parentoffset, name, quiet=()):
30115b97f5cSMasahiro Yamada        """Get the offset of a named subnode
30215b97f5cSMasahiro Yamada
30315b97f5cSMasahiro Yamada        Args:
30415b97f5cSMasahiro Yamada            parentoffset: Offset of the parent node to check
30515b97f5cSMasahiro Yamada            name: Name of the required subnode, e.g. 'subnode@1'
30615b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
30715b97f5cSMasahiro Yamada
30815b97f5cSMasahiro Yamada        Returns:
30915b97f5cSMasahiro Yamada            The node offset of the found node, if any
31015b97f5cSMasahiro Yamada
31115b97f5cSMasahiro Yamada        Raises
31215b97f5cSMasahiro Yamada            FdtException if there is no node with that name, or other error
31315b97f5cSMasahiro Yamada        """
31415b97f5cSMasahiro Yamada        return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
31515b97f5cSMasahiro Yamada                         quiet)
31615b97f5cSMasahiro Yamada
31715b97f5cSMasahiro Yamada    def path_offset(self, path, quiet=()):
31815b97f5cSMasahiro Yamada        """Get the offset for a given path
31915b97f5cSMasahiro Yamada
32015b97f5cSMasahiro Yamada        Args:
32115b97f5cSMasahiro Yamada            path: Path to the required node, e.g. '/node@3/subnode@1'
32215b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
32315b97f5cSMasahiro Yamada
32415b97f5cSMasahiro Yamada        Returns:
32515b97f5cSMasahiro Yamada            Node offset
32615b97f5cSMasahiro Yamada
32715b97f5cSMasahiro Yamada        Raises
32815b97f5cSMasahiro Yamada            FdtException if the path is not valid or not found
32915b97f5cSMasahiro Yamada        """
33015b97f5cSMasahiro Yamada        return check_err(fdt_path_offset(self._fdt, path), quiet)
33115b97f5cSMasahiro Yamada
3323def0cf2SSimon Glass    def get_name(self, nodeoffset):
3333def0cf2SSimon Glass        """Get the name of a node
3343def0cf2SSimon Glass
3353def0cf2SSimon Glass        Args:
3363def0cf2SSimon Glass            nodeoffset: Offset of node to check
3373def0cf2SSimon Glass
3383def0cf2SSimon Glass        Returns:
3393def0cf2SSimon Glass            Node name
3403def0cf2SSimon Glass
3413def0cf2SSimon Glass        Raises:
3423def0cf2SSimon Glass            FdtException on error (e.g. nodeoffset is invalid)
3433def0cf2SSimon Glass        """
3443def0cf2SSimon Glass        return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
3453def0cf2SSimon Glass
34615b97f5cSMasahiro Yamada    def first_property_offset(self, nodeoffset, quiet=()):
34715b97f5cSMasahiro Yamada        """Get the offset of the first property in a node offset
34815b97f5cSMasahiro Yamada
34915b97f5cSMasahiro Yamada        Args:
35015b97f5cSMasahiro Yamada            nodeoffset: Offset to the node to check
35115b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
35215b97f5cSMasahiro Yamada
35315b97f5cSMasahiro Yamada        Returns:
35415b97f5cSMasahiro Yamada            Offset of the first property
35515b97f5cSMasahiro Yamada
35615b97f5cSMasahiro Yamada        Raises
35715b97f5cSMasahiro Yamada            FdtException if the associated node has no properties, or some
35815b97f5cSMasahiro Yamada                other error occurred
35915b97f5cSMasahiro Yamada        """
36015b97f5cSMasahiro Yamada        return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
36115b97f5cSMasahiro Yamada                         quiet)
36215b97f5cSMasahiro Yamada
36315b97f5cSMasahiro Yamada    def next_property_offset(self, prop_offset, quiet=()):
36415b97f5cSMasahiro Yamada        """Get the next property in a node
36515b97f5cSMasahiro Yamada
36615b97f5cSMasahiro Yamada        Args:
36715b97f5cSMasahiro Yamada            prop_offset: Offset of the previous property
36815b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
36915b97f5cSMasahiro Yamada
37015b97f5cSMasahiro Yamada        Returns:
37115b97f5cSMasahiro Yamada            Offset of the next property
37215b97f5cSMasahiro Yamada
37315b97f5cSMasahiro Yamada        Raises:
37415b97f5cSMasahiro Yamada            FdtException if the associated node has no more properties, or
37515b97f5cSMasahiro Yamada                some other error occurred
37615b97f5cSMasahiro Yamada        """
37715b97f5cSMasahiro Yamada        return check_err(fdt_next_property_offset(self._fdt, prop_offset),
37815b97f5cSMasahiro Yamada                         quiet)
37915b97f5cSMasahiro Yamada
38015b97f5cSMasahiro Yamada    def get_property_by_offset(self, prop_offset, quiet=()):
38115b97f5cSMasahiro Yamada        """Obtains a property that can be examined
38215b97f5cSMasahiro Yamada
38315b97f5cSMasahiro Yamada        Args:
38415b97f5cSMasahiro Yamada            prop_offset: Offset of property (e.g. from first_property_offset())
38515b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
38615b97f5cSMasahiro Yamada
38715b97f5cSMasahiro Yamada        Returns:
38815b97f5cSMasahiro Yamada            Property object, or None if not found
38915b97f5cSMasahiro Yamada
39015b97f5cSMasahiro Yamada        Raises:
39115b97f5cSMasahiro Yamada            FdtException on error (e.g. invalid prop_offset or device
39215b97f5cSMasahiro Yamada            tree format)
39315b97f5cSMasahiro Yamada        """
39415b97f5cSMasahiro Yamada        pdata = check_err_null(
39515b97f5cSMasahiro Yamada                fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
39615b97f5cSMasahiro Yamada        if isinstance(pdata, (int)):
39715b97f5cSMasahiro Yamada            return pdata
39815b97f5cSMasahiro Yamada        return Property(pdata[0], pdata[1])
39915b97f5cSMasahiro Yamada
40015b97f5cSMasahiro Yamada    def getprop(self, nodeoffset, prop_name, quiet=()):
40115b97f5cSMasahiro Yamada        """Get a property from a node
40215b97f5cSMasahiro Yamada
40315b97f5cSMasahiro Yamada        Args:
40415b97f5cSMasahiro Yamada            nodeoffset: Node offset containing property to get
40515b97f5cSMasahiro Yamada            prop_name: Name of property to get
40615b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
40715b97f5cSMasahiro Yamada
40815b97f5cSMasahiro Yamada        Returns:
409*50c59522SSimon Glass            Value of property as a Property object (which can be used as a
410*50c59522SSimon Glass               bytearray/string), or -ve error number. On failure, returns an
411*50c59522SSimon Glass               integer error
41215b97f5cSMasahiro Yamada
41315b97f5cSMasahiro Yamada        Raises:
41415b97f5cSMasahiro Yamada            FdtError if any error occurs (e.g. the property is not found)
41515b97f5cSMasahiro Yamada        """
41615b97f5cSMasahiro Yamada        pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
41715b97f5cSMasahiro Yamada                               quiet)
41815b97f5cSMasahiro Yamada        if isinstance(pdata, (int)):
41915b97f5cSMasahiro Yamada            return pdata
4203def0cf2SSimon Glass        return Property(prop_name, bytearray(pdata[0]))
42115b97f5cSMasahiro Yamada
42215b97f5cSMasahiro Yamada    def get_phandle(self, nodeoffset):
42315b97f5cSMasahiro Yamada        """Get the phandle of a node
42415b97f5cSMasahiro Yamada
42515b97f5cSMasahiro Yamada        Args:
42615b97f5cSMasahiro Yamada            nodeoffset: Node offset to check
42715b97f5cSMasahiro Yamada
42815b97f5cSMasahiro Yamada        Returns:
42915b97f5cSMasahiro Yamada            phandle of node, or 0 if the node has no phandle or another error
43015b97f5cSMasahiro Yamada            occurs
43115b97f5cSMasahiro Yamada        """
43215b97f5cSMasahiro Yamada        return fdt_get_phandle(self._fdt, nodeoffset)
43315b97f5cSMasahiro Yamada
43415b97f5cSMasahiro Yamada    def parent_offset(self, nodeoffset, quiet=()):
43515b97f5cSMasahiro Yamada        """Get the offset of a node's parent
43615b97f5cSMasahiro Yamada
43715b97f5cSMasahiro Yamada        Args:
43815b97f5cSMasahiro Yamada            nodeoffset: Node offset to check
43915b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
44015b97f5cSMasahiro Yamada
44115b97f5cSMasahiro Yamada        Returns:
44215b97f5cSMasahiro Yamada            The offset of the parent node, if any
44315b97f5cSMasahiro Yamada
44415b97f5cSMasahiro Yamada        Raises:
44515b97f5cSMasahiro Yamada            FdtException if no parent found or other error occurs
44615b97f5cSMasahiro Yamada        """
44715b97f5cSMasahiro Yamada        return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
44815b97f5cSMasahiro Yamada
449*50c59522SSimon Glass    def node_offset_by_phandle(self, phandle, quiet=()):
450*50c59522SSimon Glass        """Get the offset of a node with the given phandle
451*50c59522SSimon Glass
452*50c59522SSimon Glass        Args:
453*50c59522SSimon Glass            phandle: Phandle to search for
454*50c59522SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
455*50c59522SSimon Glass
456*50c59522SSimon Glass        Returns:
457*50c59522SSimon Glass            The offset of node with that phandle, if any
458*50c59522SSimon Glass
459*50c59522SSimon Glass        Raises:
460*50c59522SSimon Glass            FdtException if no node found or other error occurs
461*50c59522SSimon Glass        """
462*50c59522SSimon Glass        return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
463*50c59522SSimon Glass
464*50c59522SSimon Glass
465*50c59522SSimon Glassclass Fdt(FdtRo):
466*50c59522SSimon Glass    """Device tree class, supporting all operations
467*50c59522SSimon Glass
468*50c59522SSimon Glass    The Fdt object is created is created from a device tree binary file,
469*50c59522SSimon Glass    e.g. with something like:
470*50c59522SSimon Glass
471*50c59522SSimon Glass       fdt = Fdt(open("filename.dtb").read())
472*50c59522SSimon Glass
473*50c59522SSimon Glass    Operations can then be performed using the methods in this class. Each
474*50c59522SSimon Glass    method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
475*50c59522SSimon Glass
476*50c59522SSimon Glass    All methods raise an FdtException if an error occurs. To avoid this
477*50c59522SSimon Glass    behaviour a 'quiet' parameter is provided for some functions. This
478*50c59522SSimon Glass    defaults to empty, but you can pass a list of errors that you expect.
479*50c59522SSimon Glass    If one of these errors occurs, the function will return an error number
480*50c59522SSimon Glass    (e.g. -NOTFOUND).
481*50c59522SSimon Glass    """
482*50c59522SSimon Glass    def __init__(self, data):
483*50c59522SSimon Glass        FdtRo.__init__(self, data)
484*50c59522SSimon Glass
485*50c59522SSimon Glass    @staticmethod
486*50c59522SSimon Glass    def create_empty_tree(size, quiet=()):
487*50c59522SSimon Glass        """Create an empty device tree ready for use
488*50c59522SSimon Glass
489*50c59522SSimon Glass        Args:
490*50c59522SSimon Glass            size: Size of device tree in bytes
491*50c59522SSimon Glass
492*50c59522SSimon Glass        Returns:
493*50c59522SSimon Glass            Fdt object containing the device tree
494*50c59522SSimon Glass        """
495*50c59522SSimon Glass        data = bytearray(size)
496*50c59522SSimon Glass        err = check_err(fdt_create_empty_tree(data, size), quiet)
497*50c59522SSimon Glass        if err:
498*50c59522SSimon Glass            return err
499*50c59522SSimon Glass        return Fdt(data)
500*50c59522SSimon Glass
501*50c59522SSimon Glass    def resize(self, size, quiet=()):
502*50c59522SSimon Glass        """Move the device tree into a larger or smaller space
503*50c59522SSimon Glass
504*50c59522SSimon Glass        This creates a new device tree of size @size and moves the existing
505*50c59522SSimon Glass        device tree contents over to that. It can be used to create more space
506*50c59522SSimon Glass        in a device tree. Note that the Fdt object remains the same, but it
507*50c59522SSimon Glass        now has a new bytearray holding the contents.
508*50c59522SSimon Glass
509*50c59522SSimon Glass        Args:
510*50c59522SSimon Glass            size: Required new size of device tree in bytes
511*50c59522SSimon Glass        """
512*50c59522SSimon Glass        fdt = bytearray(size)
513*50c59522SSimon Glass        err = check_err(fdt_open_into(self._fdt, fdt, size), quiet)
514*50c59522SSimon Glass        if err:
515*50c59522SSimon Glass            return err
516*50c59522SSimon Glass        self._fdt = fdt
517*50c59522SSimon Glass
518*50c59522SSimon Glass    def pack(self, quiet=()):
519*50c59522SSimon Glass        """Pack the device tree to remove unused space
520*50c59522SSimon Glass
521*50c59522SSimon Glass        This adjusts the tree in place.
522*50c59522SSimon Glass
523*50c59522SSimon Glass        Args:
524*50c59522SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
525*50c59522SSimon Glass
526*50c59522SSimon Glass        Returns:
527*50c59522SSimon Glass            Error code, or 0 if OK
528*50c59522SSimon Glass
529*50c59522SSimon Glass        Raises:
530*50c59522SSimon Glass            FdtException if any error occurs
531*50c59522SSimon Glass        """
532*50c59522SSimon Glass        err = check_err(fdt_pack(self._fdt), quiet)
533*50c59522SSimon Glass        if err:
534*50c59522SSimon Glass            return err
535*50c59522SSimon Glass        del self._fdt[self.totalsize():]
536*50c59522SSimon Glass        return err
537*50c59522SSimon Glass
5383def0cf2SSimon Glass    def set_name(self, nodeoffset, name, quiet=()):
5393def0cf2SSimon Glass        """Set the name of a node
5403def0cf2SSimon Glass
5413def0cf2SSimon Glass        Args:
5423def0cf2SSimon Glass            nodeoffset: Node offset of node to update
543*50c59522SSimon Glass            name: New node name (string without \0)
5443def0cf2SSimon Glass
5453def0cf2SSimon Glass        Returns:
5463def0cf2SSimon Glass            Error code, or 0 if OK
5473def0cf2SSimon Glass
5483def0cf2SSimon Glass        Raises:
5493def0cf2SSimon Glass            FdtException if no parent found or other error occurs
5503def0cf2SSimon Glass        """
551*50c59522SSimon Glass        if chr(0) in name:
552*50c59522SSimon Glass            raise ValueError('Property contains embedded nul characters')
5533def0cf2SSimon Glass        return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet)
5543def0cf2SSimon Glass
5553def0cf2SSimon Glass    def setprop(self, nodeoffset, prop_name, val, quiet=()):
5563def0cf2SSimon Glass        """Set the value of a property
5573def0cf2SSimon Glass
5583def0cf2SSimon Glass        Args:
5593def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
5603def0cf2SSimon Glass            prop_name: Name of property
5613def0cf2SSimon Glass            val: Value to write (string or bytearray)
5623def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
5633def0cf2SSimon Glass
5643def0cf2SSimon Glass        Returns:
5653def0cf2SSimon Glass            Error code, or 0 if OK
5663def0cf2SSimon Glass
5673def0cf2SSimon Glass        Raises:
5683def0cf2SSimon Glass            FdtException if no parent found or other error occurs
5693def0cf2SSimon Glass        """
5703def0cf2SSimon Glass        return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
5713def0cf2SSimon Glass                                     len(val)), quiet)
5723def0cf2SSimon Glass
5733def0cf2SSimon Glass    def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
5743def0cf2SSimon Glass        """Set the value of a property
5753def0cf2SSimon Glass
5763def0cf2SSimon Glass        Args:
5773def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
5783def0cf2SSimon Glass            prop_name: Name of property
5793def0cf2SSimon Glass            val: Value to write (integer)
5803def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
5813def0cf2SSimon Glass
5823def0cf2SSimon Glass        Returns:
5833def0cf2SSimon Glass            Error code, or 0 if OK
5843def0cf2SSimon Glass
5853def0cf2SSimon Glass        Raises:
5863def0cf2SSimon Glass            FdtException if no parent found or other error occurs
5873def0cf2SSimon Glass        """
5883def0cf2SSimon Glass        return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val),
5893def0cf2SSimon Glass                         quiet)
5903def0cf2SSimon Glass
5913def0cf2SSimon Glass    def setprop_u64(self, nodeoffset, prop_name, val, quiet=()):
5923def0cf2SSimon Glass        """Set the value of a property
5933def0cf2SSimon Glass
5943def0cf2SSimon Glass        Args:
5953def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
5963def0cf2SSimon Glass            prop_name: Name of property
5973def0cf2SSimon Glass            val: Value to write (integer)
5983def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
5993def0cf2SSimon Glass
6003def0cf2SSimon Glass        Returns:
6013def0cf2SSimon Glass            Error code, or 0 if OK
6023def0cf2SSimon Glass
6033def0cf2SSimon Glass        Raises:
6043def0cf2SSimon Glass            FdtException if no parent found or other error occurs
6053def0cf2SSimon Glass        """
6063def0cf2SSimon Glass        return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val),
6073def0cf2SSimon Glass                         quiet)
6083def0cf2SSimon Glass
6093def0cf2SSimon Glass    def setprop_str(self, nodeoffset, prop_name, val, quiet=()):
6103def0cf2SSimon Glass        """Set the string value of a property
6113def0cf2SSimon Glass
6123def0cf2SSimon Glass        The property is set to the string, with a nul terminator added
6133def0cf2SSimon Glass
6143def0cf2SSimon Glass        Args:
6153def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
6163def0cf2SSimon Glass            prop_name: Name of property
617*50c59522SSimon Glass            val: Value to write (string without nul terminator). Unicode is
618*50c59522SSimon Glass                supposed by encoding to UTF-8
6193def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
6203def0cf2SSimon Glass
6213def0cf2SSimon Glass        Returns:
6223def0cf2SSimon Glass            Error code, or 0 if OK
6233def0cf2SSimon Glass
6243def0cf2SSimon Glass        Raises:
6253def0cf2SSimon Glass            FdtException if no parent found or other error occurs
6263def0cf2SSimon Glass        """
627*50c59522SSimon Glass        val = val.encode('utf-8') + '\0'
6283def0cf2SSimon Glass        return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name,
6293def0cf2SSimon Glass                                     val, len(val)), quiet)
6303def0cf2SSimon Glass
6313def0cf2SSimon Glass    def delprop(self, nodeoffset, prop_name):
6323def0cf2SSimon Glass        """Delete a property from a node
6333def0cf2SSimon Glass
6343def0cf2SSimon Glass        Args:
6353def0cf2SSimon Glass            nodeoffset: Node offset containing property to delete
6363def0cf2SSimon Glass            prop_name: Name of property to delete
6373def0cf2SSimon Glass
6383def0cf2SSimon Glass        Raises:
6393def0cf2SSimon Glass            FdtError if the property does not exist, or another error occurs
6403def0cf2SSimon Glass        """
6413def0cf2SSimon Glass        return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
6423def0cf2SSimon Glass
643c640ed0cSSimon Glass    def del_node(self, nodeoffset):
644c640ed0cSSimon Glass        """Delete a node
645c640ed0cSSimon Glass
646c640ed0cSSimon Glass        Args:
647c640ed0cSSimon Glass            nodeoffset: Node offset containing property to delete
648c640ed0cSSimon Glass
649c640ed0cSSimon Glass        Raises:
650c640ed0cSSimon Glass            FdtError if the node does not exist, or another error occurs
651c640ed0cSSimon Glass        """
652c640ed0cSSimon Glass        return check_err(fdt_del_node(self._fdt, nodeoffset))
653c640ed0cSSimon Glass
6543def0cf2SSimon Glass
6553def0cf2SSimon Glassclass Property(bytearray):
65615b97f5cSMasahiro Yamada    """Holds a device tree property name and value.
65715b97f5cSMasahiro Yamada
65815b97f5cSMasahiro Yamada    This holds a copy of a property taken from the device tree. It does not
65915b97f5cSMasahiro Yamada    reference the device tree, so if anything changes in the device tree,
66015b97f5cSMasahiro Yamada    a Property object will remain valid.
66115b97f5cSMasahiro Yamada
66215b97f5cSMasahiro Yamada    Properties:
66315b97f5cSMasahiro Yamada        name: Property name
6643def0cf2SSimon Glass        value: Property value as a bytearray
66515b97f5cSMasahiro Yamada    """
66615b97f5cSMasahiro Yamada    def __init__(self, name, value):
6673def0cf2SSimon Glass        bytearray.__init__(self, value)
66815b97f5cSMasahiro Yamada        self.name = name
6693def0cf2SSimon Glass
6703def0cf2SSimon Glass    def as_cell(self, fmt):
6713def0cf2SSimon Glass        return struct.unpack('>' + fmt, self)[0]
6723def0cf2SSimon Glass
6733def0cf2SSimon Glass    def as_uint32(self):
6743def0cf2SSimon Glass        return self.as_cell('L')
6753def0cf2SSimon Glass
6763def0cf2SSimon Glass    def as_int32(self):
6773def0cf2SSimon Glass        return self.as_cell('l')
6783def0cf2SSimon Glass
6793def0cf2SSimon Glass    def as_uint64(self):
6803def0cf2SSimon Glass        return self.as_cell('Q')
6813def0cf2SSimon Glass
6823def0cf2SSimon Glass    def as_int64(self):
6833def0cf2SSimon Glass        return self.as_cell('q')
6843def0cf2SSimon Glass
6853def0cf2SSimon Glass    def as_str(self):
686*50c59522SSimon Glass        """Unicode is supported by decoding from UTF-8"""
687*50c59522SSimon Glass        if self[-1] != 0:
688*50c59522SSimon Glass            raise ValueError('Property lacks nul termination')
689*50c59522SSimon Glass        if 0 in self[:-1]:
690*50c59522SSimon Glass            raise ValueError('Property contains embedded nul characters')
691*50c59522SSimon Glass        return self[:-1].decode('utf-8')
6923def0cf2SSimon Glass
6933def0cf2SSimon Glass
694*50c59522SSimon Glassclass FdtSw(FdtRo):
6953def0cf2SSimon Glass    """Software interface to create a device tree from scratch
6963def0cf2SSimon Glass
6973def0cf2SSimon Glass    The methods in this class work by adding to an existing 'partial' device
6983def0cf2SSimon Glass    tree buffer of a fixed size created by instantiating this class. When the
699*50c59522SSimon Glass    tree is complete, call as_fdt() to obtain a device tree ready to be used.
7003def0cf2SSimon Glass
7013def0cf2SSimon Glass    Similarly with nodes, a new node is started with begin_node() and finished
7023def0cf2SSimon Glass    with end_node().
7033def0cf2SSimon Glass
7043def0cf2SSimon Glass    The context manager functions can be used to make this a bit easier:
7053def0cf2SSimon Glass
7063def0cf2SSimon Glass    # First create the device tree with a node and property:
707*50c59522SSimon Glass    sw = FdtSw()
708*50c59522SSimon Glass    with sw.add_node('node'):
7093def0cf2SSimon Glass        sw.property_u32('reg', 2)
710*50c59522SSimon Glass    fdt = sw.as_fdt()
7113def0cf2SSimon Glass
7123def0cf2SSimon Glass    # Now we can use it as a real device tree
7133def0cf2SSimon Glass    fdt.setprop_u32(0, 'reg', 3)
714*50c59522SSimon Glass
715*50c59522SSimon Glass    The size hint provides a starting size for the space to be used by the
716*50c59522SSimon Glass    device tree. This will be increased automatically as needed as new items
717*50c59522SSimon Glass    are added to the tree.
7183def0cf2SSimon Glass    """
719*50c59522SSimon Glass    INC_SIZE = 1024  # Expand size by this much when out of space
720*50c59522SSimon Glass
721*50c59522SSimon Glass    def __init__(self, size_hint=None):
722*50c59522SSimon Glass        """Create a new FdtSw object
723*50c59522SSimon Glass
724*50c59522SSimon Glass        Args:
725*50c59522SSimon Glass            size_hint: A hint as to the initial size to use
726*50c59522SSimon Glass
727*50c59522SSimon Glass        Raises:
728*50c59522SSimon Glass            ValueError if size_hint is negative
729*50c59522SSimon Glass
730*50c59522SSimon Glass        Returns:
731*50c59522SSimon Glass            FdtSw object on success, else integer error code (if not raising)
732*50c59522SSimon Glass        """
733*50c59522SSimon Glass        if not size_hint:
734*50c59522SSimon Glass            size_hint = self.INC_SIZE
735*50c59522SSimon Glass        fdtsw = bytearray(size_hint)
736*50c59522SSimon Glass        err = check_err(fdt_create(fdtsw, size_hint))
7373def0cf2SSimon Glass        if err:
7383def0cf2SSimon Glass            return err
739*50c59522SSimon Glass        self._fdt = fdtsw
7403def0cf2SSimon Glass
741*50c59522SSimon Glass    def as_fdt(self):
7423def0cf2SSimon Glass        """Convert a FdtSw into an Fdt so it can be accessed as normal
7433def0cf2SSimon Glass
744*50c59522SSimon Glass        Creates a new Fdt object from the work-in-progress device tree. This
745*50c59522SSimon Glass        does not call fdt_finish() on the current object, so it is possible to
746*50c59522SSimon Glass        add more nodes/properties and call as_fdt() again to get an updated
747*50c59522SSimon Glass        tree.
7483def0cf2SSimon Glass
7493def0cf2SSimon Glass        Returns:
7503def0cf2SSimon Glass            Fdt object allowing access to the newly created device tree
7513def0cf2SSimon Glass        """
752*50c59522SSimon Glass        fdtsw = bytearray(self._fdt)
753*50c59522SSimon Glass        check_err(fdt_finish(fdtsw))
754*50c59522SSimon Glass        return Fdt(fdtsw)
7553def0cf2SSimon Glass
756*50c59522SSimon Glass    def check_space(self, val):
757*50c59522SSimon Glass        """Check if we need to add more space to the FDT
758*50c59522SSimon Glass
759*50c59522SSimon Glass        This should be called with the error code from an operation. If this is
760*50c59522SSimon Glass        -NOSPACE then the FDT will be expanded to have more space, and True will
761*50c59522SSimon Glass        be returned, indicating that the operation needs to be tried again.
762*50c59522SSimon Glass
763*50c59522SSimon Glass        Args:
764*50c59522SSimon Glass            val: Return value from the operation that was attempted
765*50c59522SSimon Glass
766*50c59522SSimon Glass        Returns:
767*50c59522SSimon Glass            True if the operation must be retried, else False
768*50c59522SSimon Glass        """
769*50c59522SSimon Glass        if check_err(val, QUIET_NOSPACE) < 0:
770*50c59522SSimon Glass            self.resize(len(self._fdt) + self.INC_SIZE)
771*50c59522SSimon Glass            return True
772*50c59522SSimon Glass        return False
773*50c59522SSimon Glass
774*50c59522SSimon Glass    def resize(self, size):
7753def0cf2SSimon Glass        """Resize the buffer to accommodate a larger tree
7763def0cf2SSimon Glass
7773def0cf2SSimon Glass        Args:
7783def0cf2SSimon Glass            size: New size of tree
7793def0cf2SSimon Glass
7803def0cf2SSimon Glass        Raises:
781*50c59522SSimon Glass            FdtException on any error
7823def0cf2SSimon Glass        """
7833def0cf2SSimon Glass        fdt = bytearray(size)
784*50c59522SSimon Glass        err = check_err(fdt_resize(self._fdt, fdt, size))
785*50c59522SSimon Glass        self._fdt = fdt
7863def0cf2SSimon Glass
787*50c59522SSimon Glass    def add_reservemap_entry(self, addr, size):
7883def0cf2SSimon Glass        """Add a new memory reserve map entry
7893def0cf2SSimon Glass
7903def0cf2SSimon Glass        Once finished adding, you must call finish_reservemap().
7913def0cf2SSimon Glass
7923def0cf2SSimon Glass        Args:
7933def0cf2SSimon Glass            addr: 64-bit start address
7943def0cf2SSimon Glass            size: 64-bit size
7953def0cf2SSimon Glass
7963def0cf2SSimon Glass        Raises:
797*50c59522SSimon Glass            FdtException on any error
7983def0cf2SSimon Glass        """
799*50c59522SSimon Glass        while self.check_space(fdt_add_reservemap_entry(self._fdt, addr,
800*50c59522SSimon Glass                                                        size)):
801*50c59522SSimon Glass            pass
8023def0cf2SSimon Glass
803*50c59522SSimon Glass    def finish_reservemap(self):
8043def0cf2SSimon Glass        """Indicate that there are no more reserve map entries to add
8053def0cf2SSimon Glass
8063def0cf2SSimon Glass        Raises:
807*50c59522SSimon Glass            FdtException on any error
8083def0cf2SSimon Glass        """
809*50c59522SSimon Glass        while self.check_space(fdt_finish_reservemap(self._fdt)):
810*50c59522SSimon Glass            pass
8113def0cf2SSimon Glass
812*50c59522SSimon Glass    def begin_node(self, name):
8133def0cf2SSimon Glass        """Begin a new node
8143def0cf2SSimon Glass
8153def0cf2SSimon Glass        Use this before adding properties to the node. Then call end_node() to
8163def0cf2SSimon Glass        finish it. You can also use the context manager as shown in the FdtSw
8173def0cf2SSimon Glass        class comment.
8183def0cf2SSimon Glass
8193def0cf2SSimon Glass        Args:
8203def0cf2SSimon Glass            name: Name of node to begin
8213def0cf2SSimon Glass
8223def0cf2SSimon Glass        Raises:
823*50c59522SSimon Glass            FdtException on any error
8243def0cf2SSimon Glass        """
825*50c59522SSimon Glass        while self.check_space(fdt_begin_node(self._fdt, name)):
826*50c59522SSimon Glass            pass
8273def0cf2SSimon Glass
828*50c59522SSimon Glass    def property_string(self, name, string):
8293def0cf2SSimon Glass        """Add a property with a string value
8303def0cf2SSimon Glass
8313def0cf2SSimon Glass        The string will be nul-terminated when written to the device tree
8323def0cf2SSimon Glass
8333def0cf2SSimon Glass        Args:
8343def0cf2SSimon Glass            name: Name of property to add
8353def0cf2SSimon Glass            string: String value of property
8363def0cf2SSimon Glass
8373def0cf2SSimon Glass        Raises:
838*50c59522SSimon Glass            FdtException on any error
8393def0cf2SSimon Glass        """
840*50c59522SSimon Glass        while self.check_space(fdt_property_string(self._fdt, name, string)):
841*50c59522SSimon Glass            pass
8423def0cf2SSimon Glass
843*50c59522SSimon Glass    def property_u32(self, name, val):
8443def0cf2SSimon Glass        """Add a property with a 32-bit value
8453def0cf2SSimon Glass
8463def0cf2SSimon Glass        Write a single-cell value to the device tree
8473def0cf2SSimon Glass
8483def0cf2SSimon Glass        Args:
8493def0cf2SSimon Glass            name: Name of property to add
8503def0cf2SSimon Glass            val: Value of property
8513def0cf2SSimon Glass
8523def0cf2SSimon Glass        Raises:
853*50c59522SSimon Glass            FdtException on any error
8543def0cf2SSimon Glass        """
855*50c59522SSimon Glass        while self.check_space(fdt_property_u32(self._fdt, name, val)):
856*50c59522SSimon Glass            pass
8573def0cf2SSimon Glass
858*50c59522SSimon Glass    def property_u64(self, name, val):
8593def0cf2SSimon Glass        """Add a property with a 64-bit value
8603def0cf2SSimon Glass
8613def0cf2SSimon Glass        Write a double-cell value to the device tree in big-endian format
8623def0cf2SSimon Glass
8633def0cf2SSimon Glass        Args:
8643def0cf2SSimon Glass            name: Name of property to add
8653def0cf2SSimon Glass            val: Value of property
8663def0cf2SSimon Glass
8673def0cf2SSimon Glass        Raises:
868*50c59522SSimon Glass            FdtException on any error
8693def0cf2SSimon Glass        """
870*50c59522SSimon Glass        while self.check_space(fdt_property_u64(self._fdt, name, val)):
871*50c59522SSimon Glass            pass
8723def0cf2SSimon Glass
873*50c59522SSimon Glass    def property_cell(self, name, val):
8743def0cf2SSimon Glass        """Add a property with a single-cell value
8753def0cf2SSimon Glass
8763def0cf2SSimon Glass        Write a single-cell value to the device tree
8773def0cf2SSimon Glass
8783def0cf2SSimon Glass        Args:
8793def0cf2SSimon Glass            name: Name of property to add
8803def0cf2SSimon Glass            val: Value of property
8813def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
8823def0cf2SSimon Glass
8833def0cf2SSimon Glass        Raises:
884*50c59522SSimon Glass            FdtException on any error
8853def0cf2SSimon Glass        """
886*50c59522SSimon Glass        while self.check_space(fdt_property_cell(self._fdt, name, val)):
887*50c59522SSimon Glass            pass
8883def0cf2SSimon Glass
889*50c59522SSimon Glass    def property(self, name, val):
8903def0cf2SSimon Glass        """Add a property
8913def0cf2SSimon Glass
8923def0cf2SSimon Glass        Write a new property with the given value to the device tree. The value
8933def0cf2SSimon Glass        is taken as is and is not nul-terminated
8943def0cf2SSimon Glass
8953def0cf2SSimon Glass        Args:
8963def0cf2SSimon Glass            name: Name of property to add
8973def0cf2SSimon Glass            val: Value of property
8983def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
8993def0cf2SSimon Glass
9003def0cf2SSimon Glass        Raises:
901*50c59522SSimon Glass            FdtException on any error
9023def0cf2SSimon Glass        """
903*50c59522SSimon Glass        while self.check_space(fdt_property_stub(self._fdt, name, val,
904*50c59522SSimon Glass                                                 len(val))):
905*50c59522SSimon Glass            pass
9063def0cf2SSimon Glass
907*50c59522SSimon Glass    def end_node(self):
9083def0cf2SSimon Glass        """End a node
9093def0cf2SSimon Glass
9103def0cf2SSimon Glass        Use this after adding properties to a node to close it off. You can also
9113def0cf2SSimon Glass        use the context manager as shown in the FdtSw class comment.
9123def0cf2SSimon Glass
9133def0cf2SSimon Glass        Args:
9143def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
9153def0cf2SSimon Glass
9163def0cf2SSimon Glass        Raises:
917*50c59522SSimon Glass            FdtException on any error
9183def0cf2SSimon Glass        """
919*50c59522SSimon Glass        while self.check_space(fdt_end_node(self._fdt)):
920*50c59522SSimon Glass            pass
9213def0cf2SSimon Glass
922*50c59522SSimon Glass    def add_node(self, name):
9233def0cf2SSimon Glass        """Create a new context for adding a node
9243def0cf2SSimon Glass
9253def0cf2SSimon Glass        When used in a 'with' clause this starts a new node and finishes it
9263def0cf2SSimon Glass        afterward.
9273def0cf2SSimon Glass
9283def0cf2SSimon Glass        Args:
9293def0cf2SSimon Glass            name: Name of node to add
9303def0cf2SSimon Glass        """
931*50c59522SSimon Glass        return NodeAdder(self, name)
9323def0cf2SSimon Glass
9333def0cf2SSimon Glass
9343def0cf2SSimon Glassclass NodeAdder():
9353def0cf2SSimon Glass    """Class to provide a node context
9363def0cf2SSimon Glass
9373def0cf2SSimon Glass    This allows you to add nodes in a more natural way:
9383def0cf2SSimon Glass
939*50c59522SSimon Glass        with fdtsw.add_node('name'):
9403def0cf2SSimon Glass            fdtsw.property_string('test', 'value')
9413def0cf2SSimon Glass
9423def0cf2SSimon Glass    The node is automatically completed with a call to end_node() when the
9433def0cf2SSimon Glass    context exits.
9443def0cf2SSimon Glass    """
945*50c59522SSimon Glass    def __init__(self, fdtsw, name):
946*50c59522SSimon Glass        self._fdt = fdtsw
9473def0cf2SSimon Glass        self._name = name
9483def0cf2SSimon Glass
9493def0cf2SSimon Glass    def __enter__(self):
950*50c59522SSimon Glass        self._fdt.begin_node(self._name)
9513def0cf2SSimon Glass
9523def0cf2SSimon Glass    def __exit__(self, type, value, traceback):
953*50c59522SSimon Glass        self._fdt.end_node()
95415b97f5cSMasahiro Yamada%}
95515b97f5cSMasahiro Yamada
95615b97f5cSMasahiro Yamada%rename(fdt_property) fdt_property_func;
95715b97f5cSMasahiro Yamada
958*50c59522SSimon Glass/*
959*50c59522SSimon Glass * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
960*50c59522SSimon Glass * so use the same type here.
961*50c59522SSimon Glass */
962*50c59522SSimon Glasstypedef uint32_t fdt32_t;
96315b97f5cSMasahiro Yamada
96415b97f5cSMasahiro Yamada%include "libfdt/fdt.h"
96515b97f5cSMasahiro Yamada
96615b97f5cSMasahiro Yamada%include "typemaps.i"
96715b97f5cSMasahiro Yamada
96815b97f5cSMasahiro Yamada/* Most functions don't change the device tree, so use a const void * */
96915b97f5cSMasahiro Yamada%typemap(in) (const void *)(const void *fdt) {
97015b97f5cSMasahiro Yamada	if (!PyByteArray_Check($input)) {
97115b97f5cSMasahiro Yamada		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
97215b97f5cSMasahiro Yamada			"', argument " "$argnum"" of type '" "$type""'");
97315b97f5cSMasahiro Yamada	}
97415b97f5cSMasahiro Yamada	$1 = (void *)PyByteArray_AsString($input);
97515b97f5cSMasahiro Yamada        fdt = $1;
97615b97f5cSMasahiro Yamada        fdt = fdt; /* avoid unused variable warning */
97715b97f5cSMasahiro Yamada}
97815b97f5cSMasahiro Yamada
97915b97f5cSMasahiro Yamada/* Some functions do change the device tree, so use void * */
98015b97f5cSMasahiro Yamada%typemap(in) (void *)(const void *fdt) {
98115b97f5cSMasahiro Yamada	if (!PyByteArray_Check($input)) {
98215b97f5cSMasahiro Yamada		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
98315b97f5cSMasahiro Yamada			"', argument " "$argnum"" of type '" "$type""'");
98415b97f5cSMasahiro Yamada	}
98515b97f5cSMasahiro Yamada	$1 = PyByteArray_AsString($input);
98615b97f5cSMasahiro Yamada        fdt = $1;
98715b97f5cSMasahiro Yamada        fdt = fdt; /* avoid unused variable warning */
98815b97f5cSMasahiro Yamada}
98915b97f5cSMasahiro Yamada
9903def0cf2SSimon Glass/* typemap used for fdt_get_property_by_offset() */
99115b97f5cSMasahiro Yamada%typemap(out) (struct fdt_property *) {
99215b97f5cSMasahiro Yamada	PyObject *buff;
99315b97f5cSMasahiro Yamada
99415b97f5cSMasahiro Yamada	if ($1) {
99515b97f5cSMasahiro Yamada		resultobj = PyString_FromString(
99615b97f5cSMasahiro Yamada			fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
99715b97f5cSMasahiro Yamada		buff = PyByteArray_FromStringAndSize(
99815b97f5cSMasahiro Yamada			(const char *)($1 + 1), fdt32_to_cpu($1->len));
99915b97f5cSMasahiro Yamada		resultobj = SWIG_Python_AppendOutput(resultobj, buff);
100015b97f5cSMasahiro Yamada	}
100115b97f5cSMasahiro Yamada}
100215b97f5cSMasahiro Yamada
100315b97f5cSMasahiro Yamada%apply int *OUTPUT { int *lenp };
100415b97f5cSMasahiro Yamada
100515b97f5cSMasahiro Yamada/* typemap used for fdt_getprop() */
100615b97f5cSMasahiro Yamada%typemap(out) (const void *) {
100715b97f5cSMasahiro Yamada	if (!$1)
100815b97f5cSMasahiro Yamada		$result = Py_None;
100915b97f5cSMasahiro Yamada	else
101015b97f5cSMasahiro Yamada		$result = Py_BuildValue("s#", $1, *arg4);
101115b97f5cSMasahiro Yamada}
101215b97f5cSMasahiro Yamada
10133def0cf2SSimon Glass/* typemap used for fdt_setprop() */
10143def0cf2SSimon Glass%typemap(in) (const void *val) {
10153def0cf2SSimon Glass    $1 = PyString_AsString($input);   /* char *str */
10163def0cf2SSimon Glass}
10173def0cf2SSimon Glass
10183def0cf2SSimon Glass/* typemap used for fdt_add_reservemap_entry() */
10193def0cf2SSimon Glass%typemap(in) uint64_t {
10203def0cf2SSimon Glass   $1 = PyLong_AsUnsignedLong($input);
10213def0cf2SSimon Glass}
10223def0cf2SSimon Glass
10233def0cf2SSimon Glass/* typemaps used for fdt_next_node() */
10243def0cf2SSimon Glass%typemap(in, numinputs=1) int *depth (int depth) {
10253def0cf2SSimon Glass   depth = (int) PyInt_AsLong($input);
10263def0cf2SSimon Glass   $1 = &depth;
10273def0cf2SSimon Glass}
10283def0cf2SSimon Glass
10293def0cf2SSimon Glass%typemap(argout) int *depth {
10303def0cf2SSimon Glass        PyObject *val = Py_BuildValue("i", *arg$argnum);
10313def0cf2SSimon Glass        resultobj = SWIG_Python_AppendOutput(resultobj, val);
10323def0cf2SSimon Glass}
10333def0cf2SSimon Glass
10343def0cf2SSimon Glass%apply int *depth { int *depth };
10353def0cf2SSimon Glass
10363def0cf2SSimon Glass/* typemaps for fdt_get_mem_rsv */
10373def0cf2SSimon Glass%typemap(in, numinputs=0) uint64_t * (uint64_t temp) {
10383def0cf2SSimon Glass   $1 = &temp;
10393def0cf2SSimon Glass}
10403def0cf2SSimon Glass
10413def0cf2SSimon Glass%typemap(argout) uint64_t * {
10423def0cf2SSimon Glass        PyObject *val = PyLong_FromUnsignedLong(*arg$argnum);
10433def0cf2SSimon Glass        if (!result) {
10443def0cf2SSimon Glass           if (PyTuple_GET_SIZE(resultobj) == 0)
10453def0cf2SSimon Glass              resultobj = val;
10463def0cf2SSimon Glass           else
10473def0cf2SSimon Glass              resultobj = SWIG_Python_AppendOutput(resultobj, val);
10483def0cf2SSimon Glass        }
10493def0cf2SSimon Glass}
10503def0cf2SSimon Glass
105115b97f5cSMasahiro Yamada/* We have both struct fdt_property and a function fdt_property() */
105215b97f5cSMasahiro Yamada%warnfilter(302) fdt_property;
105315b97f5cSMasahiro Yamada
105415b97f5cSMasahiro Yamada/* These are macros in the header so have to be redefined here */
1055*50c59522SSimon Glassuint32_t fdt_magic(const void *fdt);
1056*50c59522SSimon Glassuint32_t fdt_totalsize(const void *fdt);
1057*50c59522SSimon Glassuint32_t fdt_off_dt_struct(const void *fdt);
1058*50c59522SSimon Glassuint32_t fdt_off_dt_strings(const void *fdt);
1059*50c59522SSimon Glassuint32_t fdt_off_mem_rsvmap(const void *fdt);
1060*50c59522SSimon Glassuint32_t fdt_version(const void *fdt);
1061*50c59522SSimon Glassuint32_t fdt_last_comp_version(const void *fdt);
1062*50c59522SSimon Glassuint32_t fdt_boot_cpuid_phys(const void *fdt);
1063*50c59522SSimon Glassuint32_t fdt_size_dt_strings(const void *fdt);
1064*50c59522SSimon Glassuint32_t fdt_size_dt_struct(const void *fdt);
1065*50c59522SSimon Glass
10663def0cf2SSimon Glassint fdt_property_string(void *fdt, const char *name, const char *val);
10673def0cf2SSimon Glassint fdt_property_cell(void *fdt, const char *name, uint32_t val);
10683def0cf2SSimon Glass
10693def0cf2SSimon Glass/*
10703def0cf2SSimon Glass * This function has a stub since the name fdt_property is used for both a
10713def0cf2SSimon Glass  * function and a struct, which confuses SWIG.
10723def0cf2SSimon Glass */
1073*50c59522SSimon Glassint fdt_property_stub(void *fdt, const char *name, const char *val, int len);
107415b97f5cSMasahiro Yamada
107515b97f5cSMasahiro Yamada%include <../libfdt/libfdt.h>
1076