Merge branch 'master' of git://git.denx.de/u-boot-samsung
[platform/kernel/u-boot.git] / lib / libfdt / pylibfdt / libfdt.i
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 %{
12 #define SWIG_FILE_WITH_INIT
13 #include "libfdt.h"
14 %}
15
16 %pythoncode %{
17
18 import struct
19
20 # Error codes, corresponding to FDT_ERR_... in libfdt.h
21 (NOTFOUND,
22         EXISTS,
23         NOSPACE,
24         BADOFFSET,
25         BADPATH,
26         BADPHANDLE,
27         BADSTATE,
28         TRUNCATED,
29         BADMAGIC,
30         BADVERSION,
31         BADSTRUCTURE,
32         BADLAYOUT,
33         INTERNAL,
34         BADNCELLS,
35         BADVALUE,
36         BADOVERLAY,
37         NOPHANDLES) = QUIET_ALL = range(1, 18)
38 # QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
39 # altogether. All # functions passed this value will return an error instead
40 # of raising an exception.
41
42 # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
43 # instead of raising an exception.
44 QUIET_NOTFOUND = (NOTFOUND,)
45
46
47 class FdtException(Exception):
48     """An exception caused by an error such as one of the codes above"""
49     def __init__(self, err):
50         self.err = err
51
52     def __str__(self):
53         return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
54
55 def strerror(fdt_err):
56     """Get the string for an error number
57
58     Args:
59         fdt_err: Error number (-ve)
60
61     Returns:
62         String containing the associated error
63     """
64     return fdt_strerror(fdt_err)
65
66 def check_err(val, quiet=()):
67     """Raise an error if the return value is -ve
68
69     This is used to check for errors returned by libfdt C functions.
70
71     Args:
72         val: Return value from a libfdt function
73         quiet: Errors to ignore (empty to raise on all errors)
74
75     Returns:
76         val if val >= 0
77
78     Raises
79         FdtException if val < 0
80     """
81     if val < 0:
82         if -val not in quiet:
83             raise FdtException(val)
84     return val
85
86 def check_err_null(val, quiet=()):
87     """Raise an error if the return value is NULL
88
89     This is used to check for a NULL return value from certain libfdt C
90     functions
91
92     Args:
93         val: Return value from a libfdt function
94         quiet: Errors to ignore (empty to raise on all errors)
95
96     Returns:
97         val if val is a list, None if not
98
99     Raises
100         FdtException if val indicates an error was reported and the error
101         is not in @quiet.
102     """
103     # Normally a list is returned which contains the data and its length.
104     # If we get just an integer error code, it means the function failed.
105     if not isinstance(val, list):
106         if -val not in quiet:
107             raise FdtException(val)
108     return val
109
110 class Fdt:
111     """Device tree class, supporting all operations
112
113     The Fdt object is created is created from a device tree binary file,
114     e.g. with something like:
115
116        fdt = Fdt(open("filename.dtb").read())
117
118     Operations can then be performed using the methods in this class. Each
119     method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
120
121     All methods raise an FdtException if an error occurs. To avoid this
122     behaviour a 'quiet' parameter is provided for some functions. This
123     defaults to empty, but you can pass a list of errors that you expect.
124     If one of these errors occurs, the function will return an error number
125     (e.g. -NOTFOUND).
126     """
127     def __init__(self, data):
128         self._fdt = bytearray(data)
129         check_err(fdt_check_header(self._fdt));
130
131     def path_offset(self, path, quiet=()):
132         """Get the offset for a given path
133
134         Args:
135             path: Path to the required node, e.g. '/node@3/subnode@1'
136             quiet: Errors to ignore (empty to raise on all errors)
137
138         Returns:
139             Node offset
140
141         Raises
142             FdtException if the path is not valid or not found
143         """
144         return check_err(fdt_path_offset(self._fdt, path), quiet)
145
146     def first_property_offset(self, nodeoffset, quiet=()):
147         """Get the offset of the first property in a node offset
148
149         Args:
150             nodeoffset: Offset to the node to check
151             quiet: Errors to ignore (empty to raise on all errors)
152
153         Returns:
154             Offset of the first property
155
156         Raises
157             FdtException if the associated node has no properties, or some
158                 other error occurred
159         """
160         return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
161                          quiet)
162
163     def next_property_offset(self, prop_offset, quiet=()):
164         """Get the next property in a node
165
166         Args:
167             prop_offset: Offset of the previous property
168             quiet: Errors to ignore (empty to raise on all errors)
169
170         Returns:
171             Offset of the next property
172
173         Raises:
174             FdtException if the associated node has no more properties, or
175                 some other error occurred
176         """
177         return check_err(fdt_next_property_offset(self._fdt, prop_offset),
178                          quiet)
179
180     def get_name(self, nodeoffset):
181         """Get the name of a node
182
183         Args:
184             nodeoffset: Offset of node to check
185
186         Returns:
187             Node name
188
189         Raises:
190             FdtException on error (e.g. nodeoffset is invalid)
191         """
192         return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
193
194     def get_property_by_offset(self, prop_offset, quiet=()):
195         """Obtains a property that can be examined
196
197         Args:
198             prop_offset: Offset of property (e.g. from first_property_offset())
199             quiet: Errors to ignore (empty to raise on all errors)
200
201         Returns:
202             Property object, or None if not found
203
204         Raises:
205             FdtException on error (e.g. invalid prop_offset or device
206             tree format)
207         """
208         pdata = check_err_null(
209                 fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
210         if isinstance(pdata, (int)):
211             return pdata
212         return Property(pdata[0], pdata[1])
213
214     def first_subnode(self, nodeoffset, quiet=()):
215         """Find the first subnode of a parent node
216
217         Args:
218             nodeoffset: Node offset of parent node
219             quiet: Errors to ignore (empty to raise on all errors)
220
221         Returns:
222             The offset of the first subnode, if any
223
224         Raises:
225             FdtException if no subnode found or other error occurs
226         """
227         return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
228
229     def next_subnode(self, nodeoffset, quiet=()):
230         """Find the next subnode
231
232         Args:
233             nodeoffset: Node offset of previous subnode
234             quiet: Errors to ignore (empty to raise on all errors)
235
236         Returns:
237             The offset of the next subnode, if any
238
239         Raises:
240             FdtException if no more subnode found or other error occurs
241         """
242         return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
243
244     def totalsize(self):
245         """Return the total size of the device tree
246
247         Returns:
248             Total tree size in bytes
249         """
250         return check_err(fdt_totalsize(self._fdt))
251
252     def off_dt_struct(self):
253         """Return the start of the device tree struct area
254
255         Returns:
256             Start offset of struct area
257         """
258         return check_err(fdt_off_dt_struct(self._fdt))
259
260     def pack(self, quiet=()):
261         """Pack the device tree to remove unused space
262
263         This adjusts the tree in place.
264
265         Args:
266             quiet: Errors to ignore (empty to raise on all errors)
267
268         Raises:
269             FdtException if any error occurs
270         """
271         return check_err(fdt_pack(self._fdt), quiet)
272
273     def delprop(self, nodeoffset, prop_name):
274         """Delete a property from a node
275
276         Args:
277             nodeoffset: Node offset containing property to delete
278             prop_name: Name of property to delete
279
280         Raises:
281             FdtError if the property does not exist, or another error occurs
282         """
283         return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
284
285     def getprop(self, nodeoffset, prop_name, quiet=()):
286         """Get a property from a node
287
288         Args:
289             nodeoffset: Node offset containing property to get
290             prop_name: Name of property to get
291             quiet: Errors to ignore (empty to raise on all errors)
292
293         Returns:
294             Value of property as a bytearray, or -ve error number
295
296         Raises:
297             FdtError if any error occurs (e.g. the property is not found)
298         """
299         pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
300                                quiet)
301         if isinstance(pdata, (int)):
302             return pdata
303         return bytearray(pdata[0])
304
305
306 class Property:
307     """Holds a device tree property name and value.
308
309     This holds a copy of a property taken from the device tree. It does not
310     reference the device tree, so if anything changes in the device tree,
311     a Property object will remain valid.
312
313     Properties:
314         name: Property name
315         value: Proper value as a bytearray
316     """
317     def __init__(self, name, value):
318         self.name = name
319         self.value = value
320 %}
321
322 %rename(fdt_property) fdt_property_func;
323
324 typedef int fdt32_t;
325
326 %include "libfdt/fdt.h"
327
328 %include "typemaps.i"
329
330 /* Most functions don't change the device tree, so use a const void * */
331 %typemap(in) (const void *)(const void *fdt) {
332         if (!PyByteArray_Check($input)) {
333                 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
334                         "', argument " "$argnum"" of type '" "$type""'");
335         }
336         $1 = (void *)PyByteArray_AsString($input);
337         fdt = $1;
338         fdt = fdt; /* avoid unused variable warning */
339 }
340
341 /* Some functions do change the device tree, so use void * */
342 %typemap(in) (void *)(const void *fdt) {
343         if (!PyByteArray_Check($input)) {
344                 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
345                         "', argument " "$argnum"" of type '" "$type""'");
346         }
347         $1 = PyByteArray_AsString($input);
348         fdt = $1;
349         fdt = fdt; /* avoid unused variable warning */
350 }
351
352 %typemap(out) (struct fdt_property *) {
353         PyObject *buff;
354
355         if ($1) {
356                 resultobj = PyString_FromString(
357                         fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
358                 buff = PyByteArray_FromStringAndSize(
359                         (const char *)($1 + 1), fdt32_to_cpu($1->len));
360                 resultobj = SWIG_Python_AppendOutput(resultobj, buff);
361         }
362 }
363
364 %apply int *OUTPUT { int *lenp };
365
366 /* typemap used for fdt_getprop() */
367 %typemap(out) (const void *) {
368         if (!$1)
369                 $result = Py_None;
370         else
371                 $result = Py_BuildValue("s#", $1, *arg4);
372 }
373
374 /* We have both struct fdt_property and a function fdt_property() */
375 %warnfilter(302) fdt_property;
376
377 /* These are macros in the header so have to be redefined here */
378 int fdt_magic(const void *fdt);
379 int fdt_totalsize(const void *fdt);
380 int fdt_off_dt_struct(const void *fdt);
381 int fdt_off_dt_strings(const void *fdt);
382 int fdt_off_mem_rsvmap(const void *fdt);
383 int fdt_version(const void *fdt);
384 int fdt_last_comp_version(const void *fdt);
385 int fdt_boot_cpuid_phys(const void *fdt);
386 int fdt_size_dt_strings(const void *fdt);
387 int fdt_size_dt_struct(const void *fdt);
388
389 %include <../libfdt/libfdt.h>