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