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