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"
15*3def0cf2SSimon Glass
16*3def0cf2SSimon Glass/*
17*3def0cf2SSimon Glass * We rename this function here to avoid problems with swig, since we also have
18*3def0cf2SSimon Glass * a struct called fdt_property. That struct causes swig to create a class in
19*3def0cf2SSimon Glass * libfdt.py called fdt_property(), which confuses things.
20*3def0cf2SSimon Glass */
21*3def0cf2SSimon Glassstatic int _fdt_property(void *fdt, const char *name, const char *val, int len)
22*3def0cf2SSimon Glass{
23*3def0cf2SSimon Glass    return fdt_property(fdt, name, val, len);
24*3def0cf2SSimon Glass}
25*3def0cf2SSimon Glass
2615b97f5cSMasahiro Yamada%}
2715b97f5cSMasahiro Yamada
2815b97f5cSMasahiro Yamada%pythoncode %{
2915b97f5cSMasahiro Yamada
3015b97f5cSMasahiro Yamadaimport struct
3115b97f5cSMasahiro Yamada
3215b97f5cSMasahiro Yamada# Error codes, corresponding to FDT_ERR_... in libfdt.h
3315b97f5cSMasahiro Yamada(NOTFOUND,
3415b97f5cSMasahiro Yamada        EXISTS,
3515b97f5cSMasahiro Yamada        NOSPACE,
3615b97f5cSMasahiro Yamada        BADOFFSET,
3715b97f5cSMasahiro Yamada        BADPATH,
3815b97f5cSMasahiro Yamada        BADPHANDLE,
3915b97f5cSMasahiro Yamada        BADSTATE,
4015b97f5cSMasahiro Yamada        TRUNCATED,
4115b97f5cSMasahiro Yamada        BADMAGIC,
4215b97f5cSMasahiro Yamada        BADVERSION,
4315b97f5cSMasahiro Yamada        BADSTRUCTURE,
4415b97f5cSMasahiro Yamada        BADLAYOUT,
4515b97f5cSMasahiro Yamada        INTERNAL,
4615b97f5cSMasahiro Yamada        BADNCELLS,
4715b97f5cSMasahiro Yamada        BADVALUE,
4815b97f5cSMasahiro Yamada        BADOVERLAY,
4915b97f5cSMasahiro Yamada        NOPHANDLES) = QUIET_ALL = range(1, 18)
5015b97f5cSMasahiro Yamada# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
5115b97f5cSMasahiro Yamada# altogether. All # functions passed this value will return an error instead
5215b97f5cSMasahiro Yamada# of raising an exception.
5315b97f5cSMasahiro Yamada
5415b97f5cSMasahiro Yamada# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
5515b97f5cSMasahiro Yamada# instead of raising an exception.
5615b97f5cSMasahiro YamadaQUIET_NOTFOUND = (NOTFOUND,)
5715b97f5cSMasahiro Yamada
5815b97f5cSMasahiro Yamada
5915b97f5cSMasahiro Yamadaclass FdtException(Exception):
6015b97f5cSMasahiro Yamada    """An exception caused by an error such as one of the codes above"""
6115b97f5cSMasahiro Yamada    def __init__(self, err):
6215b97f5cSMasahiro Yamada        self.err = err
6315b97f5cSMasahiro Yamada
6415b97f5cSMasahiro Yamada    def __str__(self):
6515b97f5cSMasahiro Yamada        return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
6615b97f5cSMasahiro Yamada
6715b97f5cSMasahiro Yamadadef strerror(fdt_err):
6815b97f5cSMasahiro Yamada    """Get the string for an error number
6915b97f5cSMasahiro Yamada
7015b97f5cSMasahiro Yamada    Args:
7115b97f5cSMasahiro Yamada        fdt_err: Error number (-ve)
7215b97f5cSMasahiro Yamada
7315b97f5cSMasahiro Yamada    Returns:
7415b97f5cSMasahiro Yamada        String containing the associated error
7515b97f5cSMasahiro Yamada    """
7615b97f5cSMasahiro Yamada    return fdt_strerror(fdt_err)
7715b97f5cSMasahiro Yamada
7815b97f5cSMasahiro Yamadadef check_err(val, quiet=()):
7915b97f5cSMasahiro Yamada    """Raise an error if the return value is -ve
8015b97f5cSMasahiro Yamada
8115b97f5cSMasahiro Yamada    This is used to check for errors returned by libfdt C functions.
8215b97f5cSMasahiro Yamada
8315b97f5cSMasahiro Yamada    Args:
8415b97f5cSMasahiro Yamada        val: Return value from a libfdt function
8515b97f5cSMasahiro Yamada        quiet: Errors to ignore (empty to raise on all errors)
8615b97f5cSMasahiro Yamada
8715b97f5cSMasahiro Yamada    Returns:
8815b97f5cSMasahiro Yamada        val if val >= 0
8915b97f5cSMasahiro Yamada
9015b97f5cSMasahiro Yamada    Raises
9115b97f5cSMasahiro Yamada        FdtException if val < 0
9215b97f5cSMasahiro Yamada    """
9315b97f5cSMasahiro Yamada    if val < 0:
9415b97f5cSMasahiro Yamada        if -val not in quiet:
9515b97f5cSMasahiro Yamada            raise FdtException(val)
9615b97f5cSMasahiro Yamada    return val
9715b97f5cSMasahiro Yamada
9815b97f5cSMasahiro Yamadadef check_err_null(val, quiet=()):
9915b97f5cSMasahiro Yamada    """Raise an error if the return value is NULL
10015b97f5cSMasahiro Yamada
10115b97f5cSMasahiro Yamada    This is used to check for a NULL return value from certain libfdt C
10215b97f5cSMasahiro Yamada    functions
10315b97f5cSMasahiro Yamada
10415b97f5cSMasahiro Yamada    Args:
10515b97f5cSMasahiro Yamada        val: Return value from a libfdt function
10615b97f5cSMasahiro Yamada        quiet: Errors to ignore (empty to raise on all errors)
10715b97f5cSMasahiro Yamada
10815b97f5cSMasahiro Yamada    Returns:
10915b97f5cSMasahiro Yamada        val if val is a list, None if not
11015b97f5cSMasahiro Yamada
11115b97f5cSMasahiro Yamada    Raises
11215b97f5cSMasahiro Yamada        FdtException if val indicates an error was reported and the error
11315b97f5cSMasahiro Yamada        is not in @quiet.
11415b97f5cSMasahiro Yamada    """
11515b97f5cSMasahiro Yamada    # Normally a list is returned which contains the data and its length.
11615b97f5cSMasahiro Yamada    # If we get just an integer error code, it means the function failed.
11715b97f5cSMasahiro Yamada    if not isinstance(val, list):
11815b97f5cSMasahiro Yamada        if -val not in quiet:
11915b97f5cSMasahiro Yamada            raise FdtException(val)
12015b97f5cSMasahiro Yamada    return val
12115b97f5cSMasahiro Yamada
122*3def0cf2SSimon Glass
12315b97f5cSMasahiro Yamadaclass Fdt:
12415b97f5cSMasahiro Yamada    """Device tree class, supporting all operations
12515b97f5cSMasahiro Yamada
12615b97f5cSMasahiro Yamada    The Fdt object is created is created from a device tree binary file,
12715b97f5cSMasahiro Yamada    e.g. with something like:
12815b97f5cSMasahiro Yamada
12915b97f5cSMasahiro Yamada       fdt = Fdt(open("filename.dtb").read())
13015b97f5cSMasahiro Yamada
13115b97f5cSMasahiro Yamada    Operations can then be performed using the methods in this class. Each
13215b97f5cSMasahiro Yamada    method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
13315b97f5cSMasahiro Yamada
13415b97f5cSMasahiro Yamada    All methods raise an FdtException if an error occurs. To avoid this
13515b97f5cSMasahiro Yamada    behaviour a 'quiet' parameter is provided for some functions. This
13615b97f5cSMasahiro Yamada    defaults to empty, but you can pass a list of errors that you expect.
13715b97f5cSMasahiro Yamada    If one of these errors occurs, the function will return an error number
13815b97f5cSMasahiro Yamada    (e.g. -NOTFOUND).
13915b97f5cSMasahiro Yamada    """
14015b97f5cSMasahiro Yamada    def __init__(self, data):
14115b97f5cSMasahiro Yamada        self._fdt = bytearray(data)
14215b97f5cSMasahiro Yamada        check_err(fdt_check_header(self._fdt));
14315b97f5cSMasahiro Yamada
144*3def0cf2SSimon Glass    def as_bytearray(self):
145*3def0cf2SSimon Glass        """Get the device tree contents as a bytearray
146*3def0cf2SSimon Glass
147*3def0cf2SSimon Glass        This can be passed directly to libfdt functions that access a
148*3def0cf2SSimon Glass        const void * for the device tree.
149*3def0cf2SSimon Glass
150*3def0cf2SSimon Glass        Returns:
151*3def0cf2SSimon Glass            bytearray containing the device tree
152*3def0cf2SSimon Glass        """
153*3def0cf2SSimon Glass        return bytearray(self._fdt)
154*3def0cf2SSimon Glass
155*3def0cf2SSimon Glass    def next_node(self, nodeoffset, depth, quiet=()):
156*3def0cf2SSimon Glass        """Find the next subnode
157*3def0cf2SSimon Glass
158*3def0cf2SSimon Glass        Args:
159*3def0cf2SSimon Glass            nodeoffset: Node offset of previous node
160*3def0cf2SSimon Glass            depth: On input, the depth of the node at nodeoffset. On output, the
161*3def0cf2SSimon Glass               depth of the returned node
162*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
163*3def0cf2SSimon Glass
164*3def0cf2SSimon Glass        Returns:
165*3def0cf2SSimon Glass            The offset of the next node, if any
166*3def0cf2SSimon Glass
167*3def0cf2SSimon Glass        Raises:
168*3def0cf2SSimon Glass            FdtException if no more nodes found or other error occurs
169*3def0cf2SSimon Glass        """
170*3def0cf2SSimon Glass        return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet)
171*3def0cf2SSimon Glass
172*3def0cf2SSimon Glass    def first_subnode(self, nodeoffset, quiet=()):
173*3def0cf2SSimon Glass        """Find the first subnode of a parent node
174*3def0cf2SSimon Glass
175*3def0cf2SSimon Glass        Args:
176*3def0cf2SSimon Glass            nodeoffset: Node offset of parent node
177*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
178*3def0cf2SSimon Glass
179*3def0cf2SSimon Glass        Returns:
180*3def0cf2SSimon Glass            The offset of the first subnode, if any
181*3def0cf2SSimon Glass
182*3def0cf2SSimon Glass        Raises:
183*3def0cf2SSimon Glass            FdtException if no subnodes found or other error occurs
184*3def0cf2SSimon Glass        """
185*3def0cf2SSimon Glass        return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
186*3def0cf2SSimon Glass
187*3def0cf2SSimon Glass    def next_subnode(self, nodeoffset, quiet=()):
188*3def0cf2SSimon Glass        """Find the next subnode
189*3def0cf2SSimon Glass
190*3def0cf2SSimon Glass        Args:
191*3def0cf2SSimon Glass            nodeoffset: Node offset of previous subnode
192*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
193*3def0cf2SSimon Glass
194*3def0cf2SSimon Glass        Returns:
195*3def0cf2SSimon Glass            The offset of the next subnode, if any
196*3def0cf2SSimon Glass
197*3def0cf2SSimon Glass        Raises:
198*3def0cf2SSimon Glass            FdtException if no more subnodes found or other error occurs
199*3def0cf2SSimon Glass        """
200*3def0cf2SSimon Glass        return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
201*3def0cf2SSimon Glass
202*3def0cf2SSimon Glass    def magic(self):
203*3def0cf2SSimon Glass        """Return the magic word from the header
204*3def0cf2SSimon Glass
205*3def0cf2SSimon Glass        Returns:
206*3def0cf2SSimon Glass            Magic word
207*3def0cf2SSimon Glass        """
208*3def0cf2SSimon Glass        return fdt_magic(self._fdt) & 0xffffffff
209*3def0cf2SSimon Glass
210*3def0cf2SSimon Glass    def totalsize(self):
211*3def0cf2SSimon Glass        """Return the total size of the device tree
212*3def0cf2SSimon Glass
213*3def0cf2SSimon Glass        Returns:
214*3def0cf2SSimon Glass            Total tree size in bytes
215*3def0cf2SSimon Glass        """
216*3def0cf2SSimon Glass        return check_err(fdt_totalsize(self._fdt))
217*3def0cf2SSimon Glass
218*3def0cf2SSimon Glass    def off_dt_struct(self):
219*3def0cf2SSimon Glass        """Return the start of the device-tree struct area
220*3def0cf2SSimon Glass
221*3def0cf2SSimon Glass        Returns:
222*3def0cf2SSimon Glass            Start offset of struct area
223*3def0cf2SSimon Glass        """
224*3def0cf2SSimon Glass        return check_err(fdt_off_dt_struct(self._fdt))
225*3def0cf2SSimon Glass
226*3def0cf2SSimon Glass    def off_dt_strings(self):
227*3def0cf2SSimon Glass        """Return the start of the device-tree string area
228*3def0cf2SSimon Glass
229*3def0cf2SSimon Glass        Returns:
230*3def0cf2SSimon Glass            Start offset of string area
231*3def0cf2SSimon Glass        """
232*3def0cf2SSimon Glass        return check_err(fdt_off_dt_strings(self._fdt))
233*3def0cf2SSimon Glass
234*3def0cf2SSimon Glass    def off_mem_rsvmap(self):
235*3def0cf2SSimon Glass        """Return the start of the memory reserve map
236*3def0cf2SSimon Glass
237*3def0cf2SSimon Glass        Returns:
238*3def0cf2SSimon Glass            Start offset of memory reserve map
239*3def0cf2SSimon Glass        """
240*3def0cf2SSimon Glass        return check_err(fdt_off_mem_rsvmap(self._fdt))
241*3def0cf2SSimon Glass
242*3def0cf2SSimon Glass    def version(self):
243*3def0cf2SSimon Glass        """Return the version of the device tree
244*3def0cf2SSimon Glass
245*3def0cf2SSimon Glass        Returns:
246*3def0cf2SSimon Glass            Version number of the device tree
247*3def0cf2SSimon Glass        """
248*3def0cf2SSimon Glass        return check_err(fdt_version(self._fdt))
249*3def0cf2SSimon Glass
250*3def0cf2SSimon Glass    def last_comp_version(self):
251*3def0cf2SSimon Glass        """Return the last compatible version of the device tree
252*3def0cf2SSimon Glass
253*3def0cf2SSimon Glass        Returns:
254*3def0cf2SSimon Glass            Last compatible version number of the device tree
255*3def0cf2SSimon Glass        """
256*3def0cf2SSimon Glass        return check_err(fdt_last_comp_version(self._fdt))
257*3def0cf2SSimon Glass
258*3def0cf2SSimon Glass    def boot_cpuid_phys(self):
259*3def0cf2SSimon Glass        """Return the physical boot CPU ID
260*3def0cf2SSimon Glass
261*3def0cf2SSimon Glass        Returns:
262*3def0cf2SSimon Glass            Physical boot CPU ID
263*3def0cf2SSimon Glass        """
264*3def0cf2SSimon Glass        return check_err(fdt_boot_cpuid_phys(self._fdt))
265*3def0cf2SSimon Glass
266*3def0cf2SSimon Glass    def size_dt_strings(self):
267*3def0cf2SSimon Glass        """Return the start of the device-tree string area
268*3def0cf2SSimon Glass
269*3def0cf2SSimon Glass        Returns:
270*3def0cf2SSimon Glass            Start offset of string area
271*3def0cf2SSimon Glass        """
272*3def0cf2SSimon Glass        return check_err(fdt_size_dt_strings(self._fdt))
273*3def0cf2SSimon Glass
274*3def0cf2SSimon Glass    def size_dt_struct(self):
275*3def0cf2SSimon Glass        """Return the start of the device-tree struct area
276*3def0cf2SSimon Glass
277*3def0cf2SSimon Glass        Returns:
278*3def0cf2SSimon Glass            Start offset of struct area
279*3def0cf2SSimon Glass        """
280*3def0cf2SSimon Glass        return check_err(fdt_size_dt_struct(self._fdt))
281*3def0cf2SSimon Glass
282*3def0cf2SSimon Glass    def num_mem_rsv(self, quiet=()):
283*3def0cf2SSimon Glass        """Return the number of memory reserve-map records
284*3def0cf2SSimon Glass
285*3def0cf2SSimon Glass        Returns:
286*3def0cf2SSimon Glass            Number of memory reserve-map records
287*3def0cf2SSimon Glass        """
288*3def0cf2SSimon Glass        return check_err(fdt_num_mem_rsv(self._fdt), quiet)
289*3def0cf2SSimon Glass
290*3def0cf2SSimon Glass    def get_mem_rsv(self, index, quiet=()):
291*3def0cf2SSimon Glass        """Return the indexed memory reserve-map record
292*3def0cf2SSimon Glass
293*3def0cf2SSimon Glass        Args:
294*3def0cf2SSimon Glass            index: Record to return (0=first)
295*3def0cf2SSimon Glass
296*3def0cf2SSimon Glass        Returns:
297*3def0cf2SSimon Glass            Number of memory reserve-map records
298*3def0cf2SSimon Glass        """
299*3def0cf2SSimon Glass        return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
300*3def0cf2SSimon Glass
30115b97f5cSMasahiro Yamada    def subnode_offset(self, parentoffset, name, quiet=()):
30215b97f5cSMasahiro Yamada        """Get the offset of a named subnode
30315b97f5cSMasahiro Yamada
30415b97f5cSMasahiro Yamada        Args:
30515b97f5cSMasahiro Yamada            parentoffset: Offset of the parent node to check
30615b97f5cSMasahiro Yamada            name: Name of the required subnode, e.g. 'subnode@1'
30715b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
30815b97f5cSMasahiro Yamada
30915b97f5cSMasahiro Yamada        Returns:
31015b97f5cSMasahiro Yamada            The node offset of the found node, if any
31115b97f5cSMasahiro Yamada
31215b97f5cSMasahiro Yamada        Raises
31315b97f5cSMasahiro Yamada            FdtException if there is no node with that name, or other error
31415b97f5cSMasahiro Yamada        """
31515b97f5cSMasahiro Yamada        return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
31615b97f5cSMasahiro Yamada                         quiet)
31715b97f5cSMasahiro Yamada
31815b97f5cSMasahiro Yamada    def path_offset(self, path, quiet=()):
31915b97f5cSMasahiro Yamada        """Get the offset for a given path
32015b97f5cSMasahiro Yamada
32115b97f5cSMasahiro Yamada        Args:
32215b97f5cSMasahiro Yamada            path: Path to the required node, e.g. '/node@3/subnode@1'
32315b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
32415b97f5cSMasahiro Yamada
32515b97f5cSMasahiro Yamada        Returns:
32615b97f5cSMasahiro Yamada            Node offset
32715b97f5cSMasahiro Yamada
32815b97f5cSMasahiro Yamada        Raises
32915b97f5cSMasahiro Yamada            FdtException if the path is not valid or not found
33015b97f5cSMasahiro Yamada        """
33115b97f5cSMasahiro Yamada        return check_err(fdt_path_offset(self._fdt, path), quiet)
33215b97f5cSMasahiro Yamada
333*3def0cf2SSimon Glass    def get_name(self, nodeoffset):
334*3def0cf2SSimon Glass        """Get the name of a node
335*3def0cf2SSimon Glass
336*3def0cf2SSimon Glass        Args:
337*3def0cf2SSimon Glass            nodeoffset: Offset of node to check
338*3def0cf2SSimon Glass
339*3def0cf2SSimon Glass        Returns:
340*3def0cf2SSimon Glass            Node name
341*3def0cf2SSimon Glass
342*3def0cf2SSimon Glass        Raises:
343*3def0cf2SSimon Glass            FdtException on error (e.g. nodeoffset is invalid)
344*3def0cf2SSimon Glass        """
345*3def0cf2SSimon Glass        return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
346*3def0cf2SSimon Glass
34715b97f5cSMasahiro Yamada    def first_property_offset(self, nodeoffset, quiet=()):
34815b97f5cSMasahiro Yamada        """Get the offset of the first property in a node offset
34915b97f5cSMasahiro Yamada
35015b97f5cSMasahiro Yamada        Args:
35115b97f5cSMasahiro Yamada            nodeoffset: Offset to the node to check
35215b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
35315b97f5cSMasahiro Yamada
35415b97f5cSMasahiro Yamada        Returns:
35515b97f5cSMasahiro Yamada            Offset of the first property
35615b97f5cSMasahiro Yamada
35715b97f5cSMasahiro Yamada        Raises
35815b97f5cSMasahiro Yamada            FdtException if the associated node has no properties, or some
35915b97f5cSMasahiro Yamada                other error occurred
36015b97f5cSMasahiro Yamada        """
36115b97f5cSMasahiro Yamada        return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
36215b97f5cSMasahiro Yamada                         quiet)
36315b97f5cSMasahiro Yamada
36415b97f5cSMasahiro Yamada    def next_property_offset(self, prop_offset, quiet=()):
36515b97f5cSMasahiro Yamada        """Get the next property in a node
36615b97f5cSMasahiro Yamada
36715b97f5cSMasahiro Yamada        Args:
36815b97f5cSMasahiro Yamada            prop_offset: Offset of the previous property
36915b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
37015b97f5cSMasahiro Yamada
37115b97f5cSMasahiro Yamada        Returns:
37215b97f5cSMasahiro Yamada            Offset of the next property
37315b97f5cSMasahiro Yamada
37415b97f5cSMasahiro Yamada        Raises:
37515b97f5cSMasahiro Yamada            FdtException if the associated node has no more properties, or
37615b97f5cSMasahiro Yamada                some other error occurred
37715b97f5cSMasahiro Yamada        """
37815b97f5cSMasahiro Yamada        return check_err(fdt_next_property_offset(self._fdt, prop_offset),
37915b97f5cSMasahiro Yamada                         quiet)
38015b97f5cSMasahiro Yamada
38115b97f5cSMasahiro Yamada    def get_property_by_offset(self, prop_offset, quiet=()):
38215b97f5cSMasahiro Yamada        """Obtains a property that can be examined
38315b97f5cSMasahiro Yamada
38415b97f5cSMasahiro Yamada        Args:
38515b97f5cSMasahiro Yamada            prop_offset: Offset of property (e.g. from first_property_offset())
38615b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
38715b97f5cSMasahiro Yamada
38815b97f5cSMasahiro Yamada        Returns:
38915b97f5cSMasahiro Yamada            Property object, or None if not found
39015b97f5cSMasahiro Yamada
39115b97f5cSMasahiro Yamada        Raises:
39215b97f5cSMasahiro Yamada            FdtException on error (e.g. invalid prop_offset or device
39315b97f5cSMasahiro Yamada            tree format)
39415b97f5cSMasahiro Yamada        """
39515b97f5cSMasahiro Yamada        pdata = check_err_null(
39615b97f5cSMasahiro Yamada                fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
39715b97f5cSMasahiro Yamada        if isinstance(pdata, (int)):
39815b97f5cSMasahiro Yamada            return pdata
39915b97f5cSMasahiro Yamada        return Property(pdata[0], pdata[1])
40015b97f5cSMasahiro Yamada
401*3def0cf2SSimon Glass    @staticmethod
402*3def0cf2SSimon Glass    def create_empty_tree(size, quiet=()):
403*3def0cf2SSimon Glass        """Create an empty device tree ready for use
40415b97f5cSMasahiro Yamada
40515b97f5cSMasahiro Yamada        Args:
406*3def0cf2SSimon Glass            size: Size of device tree in bytes
40715b97f5cSMasahiro Yamada
40815b97f5cSMasahiro Yamada        Returns:
409*3def0cf2SSimon Glass            Fdt object containing the device tree
41015b97f5cSMasahiro Yamada        """
411*3def0cf2SSimon Glass        data = bytearray(size)
412*3def0cf2SSimon Glass        err = check_err(fdt_create_empty_tree(data, size), quiet)
413*3def0cf2SSimon Glass        if err:
414*3def0cf2SSimon Glass            return err
415*3def0cf2SSimon Glass        return Fdt(data)
41615b97f5cSMasahiro Yamada
417*3def0cf2SSimon Glass    def open_into(self, size, quiet=()):
418*3def0cf2SSimon Glass        """Move the device tree into a larger or smaller space
419*3def0cf2SSimon Glass
420*3def0cf2SSimon Glass        This creates a new device tree of size @size and moves the existing
421*3def0cf2SSimon Glass        device tree contents over to that. It can be used to create more space
422*3def0cf2SSimon Glass        in a device tree.
42315b97f5cSMasahiro Yamada
42415b97f5cSMasahiro Yamada        Args:
425*3def0cf2SSimon Glass            size: Required new size of device tree in bytes
42615b97f5cSMasahiro Yamada        """
427*3def0cf2SSimon Glass        fdt = bytearray(size)
428*3def0cf2SSimon Glass        fdt[:len(self._fdt)] = self._fdt
429*3def0cf2SSimon Glass        err = check_err(fdt_open_into(self._fdt, fdt, size), quiet)
430*3def0cf2SSimon Glass        if err:
431*3def0cf2SSimon Glass            return err
432*3def0cf2SSimon Glass        self._fdt = fdt
43315b97f5cSMasahiro Yamada
43415b97f5cSMasahiro Yamada    def pack(self, quiet=()):
43515b97f5cSMasahiro Yamada        """Pack the device tree to remove unused space
43615b97f5cSMasahiro Yamada
43715b97f5cSMasahiro Yamada        This adjusts the tree in place.
43815b97f5cSMasahiro Yamada
43915b97f5cSMasahiro Yamada        Args:
44015b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
44115b97f5cSMasahiro Yamada
44215b97f5cSMasahiro Yamada        Raises:
44315b97f5cSMasahiro Yamada            FdtException if any error occurs
44415b97f5cSMasahiro Yamada        """
44515b97f5cSMasahiro Yamada        return check_err(fdt_pack(self._fdt), quiet)
44615b97f5cSMasahiro Yamada
44715b97f5cSMasahiro Yamada    def getprop(self, nodeoffset, prop_name, quiet=()):
44815b97f5cSMasahiro Yamada        """Get a property from a node
44915b97f5cSMasahiro Yamada
45015b97f5cSMasahiro Yamada        Args:
45115b97f5cSMasahiro Yamada            nodeoffset: Node offset containing property to get
45215b97f5cSMasahiro Yamada            prop_name: Name of property to get
45315b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
45415b97f5cSMasahiro Yamada
45515b97f5cSMasahiro Yamada        Returns:
456*3def0cf2SSimon Glass            Value of property as a string, or -ve error number
45715b97f5cSMasahiro Yamada
45815b97f5cSMasahiro Yamada        Raises:
45915b97f5cSMasahiro Yamada            FdtError if any error occurs (e.g. the property is not found)
46015b97f5cSMasahiro Yamada        """
46115b97f5cSMasahiro Yamada        pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
46215b97f5cSMasahiro Yamada                               quiet)
46315b97f5cSMasahiro Yamada        if isinstance(pdata, (int)):
46415b97f5cSMasahiro Yamada            return pdata
465*3def0cf2SSimon Glass        return str(pdata[0])
466*3def0cf2SSimon Glass
467*3def0cf2SSimon Glass    def getprop_obj(self, nodeoffset, prop_name, quiet=()):
468*3def0cf2SSimon Glass        """Get a property from a node as a Property object
469*3def0cf2SSimon Glass
470*3def0cf2SSimon Glass        Args:
471*3def0cf2SSimon Glass            nodeoffset: Node offset containing property to get
472*3def0cf2SSimon Glass            prop_name: Name of property to get
473*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
474*3def0cf2SSimon Glass
475*3def0cf2SSimon Glass        Returns:
476*3def0cf2SSimon Glass            Property object, or None if not found
477*3def0cf2SSimon Glass
478*3def0cf2SSimon Glass        Raises:
479*3def0cf2SSimon Glass            FdtError if any error occurs (e.g. the property is not found)
480*3def0cf2SSimon Glass        """
481*3def0cf2SSimon Glass        pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
482*3def0cf2SSimon Glass                               quiet)
483*3def0cf2SSimon Glass        if isinstance(pdata, (int)):
484*3def0cf2SSimon Glass            return None
485*3def0cf2SSimon Glass        return Property(prop_name, bytearray(pdata[0]))
48615b97f5cSMasahiro Yamada
48715b97f5cSMasahiro Yamada    def get_phandle(self, nodeoffset):
48815b97f5cSMasahiro Yamada        """Get the phandle of a node
48915b97f5cSMasahiro Yamada
49015b97f5cSMasahiro Yamada        Args:
49115b97f5cSMasahiro Yamada            nodeoffset: Node offset to check
49215b97f5cSMasahiro Yamada
49315b97f5cSMasahiro Yamada        Returns:
49415b97f5cSMasahiro Yamada            phandle of node, or 0 if the node has no phandle or another error
49515b97f5cSMasahiro Yamada            occurs
49615b97f5cSMasahiro Yamada        """
49715b97f5cSMasahiro Yamada        return fdt_get_phandle(self._fdt, nodeoffset)
49815b97f5cSMasahiro Yamada
49915b97f5cSMasahiro Yamada    def parent_offset(self, nodeoffset, quiet=()):
50015b97f5cSMasahiro Yamada        """Get the offset of a node's parent
50115b97f5cSMasahiro Yamada
50215b97f5cSMasahiro Yamada        Args:
50315b97f5cSMasahiro Yamada            nodeoffset: Node offset to check
50415b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
50515b97f5cSMasahiro Yamada
50615b97f5cSMasahiro Yamada        Returns:
50715b97f5cSMasahiro Yamada            The offset of the parent node, if any
50815b97f5cSMasahiro Yamada
50915b97f5cSMasahiro Yamada        Raises:
51015b97f5cSMasahiro Yamada            FdtException if no parent found or other error occurs
51115b97f5cSMasahiro Yamada        """
51215b97f5cSMasahiro Yamada        return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
51315b97f5cSMasahiro Yamada
514*3def0cf2SSimon Glass    def set_name(self, nodeoffset, name, quiet=()):
515*3def0cf2SSimon Glass        """Set the name of a node
516*3def0cf2SSimon Glass
517*3def0cf2SSimon Glass        Args:
518*3def0cf2SSimon Glass            nodeoffset: Node offset of node to update
519*3def0cf2SSimon Glass            name: New node name
520*3def0cf2SSimon Glass
521*3def0cf2SSimon Glass        Returns:
522*3def0cf2SSimon Glass            Error code, or 0 if OK
523*3def0cf2SSimon Glass
524*3def0cf2SSimon Glass        Raises:
525*3def0cf2SSimon Glass            FdtException if no parent found or other error occurs
526*3def0cf2SSimon Glass        """
527*3def0cf2SSimon Glass        return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet)
528*3def0cf2SSimon Glass
529*3def0cf2SSimon Glass    def setprop(self, nodeoffset, prop_name, val, quiet=()):
530*3def0cf2SSimon Glass        """Set the value of a property
531*3def0cf2SSimon Glass
532*3def0cf2SSimon Glass        Args:
533*3def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
534*3def0cf2SSimon Glass            prop_name: Name of property
535*3def0cf2SSimon Glass            val: Value to write (string or bytearray)
536*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
537*3def0cf2SSimon Glass
538*3def0cf2SSimon Glass        Returns:
539*3def0cf2SSimon Glass            Error code, or 0 if OK
540*3def0cf2SSimon Glass
541*3def0cf2SSimon Glass        Raises:
542*3def0cf2SSimon Glass            FdtException if no parent found or other error occurs
543*3def0cf2SSimon Glass        """
544*3def0cf2SSimon Glass        return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
545*3def0cf2SSimon Glass                                     len(val)), quiet)
546*3def0cf2SSimon Glass
547*3def0cf2SSimon Glass    def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
548*3def0cf2SSimon Glass        """Set the value of a property
549*3def0cf2SSimon Glass
550*3def0cf2SSimon Glass        Args:
551*3def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
552*3def0cf2SSimon Glass            prop_name: Name of property
553*3def0cf2SSimon Glass            val: Value to write (integer)
554*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
555*3def0cf2SSimon Glass
556*3def0cf2SSimon Glass        Returns:
557*3def0cf2SSimon Glass            Error code, or 0 if OK
558*3def0cf2SSimon Glass
559*3def0cf2SSimon Glass        Raises:
560*3def0cf2SSimon Glass            FdtException if no parent found or other error occurs
561*3def0cf2SSimon Glass        """
562*3def0cf2SSimon Glass        return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val),
563*3def0cf2SSimon Glass                         quiet)
564*3def0cf2SSimon Glass
565*3def0cf2SSimon Glass    def setprop_u64(self, nodeoffset, prop_name, val, quiet=()):
566*3def0cf2SSimon Glass        """Set the value of a property
567*3def0cf2SSimon Glass
568*3def0cf2SSimon Glass        Args:
569*3def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
570*3def0cf2SSimon Glass            prop_name: Name of property
571*3def0cf2SSimon Glass            val: Value to write (integer)
572*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
573*3def0cf2SSimon Glass
574*3def0cf2SSimon Glass        Returns:
575*3def0cf2SSimon Glass            Error code, or 0 if OK
576*3def0cf2SSimon Glass
577*3def0cf2SSimon Glass        Raises:
578*3def0cf2SSimon Glass            FdtException if no parent found or other error occurs
579*3def0cf2SSimon Glass        """
580*3def0cf2SSimon Glass        return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val),
581*3def0cf2SSimon Glass                         quiet)
582*3def0cf2SSimon Glass
583*3def0cf2SSimon Glass    def setprop_str(self, nodeoffset, prop_name, val, quiet=()):
584*3def0cf2SSimon Glass        """Set the string value of a property
585*3def0cf2SSimon Glass
586*3def0cf2SSimon Glass        The property is set to the string, with a nul terminator added
587*3def0cf2SSimon Glass
588*3def0cf2SSimon Glass        Args:
589*3def0cf2SSimon Glass            nodeoffset: Node offset containing the property to create/update
590*3def0cf2SSimon Glass            prop_name: Name of property
591*3def0cf2SSimon Glass            val: Value to write (string without nul terminator)
592*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
593*3def0cf2SSimon Glass
594*3def0cf2SSimon Glass        Returns:
595*3def0cf2SSimon Glass            Error code, or 0 if OK
596*3def0cf2SSimon Glass
597*3def0cf2SSimon Glass        Raises:
598*3def0cf2SSimon Glass            FdtException if no parent found or other error occurs
599*3def0cf2SSimon Glass        """
600*3def0cf2SSimon Glass        val += '\0'
601*3def0cf2SSimon Glass        return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name,
602*3def0cf2SSimon Glass                                     val, len(val)), quiet)
603*3def0cf2SSimon Glass
604*3def0cf2SSimon Glass    def delprop(self, nodeoffset, prop_name):
605*3def0cf2SSimon Glass        """Delete a property from a node
606*3def0cf2SSimon Glass
607*3def0cf2SSimon Glass        Args:
608*3def0cf2SSimon Glass            nodeoffset: Node offset containing property to delete
609*3def0cf2SSimon Glass            prop_name: Name of property to delete
610*3def0cf2SSimon Glass
611*3def0cf2SSimon Glass        Raises:
612*3def0cf2SSimon Glass            FdtError if the property does not exist, or another error occurs
613*3def0cf2SSimon Glass        """
614*3def0cf2SSimon Glass        return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
615*3def0cf2SSimon Glass
61615b97f5cSMasahiro Yamada    def node_offset_by_phandle(self, phandle, quiet=()):
61715b97f5cSMasahiro Yamada        """Get the offset of a node with the given phandle
61815b97f5cSMasahiro Yamada
61915b97f5cSMasahiro Yamada        Args:
62015b97f5cSMasahiro Yamada            phandle: Phandle to search for
62115b97f5cSMasahiro Yamada            quiet: Errors to ignore (empty to raise on all errors)
62215b97f5cSMasahiro Yamada
62315b97f5cSMasahiro Yamada        Returns:
62415b97f5cSMasahiro Yamada            The offset of node with that phandle, if any
62515b97f5cSMasahiro Yamada
62615b97f5cSMasahiro Yamada        Raises:
62715b97f5cSMasahiro Yamada            FdtException if no node found or other error occurs
62815b97f5cSMasahiro Yamada        """
62915b97f5cSMasahiro Yamada        return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
63015b97f5cSMasahiro Yamada
631*3def0cf2SSimon Glass
632*3def0cf2SSimon Glassclass Property(bytearray):
63315b97f5cSMasahiro Yamada    """Holds a device tree property name and value.
63415b97f5cSMasahiro Yamada
63515b97f5cSMasahiro Yamada    This holds a copy of a property taken from the device tree. It does not
63615b97f5cSMasahiro Yamada    reference the device tree, so if anything changes in the device tree,
63715b97f5cSMasahiro Yamada    a Property object will remain valid.
63815b97f5cSMasahiro Yamada
63915b97f5cSMasahiro Yamada    Properties:
64015b97f5cSMasahiro Yamada        name: Property name
641*3def0cf2SSimon Glass        value: Property value as a bytearray
64215b97f5cSMasahiro Yamada    """
64315b97f5cSMasahiro Yamada    def __init__(self, name, value):
644*3def0cf2SSimon Glass        bytearray.__init__(self, value)
64515b97f5cSMasahiro Yamada        self.name = name
646*3def0cf2SSimon Glass
647*3def0cf2SSimon Glass    def as_cell(self, fmt):
648*3def0cf2SSimon Glass        return struct.unpack('>' + fmt, self)[0]
649*3def0cf2SSimon Glass
650*3def0cf2SSimon Glass    def as_uint32(self):
651*3def0cf2SSimon Glass        return self.as_cell('L')
652*3def0cf2SSimon Glass
653*3def0cf2SSimon Glass    def as_int32(self):
654*3def0cf2SSimon Glass        return self.as_cell('l')
655*3def0cf2SSimon Glass
656*3def0cf2SSimon Glass    def as_uint64(self):
657*3def0cf2SSimon Glass        return self.as_cell('Q')
658*3def0cf2SSimon Glass
659*3def0cf2SSimon Glass    def as_int64(self):
660*3def0cf2SSimon Glass        return self.as_cell('q')
661*3def0cf2SSimon Glass
662*3def0cf2SSimon Glass    def as_str(self):
663*3def0cf2SSimon Glass        return self[:-1]
664*3def0cf2SSimon Glass
665*3def0cf2SSimon Glass
666*3def0cf2SSimon Glassclass FdtSw(object):
667*3def0cf2SSimon Glass    """Software interface to create a device tree from scratch
668*3def0cf2SSimon Glass
669*3def0cf2SSimon Glass    The methods in this class work by adding to an existing 'partial' device
670*3def0cf2SSimon Glass    tree buffer of a fixed size created by instantiating this class. When the
671*3def0cf2SSimon Glass    tree is complete, call finish() to complete the device tree so that it can
672*3def0cf2SSimon Glass    be used.
673*3def0cf2SSimon Glass
674*3def0cf2SSimon Glass    Similarly with nodes, a new node is started with begin_node() and finished
675*3def0cf2SSimon Glass    with end_node().
676*3def0cf2SSimon Glass
677*3def0cf2SSimon Glass    The context manager functions can be used to make this a bit easier:
678*3def0cf2SSimon Glass
679*3def0cf2SSimon Glass    # First create the device tree with a node and property:
680*3def0cf2SSimon Glass    with FdtSw(small_size) as sw:
681*3def0cf2SSimon Glass        with sw.AddNode('node'):
682*3def0cf2SSimon Glass            sw.property_u32('reg', 2)
683*3def0cf2SSimon Glass    fdt = sw.AsFdt()
684*3def0cf2SSimon Glass
685*3def0cf2SSimon Glass    # Now we can use it as a real device tree
686*3def0cf2SSimon Glass    fdt.setprop_u32(0, 'reg', 3)
687*3def0cf2SSimon Glass    """
688*3def0cf2SSimon Glass    def __init__(self, size, quiet=()):
689*3def0cf2SSimon Glass        fdtrw = bytearray(size)
690*3def0cf2SSimon Glass        err = check_err(fdt_create(fdtrw, size))
691*3def0cf2SSimon Glass        if err:
692*3def0cf2SSimon Glass            return err
693*3def0cf2SSimon Glass        self._fdtrw = fdtrw
694*3def0cf2SSimon Glass
695*3def0cf2SSimon Glass    def __enter__(self):
696*3def0cf2SSimon Glass        """Contact manager to use to create a device tree via software"""
697*3def0cf2SSimon Glass        return self
698*3def0cf2SSimon Glass
699*3def0cf2SSimon Glass    def __exit__(self, type, value, traceback):
700*3def0cf2SSimon Glass        check_err(fdt_finish(self._fdtrw))
701*3def0cf2SSimon Glass
702*3def0cf2SSimon Glass    def AsFdt(self):
703*3def0cf2SSimon Glass        """Convert a FdtSw into an Fdt so it can be accessed as normal
704*3def0cf2SSimon Glass
705*3def0cf2SSimon Glass        Note that finish() must be called before this function will work. If
706*3def0cf2SSimon Glass        you are using the context manager (see 'with' code in the FdtSw class
707*3def0cf2SSimon Glass        comment) then this will happen automatically.
708*3def0cf2SSimon Glass
709*3def0cf2SSimon Glass        Returns:
710*3def0cf2SSimon Glass            Fdt object allowing access to the newly created device tree
711*3def0cf2SSimon Glass        """
712*3def0cf2SSimon Glass        return Fdt(self._fdtrw)
713*3def0cf2SSimon Glass
714*3def0cf2SSimon Glass    def resize(self, size, quiet=()):
715*3def0cf2SSimon Glass        """Resize the buffer to accommodate a larger tree
716*3def0cf2SSimon Glass
717*3def0cf2SSimon Glass        Args:
718*3def0cf2SSimon Glass            size: New size of tree
719*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
720*3def0cf2SSimon Glass
721*3def0cf2SSimon Glass        Raises:
722*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
723*3def0cf2SSimon Glass        """
724*3def0cf2SSimon Glass        fdt = bytearray(size)
725*3def0cf2SSimon Glass        fdt[:len(self._fdtrw)] = self._fdtrw
726*3def0cf2SSimon Glass        err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet)
727*3def0cf2SSimon Glass        if err:
728*3def0cf2SSimon Glass            return err
729*3def0cf2SSimon Glass        self._fdtrw = fdt
730*3def0cf2SSimon Glass
731*3def0cf2SSimon Glass    def add_reservemap_entry(self, addr, size, quiet=()):
732*3def0cf2SSimon Glass        """Add a new memory reserve map entry
733*3def0cf2SSimon Glass
734*3def0cf2SSimon Glass        Once finished adding, you must call finish_reservemap().
735*3def0cf2SSimon Glass
736*3def0cf2SSimon Glass        Args:
737*3def0cf2SSimon Glass            addr: 64-bit start address
738*3def0cf2SSimon Glass            size: 64-bit size
739*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
740*3def0cf2SSimon Glass
741*3def0cf2SSimon Glass        Raises:
742*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
743*3def0cf2SSimon Glass        """
744*3def0cf2SSimon Glass        return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size),
745*3def0cf2SSimon Glass                         quiet)
746*3def0cf2SSimon Glass
747*3def0cf2SSimon Glass    def finish_reservemap(self, quiet=()):
748*3def0cf2SSimon Glass        """Indicate that there are no more reserve map entries to add
749*3def0cf2SSimon Glass
750*3def0cf2SSimon Glass        Args:
751*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
752*3def0cf2SSimon Glass
753*3def0cf2SSimon Glass        Raises:
754*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
755*3def0cf2SSimon Glass        """
756*3def0cf2SSimon Glass        return check_err(fdt_finish_reservemap(self._fdtrw), quiet)
757*3def0cf2SSimon Glass
758*3def0cf2SSimon Glass    def begin_node(self, name, quiet=()):
759*3def0cf2SSimon Glass        """Begin a new node
760*3def0cf2SSimon Glass
761*3def0cf2SSimon Glass        Use this before adding properties to the node. Then call end_node() to
762*3def0cf2SSimon Glass        finish it. You can also use the context manager as shown in the FdtSw
763*3def0cf2SSimon Glass        class comment.
764*3def0cf2SSimon Glass
765*3def0cf2SSimon Glass        Args:
766*3def0cf2SSimon Glass            name: Name of node to begin
767*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
768*3def0cf2SSimon Glass
769*3def0cf2SSimon Glass        Raises:
770*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
771*3def0cf2SSimon Glass        """
772*3def0cf2SSimon Glass        return check_err(fdt_begin_node(self._fdtrw, name), quiet)
773*3def0cf2SSimon Glass
774*3def0cf2SSimon Glass    def property_string(self, name, string, quiet=()):
775*3def0cf2SSimon Glass        """Add a property with a string value
776*3def0cf2SSimon Glass
777*3def0cf2SSimon Glass        The string will be nul-terminated when written to the device tree
778*3def0cf2SSimon Glass
779*3def0cf2SSimon Glass        Args:
780*3def0cf2SSimon Glass            name: Name of property to add
781*3def0cf2SSimon Glass            string: String value of property
782*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
783*3def0cf2SSimon Glass
784*3def0cf2SSimon Glass        Raises:
785*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
786*3def0cf2SSimon Glass        """
787*3def0cf2SSimon Glass        return check_err(fdt_property_string(self._fdtrw, name, string), quiet)
788*3def0cf2SSimon Glass
789*3def0cf2SSimon Glass    def property_u32(self, name, val, quiet=()):
790*3def0cf2SSimon Glass        """Add a property with a 32-bit value
791*3def0cf2SSimon Glass
792*3def0cf2SSimon Glass        Write a single-cell value to the device tree
793*3def0cf2SSimon Glass
794*3def0cf2SSimon Glass        Args:
795*3def0cf2SSimon Glass            name: Name of property to add
796*3def0cf2SSimon Glass            val: Value of property
797*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
798*3def0cf2SSimon Glass
799*3def0cf2SSimon Glass        Raises:
800*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
801*3def0cf2SSimon Glass        """
802*3def0cf2SSimon Glass        return check_err(fdt_property_u32(self._fdtrw, name, val), quiet)
803*3def0cf2SSimon Glass
804*3def0cf2SSimon Glass    def property_u64(self, name, val, quiet=()):
805*3def0cf2SSimon Glass        """Add a property with a 64-bit value
806*3def0cf2SSimon Glass
807*3def0cf2SSimon Glass        Write a double-cell value to the device tree in big-endian format
808*3def0cf2SSimon Glass
809*3def0cf2SSimon Glass        Args:
810*3def0cf2SSimon Glass            name: Name of property to add
811*3def0cf2SSimon Glass            val: Value of property
812*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
813*3def0cf2SSimon Glass
814*3def0cf2SSimon Glass        Raises:
815*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
816*3def0cf2SSimon Glass        """
817*3def0cf2SSimon Glass        return check_err(fdt_property_u64(self._fdtrw, name, val), quiet)
818*3def0cf2SSimon Glass
819*3def0cf2SSimon Glass    def property_cell(self, name, val, quiet=()):
820*3def0cf2SSimon Glass        """Add a property with a single-cell value
821*3def0cf2SSimon Glass
822*3def0cf2SSimon Glass        Write a single-cell value to the device tree
823*3def0cf2SSimon Glass
824*3def0cf2SSimon Glass        Args:
825*3def0cf2SSimon Glass            name: Name of property to add
826*3def0cf2SSimon Glass            val: Value of property
827*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
828*3def0cf2SSimon Glass
829*3def0cf2SSimon Glass        Raises:
830*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
831*3def0cf2SSimon Glass        """
832*3def0cf2SSimon Glass        return check_err(fdt_property_cell(self._fdtrw, name, val), quiet)
833*3def0cf2SSimon Glass
834*3def0cf2SSimon Glass    def property(self, name, val, quiet=()):
835*3def0cf2SSimon Glass        """Add a property
836*3def0cf2SSimon Glass
837*3def0cf2SSimon Glass        Write a new property with the given value to the device tree. The value
838*3def0cf2SSimon Glass        is taken as is and is not nul-terminated
839*3def0cf2SSimon Glass
840*3def0cf2SSimon Glass        Args:
841*3def0cf2SSimon Glass            name: Name of property to add
842*3def0cf2SSimon Glass            val: Value of property
843*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
844*3def0cf2SSimon Glass
845*3def0cf2SSimon Glass        Raises:
846*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
847*3def0cf2SSimon Glass        """
848*3def0cf2SSimon Glass        return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet)
849*3def0cf2SSimon Glass
850*3def0cf2SSimon Glass    def end_node(self, quiet=()):
851*3def0cf2SSimon Glass        """End a node
852*3def0cf2SSimon Glass
853*3def0cf2SSimon Glass        Use this after adding properties to a node to close it off. You can also
854*3def0cf2SSimon Glass        use the context manager as shown in the FdtSw class comment.
855*3def0cf2SSimon Glass
856*3def0cf2SSimon Glass        Args:
857*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
858*3def0cf2SSimon Glass
859*3def0cf2SSimon Glass        Raises:
860*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
861*3def0cf2SSimon Glass        """
862*3def0cf2SSimon Glass        return check_err(fdt_end_node(self._fdtrw), quiet)
863*3def0cf2SSimon Glass
864*3def0cf2SSimon Glass    def finish(self, quiet=()):
865*3def0cf2SSimon Glass        """Finish writing the device tree
866*3def0cf2SSimon Glass
867*3def0cf2SSimon Glass        This closes off the device tree ready for use
868*3def0cf2SSimon Glass
869*3def0cf2SSimon Glass        Args:
870*3def0cf2SSimon Glass            quiet: Errors to ignore (empty to raise on all errors)
871*3def0cf2SSimon Glass
872*3def0cf2SSimon Glass        Raises:
873*3def0cf2SSimon Glass            FdtException if no node found or other error occurs
874*3def0cf2SSimon Glass        """
875*3def0cf2SSimon Glass        return check_err(fdt_finish(self._fdtrw), quiet)
876*3def0cf2SSimon Glass
877*3def0cf2SSimon Glass    def AddNode(self, name):
878*3def0cf2SSimon Glass        """Create a new context for adding a node
879*3def0cf2SSimon Glass
880*3def0cf2SSimon Glass        When used in a 'with' clause this starts a new node and finishes it
881*3def0cf2SSimon Glass        afterward.
882*3def0cf2SSimon Glass
883*3def0cf2SSimon Glass        Args:
884*3def0cf2SSimon Glass            name: Name of node to add
885*3def0cf2SSimon Glass        """
886*3def0cf2SSimon Glass        return NodeAdder(self._fdtrw, name)
887*3def0cf2SSimon Glass
888*3def0cf2SSimon Glass
889*3def0cf2SSimon Glassclass NodeAdder():
890*3def0cf2SSimon Glass    """Class to provide a node context
891*3def0cf2SSimon Glass
892*3def0cf2SSimon Glass    This allows you to add nodes in a more natural way:
893*3def0cf2SSimon Glass
894*3def0cf2SSimon Glass        with fdtsw.AddNode('name'):
895*3def0cf2SSimon Glass            fdtsw.property_string('test', 'value')
896*3def0cf2SSimon Glass
897*3def0cf2SSimon Glass    The node is automatically completed with a call to end_node() when the
898*3def0cf2SSimon Glass    context exits.
899*3def0cf2SSimon Glass    """
900*3def0cf2SSimon Glass    def __init__(self, fdt, name):
901*3def0cf2SSimon Glass        self._fdt = fdt
902*3def0cf2SSimon Glass        self._name = name
903*3def0cf2SSimon Glass
904*3def0cf2SSimon Glass    def __enter__(self):
905*3def0cf2SSimon Glass        check_err(fdt_begin_node(self._fdt, self._name))
906*3def0cf2SSimon Glass
907*3def0cf2SSimon Glass    def __exit__(self, type, value, traceback):
908*3def0cf2SSimon Glass        check_err(fdt_end_node(self._fdt))
90915b97f5cSMasahiro Yamada%}
91015b97f5cSMasahiro Yamada
91115b97f5cSMasahiro Yamada%rename(fdt_property) fdt_property_func;
91215b97f5cSMasahiro Yamada
91315b97f5cSMasahiro Yamadatypedef int fdt32_t;
91415b97f5cSMasahiro Yamada
91515b97f5cSMasahiro Yamada%include "libfdt/fdt.h"
91615b97f5cSMasahiro Yamada
91715b97f5cSMasahiro Yamada%include "typemaps.i"
91815b97f5cSMasahiro Yamada
91915b97f5cSMasahiro Yamada/* Most functions don't change the device tree, so use a const void * */
92015b97f5cSMasahiro Yamada%typemap(in) (const void *)(const void *fdt) {
92115b97f5cSMasahiro Yamada	if (!PyByteArray_Check($input)) {
92215b97f5cSMasahiro Yamada		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
92315b97f5cSMasahiro Yamada			"', argument " "$argnum"" of type '" "$type""'");
92415b97f5cSMasahiro Yamada	}
92515b97f5cSMasahiro Yamada	$1 = (void *)PyByteArray_AsString($input);
92615b97f5cSMasahiro Yamada        fdt = $1;
92715b97f5cSMasahiro Yamada        fdt = fdt; /* avoid unused variable warning */
92815b97f5cSMasahiro Yamada}
92915b97f5cSMasahiro Yamada
93015b97f5cSMasahiro Yamada/* Some functions do change the device tree, so use void * */
93115b97f5cSMasahiro Yamada%typemap(in) (void *)(const void *fdt) {
93215b97f5cSMasahiro Yamada	if (!PyByteArray_Check($input)) {
93315b97f5cSMasahiro Yamada		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
93415b97f5cSMasahiro Yamada			"', argument " "$argnum"" of type '" "$type""'");
93515b97f5cSMasahiro Yamada	}
93615b97f5cSMasahiro Yamada	$1 = PyByteArray_AsString($input);
93715b97f5cSMasahiro Yamada        fdt = $1;
93815b97f5cSMasahiro Yamada        fdt = fdt; /* avoid unused variable warning */
93915b97f5cSMasahiro Yamada}
94015b97f5cSMasahiro Yamada
941*3def0cf2SSimon Glass/* typemap used for fdt_get_property_by_offset() */
94215b97f5cSMasahiro Yamada%typemap(out) (struct fdt_property *) {
94315b97f5cSMasahiro Yamada	PyObject *buff;
94415b97f5cSMasahiro Yamada
94515b97f5cSMasahiro Yamada	if ($1) {
94615b97f5cSMasahiro Yamada		resultobj = PyString_FromString(
94715b97f5cSMasahiro Yamada			fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
94815b97f5cSMasahiro Yamada		buff = PyByteArray_FromStringAndSize(
94915b97f5cSMasahiro Yamada			(const char *)($1 + 1), fdt32_to_cpu($1->len));
95015b97f5cSMasahiro Yamada		resultobj = SWIG_Python_AppendOutput(resultobj, buff);
95115b97f5cSMasahiro Yamada	}
95215b97f5cSMasahiro Yamada}
95315b97f5cSMasahiro Yamada
95415b97f5cSMasahiro Yamada%apply int *OUTPUT { int *lenp };
95515b97f5cSMasahiro Yamada
95615b97f5cSMasahiro Yamada/* typemap used for fdt_getprop() */
95715b97f5cSMasahiro Yamada%typemap(out) (const void *) {
95815b97f5cSMasahiro Yamada	if (!$1)
95915b97f5cSMasahiro Yamada		$result = Py_None;
96015b97f5cSMasahiro Yamada	else
96115b97f5cSMasahiro Yamada		$result = Py_BuildValue("s#", $1, *arg4);
96215b97f5cSMasahiro Yamada}
96315b97f5cSMasahiro Yamada
964*3def0cf2SSimon Glass/* typemap used for fdt_setprop() */
965*3def0cf2SSimon Glass%typemap(in) (const void *val) {
966*3def0cf2SSimon Glass    $1 = PyString_AsString($input);   /* char *str */
967*3def0cf2SSimon Glass}
968*3def0cf2SSimon Glass
969*3def0cf2SSimon Glass/* typemap used for fdt_add_reservemap_entry() */
970*3def0cf2SSimon Glass%typemap(in) uint64_t {
971*3def0cf2SSimon Glass   $1 = PyLong_AsUnsignedLong($input);
972*3def0cf2SSimon Glass}
973*3def0cf2SSimon Glass
974*3def0cf2SSimon Glass/* typemaps used for fdt_next_node() */
975*3def0cf2SSimon Glass%typemap(in, numinputs=1) int *depth (int depth) {
976*3def0cf2SSimon Glass   depth = (int) PyInt_AsLong($input);
977*3def0cf2SSimon Glass   $1 = &depth;
978*3def0cf2SSimon Glass}
979*3def0cf2SSimon Glass
980*3def0cf2SSimon Glass%typemap(argout) int *depth {
981*3def0cf2SSimon Glass        PyObject *val = Py_BuildValue("i", *arg$argnum);
982*3def0cf2SSimon Glass        resultobj = SWIG_Python_AppendOutput(resultobj, val);
983*3def0cf2SSimon Glass}
984*3def0cf2SSimon Glass
985*3def0cf2SSimon Glass%apply int *depth { int *depth };
986*3def0cf2SSimon Glass
987*3def0cf2SSimon Glass/* typemaps for fdt_get_mem_rsv */
988*3def0cf2SSimon Glass%typemap(in, numinputs=0) uint64_t * (uint64_t temp) {
989*3def0cf2SSimon Glass   $1 = &temp;
990*3def0cf2SSimon Glass}
991*3def0cf2SSimon Glass
992*3def0cf2SSimon Glass%typemap(argout) uint64_t * {
993*3def0cf2SSimon Glass        PyObject *val = PyLong_FromUnsignedLong(*arg$argnum);
994*3def0cf2SSimon Glass        if (!result) {
995*3def0cf2SSimon Glass           if (PyTuple_GET_SIZE(resultobj) == 0)
996*3def0cf2SSimon Glass              resultobj = val;
997*3def0cf2SSimon Glass           else
998*3def0cf2SSimon Glass              resultobj = SWIG_Python_AppendOutput(resultobj, val);
999*3def0cf2SSimon Glass        }
1000*3def0cf2SSimon Glass}
1001*3def0cf2SSimon Glass
100215b97f5cSMasahiro Yamada/* We have both struct fdt_property and a function fdt_property() */
100315b97f5cSMasahiro Yamada%warnfilter(302) fdt_property;
100415b97f5cSMasahiro Yamada
100515b97f5cSMasahiro Yamada/* These are macros in the header so have to be redefined here */
100615b97f5cSMasahiro Yamadaint fdt_magic(const void *fdt);
100715b97f5cSMasahiro Yamadaint fdt_totalsize(const void *fdt);
100815b97f5cSMasahiro Yamadaint fdt_off_dt_struct(const void *fdt);
100915b97f5cSMasahiro Yamadaint fdt_off_dt_strings(const void *fdt);
101015b97f5cSMasahiro Yamadaint fdt_off_mem_rsvmap(const void *fdt);
101115b97f5cSMasahiro Yamadaint fdt_version(const void *fdt);
101215b97f5cSMasahiro Yamadaint fdt_last_comp_version(const void *fdt);
101315b97f5cSMasahiro Yamadaint fdt_boot_cpuid_phys(const void *fdt);
101415b97f5cSMasahiro Yamadaint fdt_size_dt_strings(const void *fdt);
101515b97f5cSMasahiro Yamadaint fdt_size_dt_struct(const void *fdt);
1016*3def0cf2SSimon Glassint fdt_property_string(void *fdt, const char *name, const char *val);
1017*3def0cf2SSimon Glassint fdt_property_cell(void *fdt, const char *name, uint32_t val);
1018*3def0cf2SSimon Glass
1019*3def0cf2SSimon Glass/*
1020*3def0cf2SSimon Glass * This function has a stub since the name fdt_property is used for both a
1021*3def0cf2SSimon Glass  * function and a struct, which confuses SWIG.
1022*3def0cf2SSimon Glass */
1023*3def0cf2SSimon Glassint _fdt_property(void *fdt, const char *name, const char *val, int len);
102415b97f5cSMasahiro Yamada
102515b97f5cSMasahiro Yamada%include <../libfdt/libfdt.h>
1026