blob: 329d03cc6b743e7f1af13d5cfb84375f1715a989 [file] [log] [blame]
Simon Glassa06a34b2016-07-25 18:59:04 -06001#!/usr/bin/python
2#
3# Copyright (C) 2016 Google, Inc
4# Written by Simon Glass <sjg@chromium.org>
5#
6# SPDX-License-Identifier: GPL-2.0+
7#
8
9import struct
10import sys
11
12import fdt_util
13
14# This deals with a device tree, presenting it as an assortment of Node and
15# Prop objects, representing nodes and properties, respectively. This file
16# contains the base classes and defines the high-level API. Most of the
17# implementation is in the FdtFallback and FdtNormal subclasses. See
18# fdt_select.py for how to create an Fdt object.
19
Simon Glassbc1dea32016-07-25 18:59:05 -060020# A list of types we support
21(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)
22
Simon Glassa06a34b2016-07-25 18:59:04 -060023def CheckErr(errnum, msg):
24 if errnum:
25 raise ValueError('Error %d: %s: %s' %
26 (errnum, libfdt.fdt_strerror(errnum), msg))
27
28class PropBase:
29 """A device tree property
30
31 Properties:
32 name: Property name (as per the device tree)
33 value: Property value as a string of bytes, or a list of strings of
34 bytes
35 type: Value type
36 """
37 def __init__(self, node, offset, name):
38 self._node = node
39 self._offset = offset
40 self.name = name
41 self.value = None
42
Simon Glassbc1dea32016-07-25 18:59:05 -060043 def BytesToValue(self, bytes):
44 """Converts a string of bytes into a type and value
45
46 Args:
47 A string containing bytes
48
49 Return:
50 A tuple:
51 Type of data
52 Data, either a single element or a list of elements. Each element
53 is one of:
54 TYPE_STRING: string value from the property
55 TYPE_INT: a byte-swapped integer stored as a 4-byte string
56 TYPE_BYTE: a byte stored as a single-byte string
57 """
58 size = len(bytes)
59 strings = bytes.split('\0')
60 is_string = True
61 count = len(strings) - 1
62 if count > 0 and not strings[-1]:
63 for string in strings[:-1]:
64 if not string:
65 is_string = False
66 break
67 for ch in string:
68 if ch < ' ' or ch > '~':
69 is_string = False
70 break
71 else:
72 is_string = False
73 if is_string:
74 if count == 1:
75 return TYPE_STRING, strings[0]
76 else:
77 return TYPE_STRING, strings[:-1]
78 if size % 4:
79 if size == 1:
80 return TYPE_BYTE, bytes[0]
81 else:
82 return TYPE_BYTE, list(bytes)
83 val = []
84 for i in range(0, size, 4):
85 val.append(bytes[i:i + 4])
86 if size == 4:
87 return TYPE_INT, val[0]
88 else:
89 return TYPE_INT, val
90
91 def GetEmpty(self, type):
92 """Get an empty / zero value of the given type
93
94 Returns:
95 A single value of the given type
96 """
97 if type == TYPE_BYTE:
98 return chr(0)
99 elif type == TYPE_INT:
100 return struct.pack('<I', 0);
101 elif type == TYPE_STRING:
102 return ''
103 else:
104 return True
105
Simon Glassa06a34b2016-07-25 18:59:04 -0600106class NodeBase:
107 """A device tree node
108
109 Properties:
110 offset: Integer offset in the device tree
111 name: Device tree node tname
112 path: Full path to node, along with the node name itself
113 _fdt: Device tree object
114 subnodes: A list of subnodes for this node, each a Node object
115 props: A dict of properties for this node, each a Prop object.
116 Keyed by property name
117 """
118 def __init__(self, fdt, offset, name, path):
119 self._fdt = fdt
120 self._offset = offset
121 self.name = name
122 self.path = path
123 self.subnodes = []
124 self.props = {}
125
126class Fdt:
127 """Provides simple access to a flat device tree blob.
128
129 Properties:
130 fname: Filename of fdt
131 _root: Root of device tree (a Node object)
132 """
133 def __init__(self, fname):
134 self._fname = fname