blob: 6774b93b2cb659432e8ea51456fae08fc1f5958f [file] [log] [blame]
Tom Rini8b0c8a12018-05-06 18:27:01 -04001/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
Simon Glassa13d9022017-05-27 07:38:11 -06002/*
3 * pylibfdt - Flat Device Tree manipulation in Python
4 * Copyright (C) 2017 Google, Inc.
5 * Written by Simon Glass <sjg@chromium.org>
Simon Glassa13d9022017-05-27 07:38:11 -06006 */
7
8%module libfdt
9
Simon Glass1c879312017-08-13 16:02:54 -060010%include <stdint.i>
11
Simon Glassa13d9022017-05-27 07:38:11 -060012%{
13#define SWIG_FILE_WITH_INIT
14#include "libfdt.h"
Simon Glass70cd0d72018-07-06 10:27:20 -060015
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
Simon Glassa13d9022017-05-27 07:38:11 -060026%}
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
Simon Glass70cd0d72018-07-06 10:27:20 -0600122
Simon Glassa13d9022017-05-27 07:38:11 -0600123class 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
Simon Glass70cd0d72018-07-06 10:27:20 -0600144 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
Simon Glass460b2522017-08-29 14:15:46 -0600301 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
Simon Glassa13d9022017-05-27 07:38:11 -0600318 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
Simon Glass70cd0d72018-07-06 10:27:20 -0600333 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
Simon Glassa13d9022017-05-27 07:38:11 -0600347 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
Simon Glassa13d9022017-05-27 07:38:11 -0600381 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
Simon Glass70cd0d72018-07-06 10:27:20 -0600401 @staticmethod
402 def create_empty_tree(size, quiet=()):
403 """Create an empty device tree ready for use
Simon Glassa13d9022017-05-27 07:38:11 -0600404
405 Args:
Simon Glass70cd0d72018-07-06 10:27:20 -0600406 size: Size of device tree in bytes
Simon Glassa13d9022017-05-27 07:38:11 -0600407
408 Returns:
Simon Glass70cd0d72018-07-06 10:27:20 -0600409 Fdt object containing the device tree
Simon Glassa13d9022017-05-27 07:38:11 -0600410 """
Simon Glass70cd0d72018-07-06 10:27:20 -0600411 data = bytearray(size)
412 err = check_err(fdt_create_empty_tree(data, size), quiet)
413 if err:
414 return err
415 return Fdt(data)
Simon Glassa13d9022017-05-27 07:38:11 -0600416
Simon Glass70cd0d72018-07-06 10:27:20 -0600417 def open_into(self, size, quiet=()):
418 """Move the device tree into a larger or smaller space
Simon Glassa13d9022017-05-27 07:38:11 -0600419
Simon Glass70cd0d72018-07-06 10:27:20 -0600420 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.
Simon Glassa13d9022017-05-27 07:38:11 -0600423
Simon Glass70cd0d72018-07-06 10:27:20 -0600424 Args:
425 size: Required new size of device tree in bytes
Simon Glassa13d9022017-05-27 07:38:11 -0600426 """
Simon Glass70cd0d72018-07-06 10:27:20 -0600427 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
Simon Glassa13d9022017-05-27 07:38:11 -0600433
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
Simon Glass70cd0d72018-07-06 10:27:20 -0600447 def getprop(self, nodeoffset, prop_name, quiet=()):
448 """Get a property from a node
Simon Glassa13d9022017-05-27 07:38:11 -0600449
450 Args:
Simon Glass70cd0d72018-07-06 10:27:20 -0600451 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
Simon Glassa13d9022017-05-27 07:38:11 -0600457
458 Raises:
Simon Glass70cd0d72018-07-06 10:27:20 -0600459 FdtError if any error occurs (e.g. the property is not found)
Simon Glassa13d9022017-05-27 07:38:11 -0600460 """
Simon Glass70cd0d72018-07-06 10:27:20 -0600461 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])
Simon Glassa13d9022017-05-27 07:38:11 -0600466
Simon Glass70cd0d72018-07-06 10:27:20 -0600467 def getprop_obj(self, nodeoffset, prop_name, quiet=()):
468 """Get a property from a node as a Property object
Simon Glassa13d9022017-05-27 07:38:11 -0600469
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:
Simon Glass70cd0d72018-07-06 10:27:20 -0600476 Property object, or None if not found
Simon Glassa13d9022017-05-27 07:38:11 -0600477
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)):
Simon Glass70cd0d72018-07-06 10:27:20 -0600484 return None
485 return Property(prop_name, bytearray(pdata[0]))
Simon Glassa13d9022017-05-27 07:38:11 -0600486
Simon Glass460b2522017-08-29 14:15:46 -0600487 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
Simon Glass70cd0d72018-07-06 10:27:20 -0600514 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
Simon Glass460b2522017-08-29 14:15:46 -0600616 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)
Simon Glassa13d9022017-05-27 07:38:11 -0600630
Simon Glass70cd0d72018-07-06 10:27:20 -0600631
632class Property(bytearray):
Simon Glassa13d9022017-05-27 07:38:11 -0600633 """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
Simon Glass70cd0d72018-07-06 10:27:20 -0600641 value: Property value as a bytearray
Simon Glassa13d9022017-05-27 07:38:11 -0600642 """
643 def __init__(self, name, value):
Simon Glass70cd0d72018-07-06 10:27:20 -0600644 bytearray.__init__(self, value)
Simon Glassa13d9022017-05-27 07:38:11 -0600645 self.name = name
Simon Glass70cd0d72018-07-06 10:27:20 -0600646
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))
Simon Glassa13d9022017-05-27 07:38:11 -0600909%}
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
Simon Glass70cd0d72018-07-06 10:27:20 -0600941/* typemap used for fdt_get_property_by_offset() */
Simon Glassa13d9022017-05-27 07:38:11 -0600942%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
Simon Glass70cd0d72018-07-06 10:27:20 -0600964/* 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
Simon Glassa13d9022017-05-27 07:38:11 -06001002/* 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);
Simon Glass70cd0d72018-07-06 10:27:20 -06001016int 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);
Simon Glassa13d9022017-05-27 07:38:11 -06001024
1025%include <../libfdt/libfdt.h>