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