3 # Copyright (C) 2016 Google, Inc
4 # Written by Simon Glass <sjg@chromium.org>
6 # SPDX-License-Identifier: GPL-2.0+
11 from fdt import Fdt, NodeBase, PropBase
15 # This deals with a device tree, presenting it as a list of Node and Prop
16 # objects, representing nodes and properties, respectively.
18 # This implementation uses the fdtget tool to access the device tree, so it
19 # is not very efficient for larger trees. The tool is called once for each
20 # node and property in the tree.
23 """A device tree property
26 name: Property name (as per the device tree)
27 value: Property value as a string of bytes, or a list of strings of
31 def __init__(self, node, name, byte_list_str):
32 PropBase.__init__(self, node, 0, name)
33 if not byte_list_str.strip():
34 self.type = fdt_util.TYPE_BOOL
36 self.bytes = [chr(int(byte, 16))
37 for byte in byte_list_str.strip().split(' ')]
38 self.type, self.value = fdt_util.BytesToValue(''.join(self.bytes))
41 """Get a (single) phandle value from a property
43 Gets the phandle valuie from a property and returns it as an integer
45 return fdt_util.fdt32_to_cpu(self.value[:4])
47 def Widen(self, newprop):
48 """Figure out which property type is more general
50 Given a current property and a new property, this function returns the
51 one that is less specific as to type. The less specific property will
52 be ble to represent the data in the more specific property. This is
64 He we want to use an int array for 'value'. The first property
65 suggests that a single int is enough, but the second one shows that
66 it is not. Calling this function with these two propertes would
67 update the current property to be like the second, since it is less
70 if newprop.type < self.type:
71 self.type = newprop.type
73 if type(newprop.value) == list and type(self.value) != list:
74 self.value = newprop.value
76 if type(self.value) == list and len(newprop.value) > len(self.value):
77 val = fdt_util.GetEmpty(self.type)
78 while len(self.value) < len(newprop.value):
79 self.value.append(val)
86 name: Device tree node tname
87 path: Full path to node, along with the node name itself
88 _fdt: Device tree object
89 subnodes: A list of subnodes for this node, each a Node object
90 props: A dict of properties for this node, each a Prop object.
91 Keyed by property name
93 def __init__(self, fdt, offset, name, path):
94 NodeBase.__init__(self, fdt, offset, name, path)
97 """Scan a node's properties and subnodes
99 This fills in the props and subnodes properties, recursively
100 searching into subnodes so that the entire tree is built.
102 for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
103 prop = Prop(self, name, byte_list_str)
104 self.props[name] = prop
106 for name in self._fdt.GetSubNodes(self.path):
107 sep = '' if self.path[-1] == '/' else '/'
108 path = self.path + sep + name
109 node = Node(self._fdt, 0, name, path)
110 self.subnodes.append(node)
115 class FdtFallback(Fdt):
116 """Provides simple access to a flat device tree blob using fdtget/fdtput
122 def __init__(self, fname):
123 Fdt.__init__(self, fname)
126 """Scan a device tree, building up a tree of Node objects
128 This fills in the self._root property
130 self._root = Node(self, 0, '/', '/')
134 """Get the root Node of the device tree
141 def GetSubNodes(self, node):
142 """Returns a list of sub-nodes of a given node
145 node: Node name to return children from
148 List of children in the node (each a string node name)
151 CmdError: if the node does not exist.
153 out = command.Output('fdtget', self._fname, '-l', node)
154 return out.strip().splitlines()
156 def GetProps(self, node, convert_dashes=False):
157 """Get all properties from a node
160 node: full path to node name to look in
161 convert_dashes: True to convert - to _ in node names
164 A dictionary containing all the properties, indexed by node name.
165 The entries are simply strings - no decoding of lists or numbers
169 CmdError: if the node does not exist.
171 out = command.Output('fdtget', self._fname, node, '-p')
172 props = out.strip().splitlines()
177 prop = re.sub('-', '_', prop)
178 props_dict[prop] = self.GetProp(node, name)
181 def GetProp(self, node, prop, default=None, typespec=None):
182 """Get a property from a device tree.
184 This looks up the given node and property, and returns the value as a
187 If the node or property does not exist, this will return the default
191 node: Full path to node to look up.
192 prop: Property name to look up.
193 default: Default value to return if nothing is present in the fdt,
194 or None to raise in this case. This will be converted to a
196 typespec: Type character to use (None for default, 's' for string)
199 string containing the property value.
202 CmdError: if the property does not exist and no default is provided.
204 args = [self._fname, node, prop, '-t', 'bx']
205 if default is not None:
206 args += ['-d', str(default)]
207 if typespec is not None:
208 args += ['-t%s' % typespec]
209 out = command.Output('fdtget', *args)
213 def Node(self, fdt, offset, name, path):
216 This is used by Fdt.Scan() to create a new node using the correct
221 offset: Offset of node
223 path: Full path to node
225 node = Node(fdt, offset, name, path)