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