1 /* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
3 * pylibfdt - Flat Device Tree manipulation in Python
4 * Copyright (C) 2017 Google, Inc.
5 * Written by Simon Glass <sjg@chromium.org>
13 #define SWIG_FILE_WITH_INIT
21 # Error codes, corresponding to FDT_ERR_... in libfdt.h
38 NOPHANDLES) = QUIET_ALL = range(1, 18)
39 # QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
40 # altogether. All # functions passed this value will return an error instead
41 # of raising an exception.
43 # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
44 # instead of raising an exception.
45 QUIET_NOTFOUND = (NOTFOUND,)
48 class FdtException(Exception):
49 """An exception caused by an error such as one of the codes above"""
50 def __init__(self, err):
54 return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
56 def strerror(fdt_err):
57 """Get the string for an error number
60 fdt_err: Error number (-ve)
63 String containing the associated error
65 return fdt_strerror(fdt_err)
67 def check_err(val, quiet=()):
68 """Raise an error if the return value is -ve
70 This is used to check for errors returned by libfdt C functions.
73 val: Return value from a libfdt function
74 quiet: Errors to ignore (empty to raise on all errors)
80 FdtException if val < 0
84 raise FdtException(val)
87 def check_err_null(val, quiet=()):
88 """Raise an error if the return value is NULL
90 This is used to check for a NULL return value from certain libfdt C
94 val: Return value from a libfdt function
95 quiet: Errors to ignore (empty to raise on all errors)
98 val if val is a list, None if not
101 FdtException if val indicates an error was reported and the error
104 # Normally a list is returned which contains the data and its length.
105 # If we get just an integer error code, it means the function failed.
106 if not isinstance(val, list):
107 if -val not in quiet:
108 raise FdtException(val)
112 """Device tree class, supporting all operations
114 The Fdt object is created is created from a device tree binary file,
115 e.g. with something like:
117 fdt = Fdt(open("filename.dtb").read())
119 Operations can then be performed using the methods in this class. Each
120 method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
122 All methods raise an FdtException if an error occurs. To avoid this
123 behaviour a 'quiet' parameter is provided for some functions. This
124 defaults to empty, but you can pass a list of errors that you expect.
125 If one of these errors occurs, the function will return an error number
128 def __init__(self, data):
129 self._fdt = bytearray(data)
130 check_err(fdt_check_header(self._fdt));
132 def subnode_offset(self, parentoffset, name, quiet=()):
133 """Get the offset of a named subnode
136 parentoffset: Offset of the parent node to check
137 name: Name of the required subnode, e.g. 'subnode@1'
138 quiet: Errors to ignore (empty to raise on all errors)
141 The node offset of the found node, if any
144 FdtException if there is no node with that name, or other error
146 return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
149 def path_offset(self, path, quiet=()):
150 """Get the offset for a given path
153 path: Path to the required node, e.g. '/node@3/subnode@1'
154 quiet: Errors to ignore (empty to raise on all errors)
160 FdtException if the path is not valid or not found
162 return check_err(fdt_path_offset(self._fdt, path), quiet)
164 def first_property_offset(self, nodeoffset, quiet=()):
165 """Get the offset of the first property in a node offset
168 nodeoffset: Offset to the node to check
169 quiet: Errors to ignore (empty to raise on all errors)
172 Offset of the first property
175 FdtException if the associated node has no properties, or some
178 return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
181 def next_property_offset(self, prop_offset, quiet=()):
182 """Get the next property in a node
185 prop_offset: Offset of the previous property
186 quiet: Errors to ignore (empty to raise on all errors)
189 Offset of the next property
192 FdtException if the associated node has no more properties, or
193 some other error occurred
195 return check_err(fdt_next_property_offset(self._fdt, prop_offset),
198 def get_name(self, nodeoffset):
199 """Get the name of a node
202 nodeoffset: Offset of node to check
208 FdtException on error (e.g. nodeoffset is invalid)
210 return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
212 def get_property_by_offset(self, prop_offset, quiet=()):
213 """Obtains a property that can be examined
216 prop_offset: Offset of property (e.g. from first_property_offset())
217 quiet: Errors to ignore (empty to raise on all errors)
220 Property object, or None if not found
223 FdtException on error (e.g. invalid prop_offset or device
226 pdata = check_err_null(
227 fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
228 if isinstance(pdata, (int)):
230 return Property(pdata[0], pdata[1])
232 def first_subnode(self, nodeoffset, quiet=()):
233 """Find the first subnode of a parent node
236 nodeoffset: Node offset of parent node
237 quiet: Errors to ignore (empty to raise on all errors)
240 The offset of the first subnode, if any
243 FdtException if no subnode found or other error occurs
245 return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
247 def next_subnode(self, nodeoffset, quiet=()):
248 """Find the next subnode
251 nodeoffset: Node offset of previous subnode
252 quiet: Errors to ignore (empty to raise on all errors)
255 The offset of the next subnode, if any
258 FdtException if no more subnode found or other error occurs
260 return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
263 """Return the total size of the device tree
266 Total tree size in bytes
268 return check_err(fdt_totalsize(self._fdt))
270 def off_dt_struct(self):
271 """Return the start of the device tree struct area
274 Start offset of struct area
276 return check_err(fdt_off_dt_struct(self._fdt))
278 def pack(self, quiet=()):
279 """Pack the device tree to remove unused space
281 This adjusts the tree in place.
284 quiet: Errors to ignore (empty to raise on all errors)
287 FdtException if any error occurs
289 return check_err(fdt_pack(self._fdt), quiet)
291 def delprop(self, nodeoffset, prop_name):
292 """Delete a property from a node
295 nodeoffset: Node offset containing property to delete
296 prop_name: Name of property to delete
299 FdtError if the property does not exist, or another error occurs
301 return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
303 def getprop(self, nodeoffset, prop_name, quiet=()):
304 """Get a property from a node
307 nodeoffset: Node offset containing property to get
308 prop_name: Name of property to get
309 quiet: Errors to ignore (empty to raise on all errors)
312 Value of property as a bytearray, or -ve error number
315 FdtError if any error occurs (e.g. the property is not found)
317 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
319 if isinstance(pdata, (int)):
321 return bytearray(pdata[0])
323 def get_phandle(self, nodeoffset):
324 """Get the phandle of a node
327 nodeoffset: Node offset to check
330 phandle of node, or 0 if the node has no phandle or another error
333 return fdt_get_phandle(self._fdt, nodeoffset)
335 def parent_offset(self, nodeoffset, quiet=()):
336 """Get the offset of a node's parent
339 nodeoffset: Node offset to check
340 quiet: Errors to ignore (empty to raise on all errors)
343 The offset of the parent node, if any
346 FdtException if no parent found or other error occurs
348 return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
350 def node_offset_by_phandle(self, phandle, quiet=()):
351 """Get the offset of a node with the given phandle
354 phandle: Phandle to search for
355 quiet: Errors to ignore (empty to raise on all errors)
358 The offset of node with that phandle, if any
361 FdtException if no node found or other error occurs
363 return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
366 """Holds a device tree property name and value.
368 This holds a copy of a property taken from the device tree. It does not
369 reference the device tree, so if anything changes in the device tree,
370 a Property object will remain valid.
374 value: Proper value as a bytearray
376 def __init__(self, name, value):
381 %rename(fdt_property) fdt_property_func;
385 %include "libfdt/fdt.h"
387 %include "typemaps.i"
389 /* Most functions don't change the device tree, so use a const void * */
390 %typemap(in) (const void *)(const void *fdt) {
391 if (!PyByteArray_Check($input)) {
392 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
393 "', argument " "$argnum"" of type '" "$type""'");
395 $1 = (void *)PyByteArray_AsString($input);
397 fdt = fdt; /* avoid unused variable warning */
400 /* Some functions do change the device tree, so use void * */
401 %typemap(in) (void *)(const void *fdt) {
402 if (!PyByteArray_Check($input)) {
403 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
404 "', argument " "$argnum"" of type '" "$type""'");
406 $1 = PyByteArray_AsString($input);
408 fdt = fdt; /* avoid unused variable warning */
411 %typemap(out) (struct fdt_property *) {
415 resultobj = PyString_FromString(
416 fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
417 buff = PyByteArray_FromStringAndSize(
418 (const char *)($1 + 1), fdt32_to_cpu($1->len));
419 resultobj = SWIG_Python_AppendOutput(resultobj, buff);
423 %apply int *OUTPUT { int *lenp };
425 /* typemap used for fdt_getprop() */
426 %typemap(out) (const void *) {
430 $result = Py_BuildValue("s#", $1, *arg4);
433 /* We have both struct fdt_property and a function fdt_property() */
434 %warnfilter(302) fdt_property;
436 /* These are macros in the header so have to be redefined here */
437 int fdt_magic(const void *fdt);
438 int fdt_totalsize(const void *fdt);
439 int fdt_off_dt_struct(const void *fdt);
440 int fdt_off_dt_strings(const void *fdt);
441 int fdt_off_mem_rsvmap(const void *fdt);
442 int fdt_version(const void *fdt);
443 int fdt_last_comp_version(const void *fdt);
444 int fdt_boot_cpuid_phys(const void *fdt);
445 int fdt_size_dt_strings(const void *fdt);
446 int fdt_size_dt_struct(const void *fdt);
448 %include <../libfdt/libfdt.h>