3 # Copyright (C) 2016 Google, Inc
4 # Written by Simon Glass <sjg@chromium.org>
6 # SPDX-License-Identifier: GPL-2.0+
13 from fdt import Fdt, NodeBase, PropBase
17 # This deals with a device tree, presenting it as a list of Node and Prop
18 # objects, representing nodes and properties, respectively.
20 # This implementation uses a libfdt Python library to access the device tree,
21 # so it is fairly efficient.
24 """A device tree property
27 name: Property name (as per the device tree)
28 value: Property value as a string of bytes, or a list of strings of
32 def __init__(self, node, offset, name, bytes):
33 PropBase.__init__(self, node, offset, name)
36 self.type = fdt.TYPE_BOOL
39 self.type, self.value = self.BytesToValue(bytes)
42 """Get a (single) phandle value from a property
44 Gets the phandle valuie from a property and returns it as an integer
46 return fdt_util.fdt32_to_cpu(self.value[:4])
48 def Widen(self, newprop):
49 """Figure out which property type is more general
51 Given a current property and a new property, this function returns the
52 one that is less specific as to type. The less specific property will
53 be ble to represent the data in the more specific property. This is
65 He we want to use an int array for 'value'. The first property
66 suggests that a single int is enough, but the second one shows that
67 it is not. Calling this function with these two propertes would
68 update the current property to be like the second, since it is less
71 if newprop.type < self.type:
72 self.type = newprop.type
74 if type(newprop.value) == list and type(self.value) != list:
75 self.value = [self.value]
77 if type(self.value) == list and len(newprop.value) > len(self.value):
78 val = self.GetEmpty(self.type)
79 while len(self.value) < len(newprop.value):
80 self.value.append(val)
87 offset: Integer offset in the device tree
88 name: Device tree node tname
89 path: Full path to node, along with the node name itself
90 _fdt: Device tree object
91 subnodes: A list of subnodes for this node, each a Node object
92 props: A dict of properties for this node, each a Prop object.
93 Keyed by property name
95 def __init__(self, fdt, offset, name, path):
96 NodeBase.__init__(self, fdt, offset, 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 self.props = self._fdt.GetProps(self.path)
106 offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
108 sep = '' if self.path[-1] == '/' else '/'
109 name = libfdt.Name(self._fdt.GetFdt(), offset)
110 path = self.path + sep + name
111 node = Node(self._fdt, offset, name, path)
112 self.subnodes.append(node)
115 offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
118 class FdtNormal(Fdt):
119 """Provides simple access to a flat device tree blob using libfdt.
122 _fdt: Device tree contents (bytearray)
123 _cached_offsets: True if all the nodes have a valid _offset property,
124 False if something has changed to invalidate the offsets
126 def __init__(self, fname):
127 Fdt.__init__(self, fname)
128 with open(self._fname) as fd:
129 self._fdt = fd.read()
132 """Get the contents of the FDT
135 The FDT contents as a string of bytes
140 """Scan a device tree, building up a tree of Node objects
142 This fills in the self._root property
144 self._root = Node(self, 0, '/', '/')
148 """Get the root Node of the device tree
155 def GetProps(self, node):
156 """Get all properties from a node.
159 node: Full path to node name to look in.
162 A dictionary containing all the properties, indexed by node name.
163 The entries are Prop objects.
166 ValueError: if the node does not exist.
168 offset = libfdt.fdt_path_offset(self._fdt, node)
172 poffset = libfdt.fdt_first_property_offset(self._fdt, offset)
174 dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
175 prop = Prop(node, poffset, libfdt.String(self._fdt, dprop.nameoff),
177 props_dict[prop.name] = prop
179 poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
183 def Node(self, fdt, offset, name, path):
186 This is used by Fdt.Scan() to create a new node using the correct
191 offset: Offset of node
193 path: Full path to node
195 node = Node(fdt, offset, name, path)