]> git.sur5r.net Git - u-boot/blob - scripts/dtc/pylibfdt/libfdt.i_shipped
6774b93b2cb659432e8ea51456fae08fc1f5958f
[u-boot] / 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  * 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  */
21 static 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
30 import 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.
56 QUIET_NOTFOUND = (NOTFOUND,)
57
58
59 class 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
67 def 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
78 def 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
98 def 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
123 class 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
632 class 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
666 class 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
889 class 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
913 typedef 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 */
1006 int fdt_magic(const void *fdt);
1007 int fdt_totalsize(const void *fdt);
1008 int fdt_off_dt_struct(const void *fdt);
1009 int fdt_off_dt_strings(const void *fdt);
1010 int fdt_off_mem_rsvmap(const void *fdt);
1011 int fdt_version(const void *fdt);
1012 int fdt_last_comp_version(const void *fdt);
1013 int fdt_boot_cpuid_phys(const void *fdt);
1014 int fdt_size_dt_strings(const void *fdt);
1015 int fdt_size_dt_struct(const void *fdt);
1016 int fdt_property_string(void *fdt, const char *name, const char *val);
1017 int 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  */
1023 int _fdt_property(void *fdt, const char *name, const char *val, int len);
1024
1025 %include <../libfdt/libfdt.h>