SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / scripts / dtc / pylibfdt / libfdt.i_shipped
1 /*
2  * pylibfdt - Flat Device Tree manipulation in Python
3  * Copyright (C) 2017 Google, Inc.
4  * Written by Simon Glass <sjg@chromium.org>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+ BSD-2-Clause
7  */
8
9 %module libfdt
10
11 %include <stdint.i>
12
13 %{
14 #define SWIG_FILE_WITH_INIT
15 #include "libfdt.h"
16 %}
17
18 %pythoncode %{
19
20 import struct
21
22 # Error codes, corresponding to FDT_ERR_... in libfdt.h
23 (NOTFOUND,
24         EXISTS,
25         NOSPACE,
26         BADOFFSET,
27         BADPATH,
28         BADPHANDLE,
29         BADSTATE,
30         TRUNCATED,
31         BADMAGIC,
32         BADVERSION,
33         BADSTRUCTURE,
34         BADLAYOUT,
35         INTERNAL,
36         BADNCELLS,
37         BADVALUE,
38         BADOVERLAY,
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.
43
44 # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
45 # instead of raising an exception.
46 QUIET_NOTFOUND = (NOTFOUND,)
47
48
49 class FdtException(Exception):
50     """An exception caused by an error such as one of the codes above"""
51     def __init__(self, err):
52         self.err = err
53
54     def __str__(self):
55         return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
56
57 def strerror(fdt_err):
58     """Get the string for an error number
59
60     Args:
61         fdt_err: Error number (-ve)
62
63     Returns:
64         String containing the associated error
65     """
66     return fdt_strerror(fdt_err)
67
68 def check_err(val, quiet=()):
69     """Raise an error if the return value is -ve
70
71     This is used to check for errors returned by libfdt C functions.
72
73     Args:
74         val: Return value from a libfdt function
75         quiet: Errors to ignore (empty to raise on all errors)
76
77     Returns:
78         val if val >= 0
79
80     Raises
81         FdtException if val < 0
82     """
83     if val < 0:
84         if -val not in quiet:
85             raise FdtException(val)
86     return val
87
88 def check_err_null(val, quiet=()):
89     """Raise an error if the return value is NULL
90
91     This is used to check for a NULL return value from certain libfdt C
92     functions
93
94     Args:
95         val: Return value from a libfdt function
96         quiet: Errors to ignore (empty to raise on all errors)
97
98     Returns:
99         val if val is a list, None if not
100
101     Raises
102         FdtException if val indicates an error was reported and the error
103         is not in @quiet.
104     """
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)
110     return val
111
112 class Fdt:
113     """Device tree class, supporting all operations
114
115     The Fdt object is created is created from a device tree binary file,
116     e.g. with something like:
117
118        fdt = Fdt(open("filename.dtb").read())
119
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...).
122
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
127     (e.g. -NOTFOUND).
128     """
129     def __init__(self, data):
130         self._fdt = bytearray(data)
131         check_err(fdt_check_header(self._fdt));
132
133     def subnode_offset(self, parentoffset, name, quiet=()):
134         """Get the offset of a named subnode
135
136         Args:
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)
140
141         Returns:
142             The node offset of the found node, if any
143
144         Raises
145             FdtException if there is no node with that name, or other error
146         """
147         return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
148                          quiet)
149
150     def path_offset(self, path, quiet=()):
151         """Get the offset for a given path
152
153         Args:
154             path: Path to the required node, e.g. '/node@3/subnode@1'
155             quiet: Errors to ignore (empty to raise on all errors)
156
157         Returns:
158             Node offset
159
160         Raises
161             FdtException if the path is not valid or not found
162         """
163         return check_err(fdt_path_offset(self._fdt, path), quiet)
164
165     def first_property_offset(self, nodeoffset, quiet=()):
166         """Get the offset of the first property in a node offset
167
168         Args:
169             nodeoffset: Offset to the node to check
170             quiet: Errors to ignore (empty to raise on all errors)
171
172         Returns:
173             Offset of the first property
174
175         Raises
176             FdtException if the associated node has no properties, or some
177                 other error occurred
178         """
179         return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
180                          quiet)
181
182     def next_property_offset(self, prop_offset, quiet=()):
183         """Get the next property in a node
184
185         Args:
186             prop_offset: Offset of the previous property
187             quiet: Errors to ignore (empty to raise on all errors)
188
189         Returns:
190             Offset of the next property
191
192         Raises:
193             FdtException if the associated node has no more properties, or
194                 some other error occurred
195         """
196         return check_err(fdt_next_property_offset(self._fdt, prop_offset),
197                          quiet)
198
199     def get_name(self, nodeoffset):
200         """Get the name of a node
201
202         Args:
203             nodeoffset: Offset of node to check
204
205         Returns:
206             Node name
207
208         Raises:
209             FdtException on error (e.g. nodeoffset is invalid)
210         """
211         return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
212
213     def get_property_by_offset(self, prop_offset, quiet=()):
214         """Obtains a property that can be examined
215
216         Args:
217             prop_offset: Offset of property (e.g. from first_property_offset())
218             quiet: Errors to ignore (empty to raise on all errors)
219
220         Returns:
221             Property object, or None if not found
222
223         Raises:
224             FdtException on error (e.g. invalid prop_offset or device
225             tree format)
226         """
227         pdata = check_err_null(
228                 fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
229         if isinstance(pdata, (int)):
230             return pdata
231         return Property(pdata[0], pdata[1])
232
233     def first_subnode(self, nodeoffset, quiet=()):
234         """Find the first subnode of a parent node
235
236         Args:
237             nodeoffset: Node offset of parent node
238             quiet: Errors to ignore (empty to raise on all errors)
239
240         Returns:
241             The offset of the first subnode, if any
242
243         Raises:
244             FdtException if no subnode found or other error occurs
245         """
246         return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
247
248     def next_subnode(self, nodeoffset, quiet=()):
249         """Find the next subnode
250
251         Args:
252             nodeoffset: Node offset of previous subnode
253             quiet: Errors to ignore (empty to raise on all errors)
254
255         Returns:
256             The offset of the next subnode, if any
257
258         Raises:
259             FdtException if no more subnode found or other error occurs
260         """
261         return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
262
263     def totalsize(self):
264         """Return the total size of the device tree
265
266         Returns:
267             Total tree size in bytes
268         """
269         return check_err(fdt_totalsize(self._fdt))
270
271     def off_dt_struct(self):
272         """Return the start of the device tree struct area
273
274         Returns:
275             Start offset of struct area
276         """
277         return check_err(fdt_off_dt_struct(self._fdt))
278
279     def pack(self, quiet=()):
280         """Pack the device tree to remove unused space
281
282         This adjusts the tree in place.
283
284         Args:
285             quiet: Errors to ignore (empty to raise on all errors)
286
287         Raises:
288             FdtException if any error occurs
289         """
290         return check_err(fdt_pack(self._fdt), quiet)
291
292     def delprop(self, nodeoffset, prop_name):
293         """Delete a property from a node
294
295         Args:
296             nodeoffset: Node offset containing property to delete
297             prop_name: Name of property to delete
298
299         Raises:
300             FdtError if the property does not exist, or another error occurs
301         """
302         return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
303
304     def getprop(self, nodeoffset, prop_name, quiet=()):
305         """Get a property from a node
306
307         Args:
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)
311
312         Returns:
313             Value of property as a bytearray, or -ve error number
314
315         Raises:
316             FdtError if any error occurs (e.g. the property is not found)
317         """
318         pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
319                                quiet)
320         if isinstance(pdata, (int)):
321             return pdata
322         return bytearray(pdata[0])
323
324     def get_phandle(self, nodeoffset):
325         """Get the phandle of a node
326
327         Args:
328             nodeoffset: Node offset to check
329
330         Returns:
331             phandle of node, or 0 if the node has no phandle or another error
332             occurs
333         """
334         return fdt_get_phandle(self._fdt, nodeoffset)
335
336     def parent_offset(self, nodeoffset, quiet=()):
337         """Get the offset of a node's parent
338
339         Args:
340             nodeoffset: Node offset to check
341             quiet: Errors to ignore (empty to raise on all errors)
342
343         Returns:
344             The offset of the parent node, if any
345
346         Raises:
347             FdtException if no parent found or other error occurs
348         """
349         return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
350
351     def node_offset_by_phandle(self, phandle, quiet=()):
352         """Get the offset of a node with the given phandle
353
354         Args:
355             phandle: Phandle to search for
356             quiet: Errors to ignore (empty to raise on all errors)
357
358         Returns:
359             The offset of node with that phandle, if any
360
361         Raises:
362             FdtException if no node found or other error occurs
363         """
364         return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
365
366 class Property:
367     """Holds a device tree property name and value.
368
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.
372
373     Properties:
374         name: Property name
375         value: Proper value as a bytearray
376     """
377     def __init__(self, name, value):
378         self.name = name
379         self.value = value
380 %}
381
382 %rename(fdt_property) fdt_property_func;
383
384 typedef int fdt32_t;
385
386 %include "libfdt/fdt.h"
387
388 %include "typemaps.i"
389
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""'");
395         }
396         $1 = (void *)PyByteArray_AsString($input);
397         fdt = $1;
398         fdt = fdt; /* avoid unused variable warning */
399 }
400
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""'");
406         }
407         $1 = PyByteArray_AsString($input);
408         fdt = $1;
409         fdt = fdt; /* avoid unused variable warning */
410 }
411
412 %typemap(out) (struct fdt_property *) {
413         PyObject *buff;
414
415         if ($1) {
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);
421         }
422 }
423
424 %apply int *OUTPUT { int *lenp };
425
426 /* typemap used for fdt_getprop() */
427 %typemap(out) (const void *) {
428         if (!$1)
429                 $result = Py_None;
430         else
431                 $result = Py_BuildValue("s#", $1, *arg4);
432 }
433
434 /* We have both struct fdt_property and a function fdt_property() */
435 %warnfilter(302) fdt_property;
436
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);
448
449 %include <../libfdt/libfdt.h>