2 * pylibfdt - Flat Device Tree manipulation in Python
3 * Copyright (C) 2017 Google, Inc.
4 * Written by Simon Glass <sjg@chromium.org>
6 * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
14 #define SWIG_FILE_WITH_INIT
22 # Error codes, corresponding to FDT_ERR_... in libfdt.h
39 NOPHANDLES) = QUIET_ALL = range(1, 18)
40 # QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
41 # altogether. All # functions passed this value will return an error instead
42 # of raising an exception.
44 # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
45 # instead of raising an exception.
46 QUIET_NOTFOUND = (NOTFOUND,)
49 class FdtException(Exception):
50 """An exception caused by an error such as one of the codes above"""
51 def __init__(self, err):
55 return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
57 def strerror(fdt_err):
58 """Get the string for an error number
61 fdt_err: Error number (-ve)
64 String containing the associated error
66 return fdt_strerror(fdt_err)
68 def check_err(val, quiet=()):
69 """Raise an error if the return value is -ve
71 This is used to check for errors returned by libfdt C functions.
74 val: Return value from a libfdt function
75 quiet: Errors to ignore (empty to raise on all errors)
81 FdtException if val < 0
85 raise FdtException(val)
88 def check_err_null(val, quiet=()):
89 """Raise an error if the return value is NULL
91 This is used to check for a NULL return value from certain libfdt C
95 val: Return value from a libfdt function
96 quiet: Errors to ignore (empty to raise on all errors)
99 val if val is a list, None if not
102 FdtException if val indicates an error was reported and the error
105 # Normally a list is returned which contains the data and its length.
106 # If we get just an integer error code, it means the function failed.
107 if not isinstance(val, list):
108 if -val not in quiet:
109 raise FdtException(val)
113 """Device tree class, supporting all operations
115 The Fdt object is created is created from a device tree binary file,
116 e.g. with something like:
118 fdt = Fdt(open("filename.dtb").read())
120 Operations can then be performed using the methods in this class. Each
121 method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
123 All methods raise an FdtException if an error occurs. To avoid this
124 behaviour a 'quiet' parameter is provided for some functions. This
125 defaults to empty, but you can pass a list of errors that you expect.
126 If one of these errors occurs, the function will return an error number
129 def __init__(self, data):
130 self._fdt = bytearray(data)
131 check_err(fdt_check_header(self._fdt));
133 def subnode_offset(self, parentoffset, name, quiet=()):
134 """Get the offset of a named subnode
137 parentoffset: Offset of the parent node to check
138 name: Name of the required subnode, e.g. 'subnode@1'
139 quiet: Errors to ignore (empty to raise on all errors)
142 The node offset of the found node, if any
145 FdtException if there is no node with that name, or other error
147 return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
150 def path_offset(self, path, quiet=()):
151 """Get the offset for a given path
154 path: Path to the required node, e.g. '/node@3/subnode@1'
155 quiet: Errors to ignore (empty to raise on all errors)
161 FdtException if the path is not valid or not found
163 return check_err(fdt_path_offset(self._fdt, path), quiet)
165 def first_property_offset(self, nodeoffset, quiet=()):
166 """Get the offset of the first property in a node offset
169 nodeoffset: Offset to the node to check
170 quiet: Errors to ignore (empty to raise on all errors)
173 Offset of the first property
176 FdtException if the associated node has no properties, or some
179 return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
182 def next_property_offset(self, prop_offset, quiet=()):
183 """Get the next property in a node
186 prop_offset: Offset of the previous property
187 quiet: Errors to ignore (empty to raise on all errors)
190 Offset of the next property
193 FdtException if the associated node has no more properties, or
194 some other error occurred
196 return check_err(fdt_next_property_offset(self._fdt, prop_offset),
199 def get_name(self, nodeoffset):
200 """Get the name of a node
203 nodeoffset: Offset of node to check
209 FdtException on error (e.g. nodeoffset is invalid)
211 return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
213 def get_property_by_offset(self, prop_offset, quiet=()):
214 """Obtains a property that can be examined
217 prop_offset: Offset of property (e.g. from first_property_offset())
218 quiet: Errors to ignore (empty to raise on all errors)
221 Property object, or None if not found
224 FdtException on error (e.g. invalid prop_offset or device
227 pdata = check_err_null(
228 fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
229 if isinstance(pdata, (int)):
231 return Property(pdata[0], pdata[1])
233 def first_subnode(self, nodeoffset, quiet=()):
234 """Find the first subnode of a parent node
237 nodeoffset: Node offset of parent node
238 quiet: Errors to ignore (empty to raise on all errors)
241 The offset of the first subnode, if any
244 FdtException if no subnode found or other error occurs
246 return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
248 def next_subnode(self, nodeoffset, quiet=()):
249 """Find the next subnode
252 nodeoffset: Node offset of previous subnode
253 quiet: Errors to ignore (empty to raise on all errors)
256 The offset of the next subnode, if any
259 FdtException if no more subnode found or other error occurs
261 return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
264 """Return the total size of the device tree
267 Total tree size in bytes
269 return check_err(fdt_totalsize(self._fdt))
271 def off_dt_struct(self):
272 """Return the start of the device tree struct area
275 Start offset of struct area
277 return check_err(fdt_off_dt_struct(self._fdt))
279 def pack(self, quiet=()):
280 """Pack the device tree to remove unused space
282 This adjusts the tree in place.
285 quiet: Errors to ignore (empty to raise on all errors)
288 FdtException if any error occurs
290 return check_err(fdt_pack(self._fdt), quiet)
292 def delprop(self, nodeoffset, prop_name):
293 """Delete a property from a node
296 nodeoffset: Node offset containing property to delete
297 prop_name: Name of property to delete
300 FdtError if the property does not exist, or another error occurs
302 return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
304 def getprop(self, nodeoffset, prop_name, quiet=()):
305 """Get a property from a node
308 nodeoffset: Node offset containing property to get
309 prop_name: Name of property to get
310 quiet: Errors to ignore (empty to raise on all errors)
313 Value of property as a bytearray, or -ve error number
316 FdtError if any error occurs (e.g. the property is not found)
318 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
320 if isinstance(pdata, (int)):
322 return bytearray(pdata[0])
324 def get_phandle(self, nodeoffset):
325 """Get the phandle of a node
328 nodeoffset: Node offset to check
331 phandle of node, or 0 if the node has no phandle or another error
334 return fdt_get_phandle(self._fdt, nodeoffset)
336 def parent_offset(self, nodeoffset, quiet=()):
337 """Get the offset of a node's parent
340 nodeoffset: Node offset to check
341 quiet: Errors to ignore (empty to raise on all errors)
344 The offset of the parent node, if any
347 FdtException if no parent found or other error occurs
349 return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
351 def node_offset_by_phandle(self, phandle, quiet=()):
352 """Get the offset of a node with the given phandle
355 phandle: Phandle to search for
356 quiet: Errors to ignore (empty to raise on all errors)
359 The offset of node with that phandle, if any
362 FdtException if no node found or other error occurs
364 return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
367 """Holds a device tree property name and value.
369 This holds a copy of a property taken from the device tree. It does not
370 reference the device tree, so if anything changes in the device tree,
371 a Property object will remain valid.
375 value: Proper value as a bytearray
377 def __init__(self, name, value):
382 %rename(fdt_property) fdt_property_func;
386 %include "libfdt/fdt.h"
388 %include "typemaps.i"
390 /* Most functions don't change the device tree, so use a const void * */
391 %typemap(in) (const void *)(const void *fdt) {
392 if (!PyByteArray_Check($input)) {
393 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
394 "', argument " "$argnum"" of type '" "$type""'");
396 $1 = (void *)PyByteArray_AsString($input);
398 fdt = fdt; /* avoid unused variable warning */
401 /* Some functions do change the device tree, so use void * */
402 %typemap(in) (void *)(const void *fdt) {
403 if (!PyByteArray_Check($input)) {
404 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
405 "', argument " "$argnum"" of type '" "$type""'");
407 $1 = PyByteArray_AsString($input);
409 fdt = fdt; /* avoid unused variable warning */
412 %typemap(out) (struct fdt_property *) {
416 resultobj = PyString_FromString(
417 fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
418 buff = PyByteArray_FromStringAndSize(
419 (const char *)($1 + 1), fdt32_to_cpu($1->len));
420 resultobj = SWIG_Python_AppendOutput(resultobj, buff);
424 %apply int *OUTPUT { int *lenp };
426 /* typemap used for fdt_getprop() */
427 %typemap(out) (const void *) {
431 $result = Py_BuildValue("s#", $1, *arg4);
434 /* We have both struct fdt_property and a function fdt_property() */
435 %warnfilter(302) fdt_property;
437 /* These are macros in the header so have to be redefined here */
438 int fdt_magic(const void *fdt);
439 int fdt_totalsize(const void *fdt);
440 int fdt_off_dt_struct(const void *fdt);
441 int fdt_off_dt_strings(const void *fdt);
442 int fdt_off_mem_rsvmap(const void *fdt);
443 int fdt_version(const void *fdt);
444 int fdt_last_comp_version(const void *fdt);
445 int fdt_boot_cpuid_phys(const void *fdt);
446 int fdt_size_dt_strings(const void *fdt);
447 int fdt_size_dt_struct(const void *fdt);
449 %include <../libfdt/libfdt.h>