3 # Copyright (C) 2016 Google, Inc
4 # Written by Simon Glass <sjg@chromium.org>
6 # SPDX-License-Identifier: GPL-2.0+
13 # This deals with a device tree, presenting it as a list of Node and Prop
14 # objects, representing nodes and properties, respectively.
16 # This implementation uses the fdtget tool to access the device tree, so it
17 # is not very efficient for larger trees. The tool is called once for each
18 # node and property in the tree.
21 """A device tree property
24 name: Property name (as per the device tree)
25 value: Property value as a string of bytes, or a list of strings of
29 def __init__(self, name, byte_list_str):
32 if not byte_list_str.strip():
33 self.type = fdt_util.TYPE_BOOL
35 bytes = [chr(int(byte, 16)) for byte in byte_list_str.strip().split(' ')]
36 self.type, self.value = fdt_util.BytesToValue(''.join(bytes))
39 """Get a (single) phandle value from a property
41 Gets the phandle valuie from a property and returns it as an integer
43 return fdt_util.fdt32_to_cpu(self.value[:4])
45 def Widen(self, newprop):
46 """Figure out which property type is more general
48 Given a current property and a new property, this function returns the
49 one that is less specific as to type. The less specific property will
50 be ble to represent the data in the more specific property. This is
62 He we want to use an int array for 'value'. The first property
63 suggests that a single int is enough, but the second one shows that
64 it is not. Calling this function with these two propertes would
65 update the current property to be like the second, since it is less
68 if newprop.type < self.type:
69 self.type = newprop.type
71 if type(newprop.value) == list and type(self.value) != list:
72 self.value = newprop.value
74 if type(self.value) == list and len(newprop.value) > len(self.value):
75 val = fdt_util.GetEmpty(self.type)
76 while len(self.value) < len(newprop.value):
77 self.value.append(val)
84 name: Device tree node tname
85 path: Full path to node, along with the node name itself
86 _fdt: Device tree object
87 subnodes: A list of subnodes for this node, each a Node object
88 props: A dict of properties for this node, each a Prop object.
89 Keyed by property name
91 def __init__(self, fdt, name, path):
99 """Scan a node's properties and subnodes
101 This fills in the props and subnodes properties, recursively
102 searching into subnodes so that the entire tree is built.
104 for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
105 prop = Prop(name, byte_list_str)
106 self.props[name] = prop
108 for name in self._fdt.GetSubNodes(self.path):
109 sep = '' if self.path[-1] == '/' else '/'
110 path = self.path + sep + name
111 node = Node(self._fdt, name, path)
112 self.subnodes.append(node)
118 """Provides simple access to a flat device tree blob.
121 fname: Filename of fdt
122 _root: Root of device tree (a Node object)
125 def __init__(self, fname):
129 """Scan a device tree, building up a tree of Node objects
131 This fills in the self._root property
133 self._root = Node(self, '/', '/')
137 """Get the root Node of the device tree
144 def GetSubNodes(self, node):
145 """Returns a list of sub-nodes of a given node
148 node: Node name to return children from
151 List of children in the node (each a string node name)
154 CmdError: if the node does not exist.
156 out = command.Output('fdtget', self.fname, '-l', node)
157 return out.strip().splitlines()
159 def GetProps(self, node, convert_dashes=False):
160 """Get all properties from a node
163 node: full path to node name to look in
164 convert_dashes: True to convert - to _ in node names
167 A dictionary containing all the properties, indexed by node name.
168 The entries are simply strings - no decoding of lists or numbers
172 CmdError: if the node does not exist.
174 out = command.Output('fdtget', self.fname, node, '-p')
175 props = out.strip().splitlines()
180 prop = re.sub('-', '_', prop)
181 props_dict[prop] = self.GetProp(node, name)
184 def GetProp(self, node, prop, default=None, typespec=None):
185 """Get a property from a device tree.
187 This looks up the given node and property, and returns the value as a
190 If the node or property does not exist, this will return the default
194 node: Full path to node to look up.
195 prop: Property name to look up.
196 default: Default value to return if nothing is present in the fdt,
197 or None to raise in this case. This will be converted to a
199 typespec: Type character to use (None for default, 's' for string)
202 string containing the property value.
205 CmdError: if the property does not exist and no default is provided.
207 args = [self.fname, node, prop, '-t', 'bx']
208 if default is not None:
209 args += ['-d', str(default)]
210 if typespec is not None:
211 args += ['-t%s' % typespec]
212 out = command.Output('fdtget', *args)