blob: 5b38e63b267f1220379330897265eb4c68787e78 [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 """
Simon Glass04402d32018-07-06 10:27:21 -0600445 err = check_err(fdt_pack(self._fdt), quiet)
446 if err:
447 return err
448 del self._fdt[self.totalsize():]
449 return err
Simon Glassa13d9022017-05-27 07:38:11 -0600450
Simon Glass70cd0d72018-07-06 10:27:20 -0600451 def getprop(self, nodeoffset, prop_name, quiet=()):
452 """Get a property from a node
Simon Glassa13d9022017-05-27 07:38:11 -0600453
454 Args:
Simon Glass70cd0d72018-07-06 10:27:20 -0600455 nodeoffset: Node offset containing property to get
456 prop_name: Name of property to get
457 quiet: Errors to ignore (empty to raise on all errors)
458
459 Returns:
460 Value of property as a string, or -ve error number
Simon Glassa13d9022017-05-27 07:38:11 -0600461
462 Raises:
Simon Glass70cd0d72018-07-06 10:27:20 -0600463 FdtError if any error occurs (e.g. the property is not found)
Simon Glassa13d9022017-05-27 07:38:11 -0600464 """
Simon Glass70cd0d72018-07-06 10:27:20 -0600465 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
466 quiet)
467 if isinstance(pdata, (int)):
468 return pdata
469 return str(pdata[0])
Simon Glassa13d9022017-05-27 07:38:11 -0600470
Simon Glass70cd0d72018-07-06 10:27:20 -0600471 def getprop_obj(self, nodeoffset, prop_name, quiet=()):
472 """Get a property from a node as a Property object
Simon Glassa13d9022017-05-27 07:38:11 -0600473
474 Args:
475 nodeoffset: Node offset containing property to get
476 prop_name: Name of property to get
477 quiet: Errors to ignore (empty to raise on all errors)
478
479 Returns:
Simon Glass70cd0d72018-07-06 10:27:20 -0600480 Property object, or None if not found
Simon Glassa13d9022017-05-27 07:38:11 -0600481
482 Raises:
483 FdtError if any error occurs (e.g. the property is not found)
484 """
485 pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
486 quiet)
487 if isinstance(pdata, (int)):
Simon Glass70cd0d72018-07-06 10:27:20 -0600488 return None
489 return Property(prop_name, bytearray(pdata[0]))
Simon Glassa13d9022017-05-27 07:38:11 -0600490
Simon Glass460b2522017-08-29 14:15:46 -0600491 def get_phandle(self, nodeoffset):
492 """Get the phandle of a node
493
494 Args:
495 nodeoffset: Node offset to check
496
497 Returns:
498 phandle of node, or 0 if the node has no phandle or another error
499 occurs
500 """
501 return fdt_get_phandle(self._fdt, nodeoffset)
502
503 def parent_offset(self, nodeoffset, quiet=()):
504 """Get the offset of a node's parent
505
506 Args:
507 nodeoffset: Node offset to check
508 quiet: Errors to ignore (empty to raise on all errors)
509
510 Returns:
511 The offset of the parent node, if any
512
513 Raises:
514 FdtException if no parent found or other error occurs
515 """
516 return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
517
Simon Glass70cd0d72018-07-06 10:27:20 -0600518 def set_name(self, nodeoffset, name, quiet=()):
519 """Set the name of a node
520
521 Args:
522 nodeoffset: Node offset of node to update
523 name: New node name
524
525 Returns:
526 Error code, or 0 if OK
527
528 Raises:
529 FdtException if no parent found or other error occurs
530 """
531 return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet)
532
533 def setprop(self, nodeoffset, prop_name, val, quiet=()):
534 """Set the value of a property
535
536 Args:
537 nodeoffset: Node offset containing the property to create/update
538 prop_name: Name of property
539 val: Value to write (string or bytearray)
540 quiet: Errors to ignore (empty to raise on all errors)
541
542 Returns:
543 Error code, or 0 if OK
544
545 Raises:
546 FdtException if no parent found or other error occurs
547 """
548 return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
549 len(val)), quiet)
550
551 def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
552 """Set the value of a property
553
554 Args:
555 nodeoffset: Node offset containing the property to create/update
556 prop_name: Name of property
557 val: Value to write (integer)
558 quiet: Errors to ignore (empty to raise on all errors)
559
560 Returns:
561 Error code, or 0 if OK
562
563 Raises:
564 FdtException if no parent found or other error occurs
565 """
566 return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val),
567 quiet)
568
569 def setprop_u64(self, nodeoffset, prop_name, val, quiet=()):
570 """Set the value of a property
571
572 Args:
573 nodeoffset: Node offset containing the property to create/update
574 prop_name: Name of property
575 val: Value to write (integer)
576 quiet: Errors to ignore (empty to raise on all errors)
577
578 Returns:
579 Error code, or 0 if OK
580
581 Raises:
582 FdtException if no parent found or other error occurs
583 """
584 return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val),
585 quiet)
586
587 def setprop_str(self, nodeoffset, prop_name, val, quiet=()):
588 """Set the string value of a property
589
590 The property is set to the string, with a nul terminator added
591
592 Args:
593 nodeoffset: Node offset containing the property to create/update
594 prop_name: Name of property
595 val: Value to write (string without nul terminator)
596 quiet: Errors to ignore (empty to raise on all errors)
597
598 Returns:
599 Error code, or 0 if OK
600
601 Raises:
602 FdtException if no parent found or other error occurs
603 """
604 val += '\0'
605 return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name,
606 val, len(val)), quiet)
607
608 def delprop(self, nodeoffset, prop_name):
609 """Delete a property from a node
610
611 Args:
612 nodeoffset: Node offset containing property to delete
613 prop_name: Name of property to delete
614
615 Raises:
616 FdtError if the property does not exist, or another error occurs
617 """
618 return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
619
Simon Glass460b2522017-08-29 14:15:46 -0600620 def node_offset_by_phandle(self, phandle, quiet=()):
621 """Get the offset of a node with the given phandle
622
623 Args:
624 phandle: Phandle to search for
625 quiet: Errors to ignore (empty to raise on all errors)
626
627 Returns:
628 The offset of node with that phandle, if any
629
630 Raises:
631 FdtException if no node found or other error occurs
632 """
633 return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
Simon Glassa13d9022017-05-27 07:38:11 -0600634
Simon Glass70cd0d72018-07-06 10:27:20 -0600635
636class Property(bytearray):
Simon Glassa13d9022017-05-27 07:38:11 -0600637 """Holds a device tree property name and value.
638
639 This holds a copy of a property taken from the device tree. It does not
640 reference the device tree, so if anything changes in the device tree,
641 a Property object will remain valid.
642
643 Properties:
644 name: Property name
Simon Glass70cd0d72018-07-06 10:27:20 -0600645 value: Property value as a bytearray
Simon Glassa13d9022017-05-27 07:38:11 -0600646 """
647 def __init__(self, name, value):
Simon Glass70cd0d72018-07-06 10:27:20 -0600648 bytearray.__init__(self, value)
Simon Glassa13d9022017-05-27 07:38:11 -0600649 self.name = name
Simon Glass70cd0d72018-07-06 10:27:20 -0600650
651 def as_cell(self, fmt):
652 return struct.unpack('>' + fmt, self)[0]
653
654 def as_uint32(self):
655 return self.as_cell('L')
656
657 def as_int32(self):
658 return self.as_cell('l')
659
660 def as_uint64(self):
661 return self.as_cell('Q')
662
663 def as_int64(self):
664 return self.as_cell('q')
665
666 def as_str(self):
667 return self[:-1]
668
669
670class FdtSw(object):
671 """Software interface to create a device tree from scratch
672
673 The methods in this class work by adding to an existing 'partial' device
674 tree buffer of a fixed size created by instantiating this class. When the
675 tree is complete, call finish() to complete the device tree so that it can
676 be used.
677
678 Similarly with nodes, a new node is started with begin_node() and finished
679 with end_node().
680
681 The context manager functions can be used to make this a bit easier:
682
683 # First create the device tree with a node and property:
684 with FdtSw(small_size) as sw:
685 with sw.AddNode('node'):
686 sw.property_u32('reg', 2)
687 fdt = sw.AsFdt()
688
689 # Now we can use it as a real device tree
690 fdt.setprop_u32(0, 'reg', 3)
691 """
692 def __init__(self, size, quiet=()):
693 fdtrw = bytearray(size)
694 err = check_err(fdt_create(fdtrw, size))
695 if err:
696 return err
697 self._fdtrw = fdtrw
698
699 def __enter__(self):
700 """Contact manager to use to create a device tree via software"""
701 return self
702
703 def __exit__(self, type, value, traceback):
704 check_err(fdt_finish(self._fdtrw))
705
706 def AsFdt(self):
707 """Convert a FdtSw into an Fdt so it can be accessed as normal
708
709 Note that finish() must be called before this function will work. If
710 you are using the context manager (see 'with' code in the FdtSw class
711 comment) then this will happen automatically.
712
713 Returns:
714 Fdt object allowing access to the newly created device tree
715 """
716 return Fdt(self._fdtrw)
717
718 def resize(self, size, quiet=()):
719 """Resize the buffer to accommodate a larger tree
720
721 Args:
722 size: New size of tree
723 quiet: Errors to ignore (empty to raise on all errors)
724
725 Raises:
726 FdtException if no node found or other error occurs
727 """
728 fdt = bytearray(size)
729 fdt[:len(self._fdtrw)] = self._fdtrw
730 err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet)
731 if err:
732 return err
733 self._fdtrw = fdt
734
735 def add_reservemap_entry(self, addr, size, quiet=()):
736 """Add a new memory reserve map entry
737
738 Once finished adding, you must call finish_reservemap().
739
740 Args:
741 addr: 64-bit start address
742 size: 64-bit size
743 quiet: Errors to ignore (empty to raise on all errors)
744
745 Raises:
746 FdtException if no node found or other error occurs
747 """
748 return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size),
749 quiet)
750
751 def finish_reservemap(self, quiet=()):
752 """Indicate that there are no more reserve map entries to add
753
754 Args:
755 quiet: Errors to ignore (empty to raise on all errors)
756
757 Raises:
758 FdtException if no node found or other error occurs
759 """
760 return check_err(fdt_finish_reservemap(self._fdtrw), quiet)
761
762 def begin_node(self, name, quiet=()):
763 """Begin a new node
764
765 Use this before adding properties to the node. Then call end_node() to
766 finish it. You can also use the context manager as shown in the FdtSw
767 class comment.
768
769 Args:
770 name: Name of node to begin
771 quiet: Errors to ignore (empty to raise on all errors)
772
773 Raises:
774 FdtException if no node found or other error occurs
775 """
776 return check_err(fdt_begin_node(self._fdtrw, name), quiet)
777
778 def property_string(self, name, string, quiet=()):
779 """Add a property with a string value
780
781 The string will be nul-terminated when written to the device tree
782
783 Args:
784 name: Name of property to add
785 string: String value of property
786 quiet: Errors to ignore (empty to raise on all errors)
787
788 Raises:
789 FdtException if no node found or other error occurs
790 """
791 return check_err(fdt_property_string(self._fdtrw, name, string), quiet)
792
793 def property_u32(self, name, val, quiet=()):
794 """Add a property with a 32-bit value
795
796 Write a single-cell value to the device tree
797
798 Args:
799 name: Name of property to add
800 val: Value of property
801 quiet: Errors to ignore (empty to raise on all errors)
802
803 Raises:
804 FdtException if no node found or other error occurs
805 """
806 return check_err(fdt_property_u32(self._fdtrw, name, val), quiet)
807
808 def property_u64(self, name, val, quiet=()):
809 """Add a property with a 64-bit value
810
811 Write a double-cell value to the device tree in big-endian format
812
813 Args:
814 name: Name of property to add
815 val: Value of property
816 quiet: Errors to ignore (empty to raise on all errors)
817
818 Raises:
819 FdtException if no node found or other error occurs
820 """
821 return check_err(fdt_property_u64(self._fdtrw, name, val), quiet)
822
823 def property_cell(self, name, val, quiet=()):
824 """Add a property with a single-cell value
825
826 Write a single-cell value to the device tree
827
828 Args:
829 name: Name of property to add
830 val: Value of property
831 quiet: Errors to ignore (empty to raise on all errors)
832
833 Raises:
834 FdtException if no node found or other error occurs
835 """
836 return check_err(fdt_property_cell(self._fdtrw, name, val), quiet)
837
838 def property(self, name, val, quiet=()):
839 """Add a property
840
841 Write a new property with the given value to the device tree. The value
842 is taken as is and is not nul-terminated
843
844 Args:
845 name: Name of property to add
846 val: Value of property
847 quiet: Errors to ignore (empty to raise on all errors)
848
849 Raises:
850 FdtException if no node found or other error occurs
851 """
852 return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet)
853
854 def end_node(self, quiet=()):
855 """End a node
856
857 Use this after adding properties to a node to close it off. You can also
858 use the context manager as shown in the FdtSw class comment.
859
860 Args:
861 quiet: Errors to ignore (empty to raise on all errors)
862
863 Raises:
864 FdtException if no node found or other error occurs
865 """
866 return check_err(fdt_end_node(self._fdtrw), quiet)
867
868 def finish(self, quiet=()):
869 """Finish writing the device tree
870
871 This closes off the device tree ready for use
872
873 Args:
874 quiet: Errors to ignore (empty to raise on all errors)
875
876 Raises:
877 FdtException if no node found or other error occurs
878 """
879 return check_err(fdt_finish(self._fdtrw), quiet)
880
881 def AddNode(self, name):
882 """Create a new context for adding a node
883
884 When used in a 'with' clause this starts a new node and finishes it
885 afterward.
886
887 Args:
888 name: Name of node to add
889 """
890 return NodeAdder(self._fdtrw, name)
891
892
893class NodeAdder():
894 """Class to provide a node context
895
896 This allows you to add nodes in a more natural way:
897
898 with fdtsw.AddNode('name'):
899 fdtsw.property_string('test', 'value')
900
901 The node is automatically completed with a call to end_node() when the
902 context exits.
903 """
904 def __init__(self, fdt, name):
905 self._fdt = fdt
906 self._name = name
907
908 def __enter__(self):
909 check_err(fdt_begin_node(self._fdt, self._name))
910
911 def __exit__(self, type, value, traceback):
912 check_err(fdt_end_node(self._fdt))
Simon Glassa13d9022017-05-27 07:38:11 -0600913%}
914
915%rename(fdt_property) fdt_property_func;
916
917typedef int fdt32_t;
918
919%include "libfdt/fdt.h"
920
921%include "typemaps.i"
922
923/* Most functions don't change the device tree, so use a const void * */
924%typemap(in) (const void *)(const void *fdt) {
925 if (!PyByteArray_Check($input)) {
926 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
927 "', argument " "$argnum"" of type '" "$type""'");
928 }
929 $1 = (void *)PyByteArray_AsString($input);
930 fdt = $1;
931 fdt = fdt; /* avoid unused variable warning */
932}
933
934/* Some functions do change the device tree, so use void * */
935%typemap(in) (void *)(const void *fdt) {
936 if (!PyByteArray_Check($input)) {
937 SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
938 "', argument " "$argnum"" of type '" "$type""'");
939 }
940 $1 = PyByteArray_AsString($input);
941 fdt = $1;
942 fdt = fdt; /* avoid unused variable warning */
943}
944
Simon Glass70cd0d72018-07-06 10:27:20 -0600945/* typemap used for fdt_get_property_by_offset() */
Simon Glassa13d9022017-05-27 07:38:11 -0600946%typemap(out) (struct fdt_property *) {
947 PyObject *buff;
948
949 if ($1) {
950 resultobj = PyString_FromString(
951 fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
952 buff = PyByteArray_FromStringAndSize(
953 (const char *)($1 + 1), fdt32_to_cpu($1->len));
954 resultobj = SWIG_Python_AppendOutput(resultobj, buff);
955 }
956}
957
958%apply int *OUTPUT { int *lenp };
959
960/* typemap used for fdt_getprop() */
961%typemap(out) (const void *) {
962 if (!$1)
963 $result = Py_None;
964 else
965 $result = Py_BuildValue("s#", $1, *arg4);
966}
967
Simon Glass70cd0d72018-07-06 10:27:20 -0600968/* typemap used for fdt_setprop() */
969%typemap(in) (const void *val) {
970 $1 = PyString_AsString($input); /* char *str */
971}
972
973/* typemap used for fdt_add_reservemap_entry() */
974%typemap(in) uint64_t {
975 $1 = PyLong_AsUnsignedLong($input);
976}
977
978/* typemaps used for fdt_next_node() */
979%typemap(in, numinputs=1) int *depth (int depth) {
980 depth = (int) PyInt_AsLong($input);
981 $1 = &depth;
982}
983
984%typemap(argout) int *depth {
985 PyObject *val = Py_BuildValue("i", *arg$argnum);
986 resultobj = SWIG_Python_AppendOutput(resultobj, val);
987}
988
989%apply int *depth { int *depth };
990
991/* typemaps for fdt_get_mem_rsv */
992%typemap(in, numinputs=0) uint64_t * (uint64_t temp) {
993 $1 = &temp;
994}
995
996%typemap(argout) uint64_t * {
997 PyObject *val = PyLong_FromUnsignedLong(*arg$argnum);
998 if (!result) {
999 if (PyTuple_GET_SIZE(resultobj) == 0)
1000 resultobj = val;
1001 else
1002 resultobj = SWIG_Python_AppendOutput(resultobj, val);
1003 }
1004}
1005
Simon Glassa13d9022017-05-27 07:38:11 -06001006/* We have both struct fdt_property and a function fdt_property() */
1007%warnfilter(302) fdt_property;
1008
1009/* These are macros in the header so have to be redefined here */
1010int fdt_magic(const void *fdt);
1011int fdt_totalsize(const void *fdt);
1012int fdt_off_dt_struct(const void *fdt);
1013int fdt_off_dt_strings(const void *fdt);
1014int fdt_off_mem_rsvmap(const void *fdt);
1015int fdt_version(const void *fdt);
1016int fdt_last_comp_version(const void *fdt);
1017int fdt_boot_cpuid_phys(const void *fdt);
1018int fdt_size_dt_strings(const void *fdt);
1019int fdt_size_dt_struct(const void *fdt);
Simon Glass70cd0d72018-07-06 10:27:20 -06001020int fdt_property_string(void *fdt, const char *name, const char *val);
1021int fdt_property_cell(void *fdt, const char *name, uint32_t val);
1022
1023/*
1024 * This function has a stub since the name fdt_property is used for both a
1025 * function and a struct, which confuses SWIG.
1026 */
1027int _fdt_property(void *fdt, const char *name, const char *val, int len);
Simon Glassa13d9022017-05-27 07:38:11 -06001028
1029%include <../libfdt/libfdt.h>