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 a libfdt Python library to access the device tree,
17 # so it is fairly efficient.
20 """A device tree property
23 name: Property name (as per the device tree)
24 value: Property value as a string of bytes, or a list of strings of
28 def __init__(self, name, bytes):
32 self.type = fdt_util.TYPE_BOOL
35 self.type, self.value = fdt_util.BytesToValue(bytes)
38 """Get a (single) phandle value from a property
40 Gets the phandle valuie from a property and returns it as an integer
42 return fdt_util.fdt32_to_cpu(self.value[:4])
44 def Widen(self, newprop):
45 """Figure out which property type is more general
47 Given a current property and a new property, this function returns the
48 one that is less specific as to type. The less specific property will
49 be ble to represent the data in the more specific property. This is
61 He we want to use an int array for 'value'. The first property
62 suggests that a single int is enough, but the second one shows that
63 it is not. Calling this function with these two propertes would
64 update the current property to be like the second, since it is less
67 if newprop.type < self.type:
68 self.type = newprop.type
70 if type(newprop.value) == list and type(self.value) != list:
71 self.value = [self.value]
73 if type(self.value) == list and len(newprop.value) > len(self.value):
74 val = fdt_util.GetEmpty(self.type)
75 while len(self.value) < len(newprop.value):
76 self.value.append(val)
83 offset: Integer offset in the device tree
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, offset, name, path):
100 """Scan a node's properties and subnodes
102 This fills in the props and subnodes properties, recursively
103 searching into subnodes so that the entire tree is built.
105 self.props = self._fdt.GetProps(self.path)
107 offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.offset)
109 sep = '' if self.path[-1] == '/' else '/'
110 name = libfdt.Name(self._fdt.GetFdt(), offset)
111 path = self.path + sep + name
112 node = Node(self._fdt, offset, name, path)
113 self.subnodes.append(node)
116 offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
120 """Provides simple access to a flat device tree blob.
123 fname: Filename of fdt
124 _root: Root of device tree (a Node object)
127 def __init__(self, fname):
129 with open(fname) as fd:
130 self._fdt = fd.read()
133 """Get the contents of the FDT
136 The FDT contents as a string of bytes
141 """Scan a device tree, building up a tree of Node objects
143 This fills in the self._root property
145 self._root = Node(self, 0, '/', '/')
149 """Get the root Node of the device tree
156 def GetProps(self, node):
157 """Get all properties from a node.
160 node: Full path to node name to look in.
163 A dictionary containing all the properties, indexed by node name.
164 The entries are Prop objects.
167 ValueError: if the node does not exist.
169 offset = libfdt.fdt_path_offset(self._fdt, node)
173 poffset = libfdt.fdt_first_property_offset(self._fdt, offset)
175 dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
176 prop = Prop(libfdt.String(self._fdt, dprop.nameoff), libfdt.Data(dprop))
177 props_dict[prop.name] = prop
179 poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)