xref: /openbmc/u-boot/scripts/dtc/pylibfdt/libfdt.i_shipped (revision 3def0cf238e0df9736a4ce8fb54c1eb561a56ddd)
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 * We rename this function here to avoid problems with swig, since we also have
18 * a struct called fdt_property. That struct causes swig to create a class in
19 * libfdt.py called fdt_property(), which confuses things.
20 */
21static int _fdt_property(void *fdt, const char *name, const char *val, int len)
22{
23    return fdt_property(fdt, name, val, len);
24}
25
26%}
27
28%pythoncode %{
29
30import struct
31
32# Error codes, corresponding to FDT_ERR_... in libfdt.h
33(NOTFOUND,
34        EXISTS,
35        NOSPACE,
36        BADOFFSET,
37        BADPATH,
38        BADPHANDLE,
39        BADSTATE,
40        TRUNCATED,
41        BADMAGIC,
42        BADVERSION,
43        BADSTRUCTURE,
44        BADLAYOUT,
45        INTERNAL,
46        BADNCELLS,
47        BADVALUE,
48        BADOVERLAY,
49        NOPHANDLES) = QUIET_ALL = range(1, 18)
50# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
51# altogether. All # functions passed this value will return an error instead
52# of raising an exception.
53
54# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
55# instead of raising an exception.
56QUIET_NOTFOUND = (NOTFOUND,)
57
58
59class FdtException(Exception):
60    """An exception caused by an error such as one of the codes above"""
61    def __init__(self, err):
62        self.err = err
63
64    def __str__(self):
65        return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
66
67def strerror(fdt_err):
68    """Get the string for an error number
69
70    Args:
71        fdt_err: Error number (-ve)
72
73    Returns:
74        String containing the associated error
75    """
76    return fdt_strerror(fdt_err)
77
78def check_err(val, quiet=()):
79    """Raise an error if the return value is -ve
80
81    This is used to check for errors returned by libfdt C functions.
82
83    Args:
84        val: Return value from a libfdt function
85        quiet: Errors to ignore (empty to raise on all errors)
86
87    Returns:
88        val if val >= 0
89
90    Raises
91        FdtException if val < 0
92    """
93    if val < 0:
94        if -val not in quiet:
95            raise FdtException(val)
96    return val
97
98def check_err_null(val, quiet=()):
99    """Raise an error if the return value is NULL
100
101    This is used to check for a NULL return value from certain libfdt C
102    functions
103
104    Args:
105        val: Return value from a libfdt function
106        quiet: Errors to ignore (empty to raise on all errors)
107
108    Returns:
109        val if val is a list, None if not
110
111    Raises
112        FdtException if val indicates an error was reported and the error
113        is not in @quiet.
114    """
115    # Normally a list is returned which contains the data and its length.
116    # If we get just an integer error code, it means the function failed.
117    if not isinstance(val, list):
118        if -val not in quiet:
119            raise FdtException(val)
120    return val
121
122
123class Fdt:
124    """Device tree class, supporting all operations
125
126    The Fdt object is created is created from a device tree binary file,
127    e.g. with something like:
128
129       fdt = Fdt(open("filename.dtb").read())
130
131    Operations can then be performed using the methods in this class. Each
132    method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
133
134    All methods raise an FdtException if an error occurs. To avoid this
135    behaviour a 'quiet' parameter is provided for some functions. This
136    defaults to empty, but you can pass a list of errors that you expect.
137    If one of these errors occurs, the function will return an error number
138    (e.g. -NOTFOUND).
139    """
140    def __init__(self, data):
141        self._fdt = bytearray(data)
142        check_err(fdt_check_header(self._fdt));
143
144    def as_bytearray(self):
145        """Get the device tree contents as a bytearray
146
147        This can be passed directly to libfdt functions that access a
148        const void * for the device tree.
149
150        Returns:
151            bytearray containing the device tree
152        """
153        return bytearray(self._fdt)
154
155    def next_node(self, nodeoffset, depth, quiet=()):
156        """Find the next subnode
157
158        Args:
159            nodeoffset: Node offset of previous node
160            depth: On input, the depth of the node at nodeoffset. On output, the
161               depth of the returned node
162            quiet: Errors to ignore (empty to raise on all errors)
163
164        Returns:
165            The offset of the next node, if any
166
167        Raises:
168            FdtException if no more nodes found or other error occurs
169        """
170        return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet)
171
172    def first_subnode(self, nodeoffset, quiet=()):
173        """Find the first subnode of a parent node
174
175        Args:
176            nodeoffset: Node offset of parent node
177            quiet: Errors to ignore (empty to raise on all errors)
178
179        Returns:
180            The offset of the first subnode, if any
181
182        Raises:
183            FdtException if no subnodes found or other error occurs
184        """
185        return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
186
187    def next_subnode(self, nodeoffset, quiet=()):
188        """Find the next subnode
189
190        Args:
191            nodeoffset: Node offset of previous subnode
192            quiet: Errors to ignore (empty to raise on all errors)
193
194        Returns:
195            The offset of the next subnode, if any
196
197        Raises:
198            FdtException if no more subnodes found or other error occurs
199        """
200        return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
201
202    def magic(self):
203        """Return the magic word from the header
204
205        Returns:
206            Magic word
207        """
208        return fdt_magic(self._fdt) & 0xffffffff
209
210    def totalsize(self):
211        """Return the total size of the device tree
212
213        Returns:
214            Total tree size in bytes
215        """
216        return check_err(fdt_totalsize(self._fdt))
217
218    def off_dt_struct(self):
219        """Return the start of the device-tree struct area
220
221        Returns:
222            Start offset of struct area
223        """
224        return check_err(fdt_off_dt_struct(self._fdt))
225
226    def off_dt_strings(self):
227        """Return the start of the device-tree string area
228
229        Returns:
230            Start offset of string area
231        """
232        return check_err(fdt_off_dt_strings(self._fdt))
233
234    def off_mem_rsvmap(self):
235        """Return the start of the memory reserve map
236
237        Returns:
238            Start offset of memory reserve map
239        """
240        return check_err(fdt_off_mem_rsvmap(self._fdt))
241
242    def version(self):
243        """Return the version of the device tree
244
245        Returns:
246            Version number of the device tree
247        """
248        return check_err(fdt_version(self._fdt))
249
250    def last_comp_version(self):
251        """Return the last compatible version of the device tree
252
253        Returns:
254            Last compatible version number of the device tree
255        """
256        return check_err(fdt_last_comp_version(self._fdt))
257
258    def boot_cpuid_phys(self):
259        """Return the physical boot CPU ID
260
261        Returns:
262            Physical boot CPU ID
263        """
264        return check_err(fdt_boot_cpuid_phys(self._fdt))
265
266    def size_dt_strings(self):
267        """Return the start of the device-tree string area
268
269        Returns:
270            Start offset of string area
271        """
272        return check_err(fdt_size_dt_strings(self._fdt))
273
274    def size_dt_struct(self):
275        """Return the start of the device-tree struct area
276
277        Returns:
278            Start offset of struct area
279        """
280        return check_err(fdt_size_dt_struct(self._fdt))
281
282    def num_mem_rsv(self, quiet=()):
283        """Return the number of memory reserve-map records
284
285        Returns:
286            Number of memory reserve-map records
287        """
288        return check_err(fdt_num_mem_rsv(self._fdt), quiet)
289
290    def get_mem_rsv(self, index, quiet=()):
291        """Return the indexed memory reserve-map record
292
293        Args:
294            index: Record to return (0=first)
295
296        Returns:
297            Number of memory reserve-map records
298        """
299        return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
300
301    def subnode_offset(self, parentoffset, name, quiet=()):
302        """Get the offset of a named subnode
303
304        Args:
305            parentoffset: Offset of the parent node to check
306            name: Name of the required subnode, e.g. 'subnode@1'
307            quiet: Errors to ignore (empty to raise on all errors)
308
309        Returns:
310            The node offset of the found node, if any
311
312        Raises
313            FdtException if there is no node with that name, or other error
314        """
315        return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
316                         quiet)
317
318    def path_offset(self, path, quiet=()):
319        """Get the offset for a given path
320
321        Args:
322            path: Path to the required node, e.g. '/node@3/subnode@1'
323            quiet: Errors to ignore (empty to raise on all errors)
324
325        Returns:
326            Node offset
327
328        Raises
329            FdtException if the path is not valid or not found
330        """
331        return check_err(fdt_path_offset(self._fdt, path), quiet)
332
333    def get_name(self, nodeoffset):
334        """Get the name of a node
335
336        Args:
337            nodeoffset: Offset of node to check
338
339        Returns:
340            Node name
341
342        Raises:
343            FdtException on error (e.g. nodeoffset is invalid)
344        """
345        return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
346
347    def first_property_offset(self, nodeoffset, quiet=()):
348        """Get the offset of the first property in a node offset
349
350        Args:
351            nodeoffset: Offset to the node to check
352            quiet: Errors to ignore (empty to raise on all errors)
353
354        Returns:
355            Offset of the first property
356
357        Raises
358            FdtException if the associated node has no properties, or some
359                other error occurred
360        """
361        return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
362                         quiet)
363
364    def next_property_offset(self, prop_offset, quiet=()):
365        """Get the next property in a node
366
367        Args:
368            prop_offset: Offset of the previous property
369            quiet: Errors to ignore (empty to raise on all errors)
370
371        Returns:
372            Offset of the next property
373
374        Raises:
375            FdtException if the associated node has no more properties, or
376                some other error occurred
377        """
378        return check_err(fdt_next_property_offset(self._fdt, prop_offset),
379                         quiet)
380
381    def get_property_by_offset(self, prop_offset, quiet=()):
382        """Obtains a property that can be examined
383
384        Args:
385            prop_offset: Offset of property (e.g. from first_property_offset())
386            quiet: Errors to ignore (empty to raise on all errors)
387
388        Returns:
389            Property object, or None if not found
390
391        Raises:
392            FdtException on error (e.g. invalid prop_offset or device
393            tree format)
394        """
395        pdata = check_err_null(
396                fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
397        if isinstance(pdata, (int)):
398            return pdata
399        return Property(pdata[0], pdata[1])
400
401    @staticmethod
402    def create_empty_tree(size, quiet=()):
403        """Create an empty device tree ready for use
404
405        Args:
406            size: Size of device tree in bytes
407
408        Returns:
409            Fdt object containing the device tree
410        """
411        data = bytearray(size)
412        err = check_err(fdt_create_empty_tree(data, size), quiet)
413        if err:
414            return err
415        return Fdt(data)
416
417    def open_into(self, size, quiet=()):
418        """Move the device tree into a larger or smaller space
419
420        This creates a new device tree of size @size and moves the existing
421        device tree contents over to that. It can be used to create more space
422        in a device tree.
423
424        Args:
425            size: Required new size of device tree in bytes
426        """
427        fdt = bytearray(size)
428        fdt[:len(self._fdt)] = self._fdt
429        err = check_err(fdt_open_into(self._fdt, fdt, size), quiet)
430        if err:
431            return err
432        self._fdt = fdt
433
434    def pack(self, quiet=()):
435        """Pack the device tree to remove unused space
436
437        This adjusts the tree in place.
438
439        Args:
440            quiet: Errors to ignore (empty to raise on all errors)
441
442        Raises:
443            FdtException if any error occurs
444        """
445        return check_err(fdt_pack(self._fdt), quiet)
446
447    def getprop(self, nodeoffset, prop_name, quiet=()):
448        """Get a property from a node
449
450        Args:
451            nodeoffset: Node offset containing property to get
452            prop_name: Name of property to get
453            quiet: Errors to ignore (empty to raise on all errors)
454
455        Returns:
456            Value of property as a string, or -ve error number
457
458        Raises:
459            FdtError if any error occurs (e.g. the property is not found)
460        """
461        pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
462                               quiet)
463        if isinstance(pdata, (int)):
464            return pdata
465        return str(pdata[0])
466
467    def getprop_obj(self, nodeoffset, prop_name, quiet=()):
468        """Get a property from a node as a Property object
469
470        Args:
471            nodeoffset: Node offset containing property to get
472            prop_name: Name of property to get
473            quiet: Errors to ignore (empty to raise on all errors)
474
475        Returns:
476            Property object, or None if not found
477
478        Raises:
479            FdtError if any error occurs (e.g. the property is not found)
480        """
481        pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
482                               quiet)
483        if isinstance(pdata, (int)):
484            return None
485        return Property(prop_name, bytearray(pdata[0]))
486
487    def get_phandle(self, nodeoffset):
488        """Get the phandle of a node
489
490        Args:
491            nodeoffset: Node offset to check
492
493        Returns:
494            phandle of node, or 0 if the node has no phandle or another error
495            occurs
496        """
497        return fdt_get_phandle(self._fdt, nodeoffset)
498
499    def parent_offset(self, nodeoffset, quiet=()):
500        """Get the offset of a node's parent
501
502        Args:
503            nodeoffset: Node offset to check
504            quiet: Errors to ignore (empty to raise on all errors)
505
506        Returns:
507            The offset of the parent node, if any
508
509        Raises:
510            FdtException if no parent found or other error occurs
511        """
512        return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
513
514    def set_name(self, nodeoffset, name, quiet=()):
515        """Set the name of a node
516
517        Args:
518            nodeoffset: Node offset of node to update
519            name: New node name
520
521        Returns:
522            Error code, or 0 if OK
523
524        Raises:
525            FdtException if no parent found or other error occurs
526        """
527        return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet)
528
529    def setprop(self, nodeoffset, prop_name, val, quiet=()):
530        """Set the value of a property
531
532        Args:
533            nodeoffset: Node offset containing the property to create/update
534            prop_name: Name of property
535            val: Value to write (string or bytearray)
536            quiet: Errors to ignore (empty to raise on all errors)
537
538        Returns:
539            Error code, or 0 if OK
540
541        Raises:
542            FdtException if no parent found or other error occurs
543        """
544        return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
545                                     len(val)), quiet)
546
547    def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
548        """Set the value of a property
549
550        Args:
551            nodeoffset: Node offset containing the property to create/update
552            prop_name: Name of property
553            val: Value to write (integer)
554            quiet: Errors to ignore (empty to raise on all errors)
555
556        Returns:
557            Error code, or 0 if OK
558
559        Raises:
560            FdtException if no parent found or other error occurs
561        """
562        return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val),
563                         quiet)
564
565    def setprop_u64(self, nodeoffset, prop_name, val, quiet=()):
566        """Set the value of a property
567
568        Args:
569            nodeoffset: Node offset containing the property to create/update
570            prop_name: Name of property
571            val: Value to write (integer)
572            quiet: Errors to ignore (empty to raise on all errors)
573
574        Returns:
575            Error code, or 0 if OK
576
577        Raises:
578            FdtException if no parent found or other error occurs
579        """
580        return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val),
581                         quiet)
582
583    def setprop_str(self, nodeoffset, prop_name, val, quiet=()):
584        """Set the string value of a property
585
586        The property is set to the string, with a nul terminator added
587
588        Args:
589            nodeoffset: Node offset containing the property to create/update
590            prop_name: Name of property
591            val: Value to write (string without nul terminator)
592            quiet: Errors to ignore (empty to raise on all errors)
593
594        Returns:
595            Error code, or 0 if OK
596
597        Raises:
598            FdtException if no parent found or other error occurs
599        """
600        val += '\0'
601        return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name,
602                                     val, len(val)), quiet)
603
604    def delprop(self, nodeoffset, prop_name):
605        """Delete a property from a node
606
607        Args:
608            nodeoffset: Node offset containing property to delete
609            prop_name: Name of property to delete
610
611        Raises:
612            FdtError if the property does not exist, or another error occurs
613        """
614        return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
615
616    def node_offset_by_phandle(self, phandle, quiet=()):
617        """Get the offset of a node with the given phandle
618
619        Args:
620            phandle: Phandle to search for
621            quiet: Errors to ignore (empty to raise on all errors)
622
623        Returns:
624            The offset of node with that phandle, if any
625
626        Raises:
627            FdtException if no node found or other error occurs
628        """
629        return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
630
631
632class Property(bytearray):
633    """Holds a device tree property name and value.
634
635    This holds a copy of a property taken from the device tree. It does not
636    reference the device tree, so if anything changes in the device tree,
637    a Property object will remain valid.
638
639    Properties:
640        name: Property name
641        value: Property value as a bytearray
642    """
643    def __init__(self, name, value):
644        bytearray.__init__(self, value)
645        self.name = name
646
647    def as_cell(self, fmt):
648        return struct.unpack('>' + fmt, self)[0]
649
650    def as_uint32(self):
651        return self.as_cell('L')
652
653    def as_int32(self):
654        return self.as_cell('l')
655
656    def as_uint64(self):
657        return self.as_cell('Q')
658
659    def as_int64(self):
660        return self.as_cell('q')
661
662    def as_str(self):
663        return self[:-1]
664
665
666class FdtSw(object):
667    """Software interface to create a device tree from scratch
668
669    The methods in this class work by adding to an existing 'partial' device
670    tree buffer of a fixed size created by instantiating this class. When the
671    tree is complete, call finish() to complete the device tree so that it can
672    be used.
673
674    Similarly with nodes, a new node is started with begin_node() and finished
675    with end_node().
676
677    The context manager functions can be used to make this a bit easier:
678
679    # First create the device tree with a node and property:
680    with FdtSw(small_size) as sw:
681        with sw.AddNode('node'):
682            sw.property_u32('reg', 2)
683    fdt = sw.AsFdt()
684
685    # Now we can use it as a real device tree
686    fdt.setprop_u32(0, 'reg', 3)
687    """
688    def __init__(self, size, quiet=()):
689        fdtrw = bytearray(size)
690        err = check_err(fdt_create(fdtrw, size))
691        if err:
692            return err
693        self._fdtrw = fdtrw
694
695    def __enter__(self):
696        """Contact manager to use to create a device tree via software"""
697        return self
698
699    def __exit__(self, type, value, traceback):
700        check_err(fdt_finish(self._fdtrw))
701
702    def AsFdt(self):
703        """Convert a FdtSw into an Fdt so it can be accessed as normal
704
705        Note that finish() must be called before this function will work. If
706        you are using the context manager (see 'with' code in the FdtSw class
707        comment) then this will happen automatically.
708
709        Returns:
710            Fdt object allowing access to the newly created device tree
711        """
712        return Fdt(self._fdtrw)
713
714    def resize(self, size, quiet=()):
715        """Resize the buffer to accommodate a larger tree
716
717        Args:
718            size: New size of tree
719            quiet: Errors to ignore (empty to raise on all errors)
720
721        Raises:
722            FdtException if no node found or other error occurs
723        """
724        fdt = bytearray(size)
725        fdt[:len(self._fdtrw)] = self._fdtrw
726        err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet)
727        if err:
728            return err
729        self._fdtrw = fdt
730
731    def add_reservemap_entry(self, addr, size, quiet=()):
732        """Add a new memory reserve map entry
733
734        Once finished adding, you must call finish_reservemap().
735
736        Args:
737            addr: 64-bit start address
738            size: 64-bit size
739            quiet: Errors to ignore (empty to raise on all errors)
740
741        Raises:
742            FdtException if no node found or other error occurs
743        """
744        return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size),
745                         quiet)
746
747    def finish_reservemap(self, quiet=()):
748        """Indicate that there are no more reserve map entries to add
749
750        Args:
751            quiet: Errors to ignore (empty to raise on all errors)
752
753        Raises:
754            FdtException if no node found or other error occurs
755        """
756        return check_err(fdt_finish_reservemap(self._fdtrw), quiet)
757
758    def begin_node(self, name, quiet=()):
759        """Begin a new node
760
761        Use this before adding properties to the node. Then call end_node() to
762        finish it. You can also use the context manager as shown in the FdtSw
763        class comment.
764
765        Args:
766            name: Name of node to begin
767            quiet: Errors to ignore (empty to raise on all errors)
768
769        Raises:
770            FdtException if no node found or other error occurs
771        """
772        return check_err(fdt_begin_node(self._fdtrw, name), quiet)
773
774    def property_string(self, name, string, quiet=()):
775        """Add a property with a string value
776
777        The string will be nul-terminated when written to the device tree
778
779        Args:
780            name: Name of property to add
781            string: String value of property
782            quiet: Errors to ignore (empty to raise on all errors)
783
784        Raises:
785            FdtException if no node found or other error occurs
786        """
787        return check_err(fdt_property_string(self._fdtrw, name, string), quiet)
788
789    def property_u32(self, name, val, quiet=()):
790        """Add a property with a 32-bit value
791
792        Write a single-cell value to the device tree
793
794        Args:
795            name: Name of property to add
796            val: Value of property
797            quiet: Errors to ignore (empty to raise on all errors)
798
799        Raises:
800            FdtException if no node found or other error occurs
801        """
802        return check_err(fdt_property_u32(self._fdtrw, name, val), quiet)
803
804    def property_u64(self, name, val, quiet=()):
805        """Add a property with a 64-bit value
806
807        Write a double-cell value to the device tree in big-endian format
808
809        Args:
810            name: Name of property to add
811            val: Value of property
812            quiet: Errors to ignore (empty to raise on all errors)
813
814        Raises:
815            FdtException if no node found or other error occurs
816        """
817        return check_err(fdt_property_u64(self._fdtrw, name, val), quiet)
818
819    def property_cell(self, name, val, quiet=()):
820        """Add a property with a single-cell value
821
822        Write a single-cell value to the device tree
823
824        Args:
825            name: Name of property to add
826            val: Value of property
827            quiet: Errors to ignore (empty to raise on all errors)
828
829        Raises:
830            FdtException if no node found or other error occurs
831        """
832        return check_err(fdt_property_cell(self._fdtrw, name, val), quiet)
833
834    def property(self, name, val, quiet=()):
835        """Add a property
836
837        Write a new property with the given value to the device tree. The value
838        is taken as is and is not nul-terminated
839
840        Args:
841            name: Name of property to add
842            val: Value of property
843            quiet: Errors to ignore (empty to raise on all errors)
844
845        Raises:
846            FdtException if no node found or other error occurs
847        """
848        return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet)
849
850    def end_node(self, quiet=()):
851        """End a node
852
853        Use this after adding properties to a node to close it off. You can also
854        use the context manager as shown in the FdtSw class comment.
855
856        Args:
857            quiet: Errors to ignore (empty to raise on all errors)
858
859        Raises:
860            FdtException if no node found or other error occurs
861        """
862        return check_err(fdt_end_node(self._fdtrw), quiet)
863
864    def finish(self, quiet=()):
865        """Finish writing the device tree
866
867        This closes off the device tree ready for use
868
869        Args:
870            quiet: Errors to ignore (empty to raise on all errors)
871
872        Raises:
873            FdtException if no node found or other error occurs
874        """
875        return check_err(fdt_finish(self._fdtrw), quiet)
876
877    def AddNode(self, name):
878        """Create a new context for adding a node
879
880        When used in a 'with' clause this starts a new node and finishes it
881        afterward.
882
883        Args:
884            name: Name of node to add
885        """
886        return NodeAdder(self._fdtrw, name)
887
888
889class NodeAdder():
890    """Class to provide a node context
891
892    This allows you to add nodes in a more natural way:
893
894        with fdtsw.AddNode('name'):
895            fdtsw.property_string('test', 'value')
896
897    The node is automatically completed with a call to end_node() when the
898    context exits.
899    """
900    def __init__(self, fdt, name):
901        self._fdt = fdt
902        self._name = name
903
904    def __enter__(self):
905        check_err(fdt_begin_node(self._fdt, self._name))
906
907    def __exit__(self, type, value, traceback):
908        check_err(fdt_end_node(self._fdt))
909%}
910
911%rename(fdt_property) fdt_property_func;
912
913typedef int fdt32_t;
914
915%include "libfdt/fdt.h"
916
917%include "typemaps.i"
918
919/* Most functions don't change the device tree, so use a const void * */
920%typemap(in) (const void *)(const void *fdt) {
921	if (!PyByteArray_Check($input)) {
922		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
923			"', argument " "$argnum"" of type '" "$type""'");
924	}
925	$1 = (void *)PyByteArray_AsString($input);
926        fdt = $1;
927        fdt = fdt; /* avoid unused variable warning */
928}
929
930/* Some functions do change the device tree, so use void * */
931%typemap(in) (void *)(const void *fdt) {
932	if (!PyByteArray_Check($input)) {
933		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
934			"', argument " "$argnum"" of type '" "$type""'");
935	}
936	$1 = PyByteArray_AsString($input);
937        fdt = $1;
938        fdt = fdt; /* avoid unused variable warning */
939}
940
941/* typemap used for fdt_get_property_by_offset() */
942%typemap(out) (struct fdt_property *) {
943	PyObject *buff;
944
945	if ($1) {
946		resultobj = PyString_FromString(
947			fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
948		buff = PyByteArray_FromStringAndSize(
949			(const char *)($1 + 1), fdt32_to_cpu($1->len));
950		resultobj = SWIG_Python_AppendOutput(resultobj, buff);
951	}
952}
953
954%apply int *OUTPUT { int *lenp };
955
956/* typemap used for fdt_getprop() */
957%typemap(out) (const void *) {
958	if (!$1)
959		$result = Py_None;
960	else
961		$result = Py_BuildValue("s#", $1, *arg4);
962}
963
964/* typemap used for fdt_setprop() */
965%typemap(in) (const void *val) {
966    $1 = PyString_AsString($input);   /* char *str */
967}
968
969/* typemap used for fdt_add_reservemap_entry() */
970%typemap(in) uint64_t {
971   $1 = PyLong_AsUnsignedLong($input);
972}
973
974/* typemaps used for fdt_next_node() */
975%typemap(in, numinputs=1) int *depth (int depth) {
976   depth = (int) PyInt_AsLong($input);
977   $1 = &depth;
978}
979
980%typemap(argout) int *depth {
981        PyObject *val = Py_BuildValue("i", *arg$argnum);
982        resultobj = SWIG_Python_AppendOutput(resultobj, val);
983}
984
985%apply int *depth { int *depth };
986
987/* typemaps for fdt_get_mem_rsv */
988%typemap(in, numinputs=0) uint64_t * (uint64_t temp) {
989   $1 = &temp;
990}
991
992%typemap(argout) uint64_t * {
993        PyObject *val = PyLong_FromUnsignedLong(*arg$argnum);
994        if (!result) {
995           if (PyTuple_GET_SIZE(resultobj) == 0)
996              resultobj = val;
997           else
998              resultobj = SWIG_Python_AppendOutput(resultobj, val);
999        }
1000}
1001
1002/* We have both struct fdt_property and a function fdt_property() */
1003%warnfilter(302) fdt_property;
1004
1005/* These are macros in the header so have to be redefined here */
1006int fdt_magic(const void *fdt);
1007int fdt_totalsize(const void *fdt);
1008int fdt_off_dt_struct(const void *fdt);
1009int fdt_off_dt_strings(const void *fdt);
1010int fdt_off_mem_rsvmap(const void *fdt);
1011int fdt_version(const void *fdt);
1012int fdt_last_comp_version(const void *fdt);
1013int fdt_boot_cpuid_phys(const void *fdt);
1014int fdt_size_dt_strings(const void *fdt);
1015int fdt_size_dt_struct(const void *fdt);
1016int fdt_property_string(void *fdt, const char *name, const char *val);
1017int fdt_property_cell(void *fdt, const char *name, uint32_t val);
1018
1019/*
1020 * This function has a stub since the name fdt_property is used for both a
1021  * function and a struct, which confuses SWIG.
1022 */
1023int _fdt_property(void *fdt, const char *name, const char *val, int len);
1024
1025%include <../libfdt/libfdt.h>
1026