blob: 0c0ebbcf47a1217f42bebc529a69e76367cf9c5b [file] [log] [blame]
Simon Glassec564b42016-07-04 11:58:08 -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 command
Simon Glassa06a34b2016-07-25 18:59:04 -060010import fdt
11from fdt import Fdt, NodeBase, PropBase
Simon Glassec564b42016-07-04 11:58:08 -060012import fdt_util
13import sys
14
15# This deals with a device tree, presenting it as a list of Node and Prop
16# objects, representing nodes and properties, respectively.
17#
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.
21
Simon Glassa06a34b2016-07-25 18:59:04 -060022class Prop(PropBase):
Simon Glassec564b42016-07-04 11:58:08 -060023 """A device tree property
24
25 Properties:
26 name: Property name (as per the device tree)
27 value: Property value as a string of bytes, or a list of strings of
28 bytes
29 type: Value type
30 """
Simon Glassa06a34b2016-07-25 18:59:04 -060031 def __init__(self, node, name, byte_list_str):
32 PropBase.__init__(self, node, 0, name)
Simon Glassec564b42016-07-04 11:58:08 -060033 if not byte_list_str.strip():
Simon Glassbc1dea32016-07-25 18:59:05 -060034 self.type = fdt.TYPE_BOOL
Simon Glassec564b42016-07-04 11:58:08 -060035 return
Simon Glassa06a34b2016-07-25 18:59:04 -060036 self.bytes = [chr(int(byte, 16))
37 for byte in byte_list_str.strip().split(' ')]
Simon Glassbc1dea32016-07-25 18:59:05 -060038 self.type, self.value = self.BytesToValue(''.join(self.bytes))
Simon Glassec564b42016-07-04 11:58:08 -060039
Simon Glassd6a33912016-07-22 09:22:49 -060040
Simon Glassa06a34b2016-07-25 18:59:04 -060041class Node(NodeBase):
Simon Glassec564b42016-07-04 11:58:08 -060042 """A device tree node
43
44 Properties:
45 name: Device tree node tname
46 path: Full path to node, along with the node name itself
47 _fdt: Device tree object
48 subnodes: A list of subnodes for this node, each a Node object
49 props: A dict of properties for this node, each a Prop object.
50 Keyed by property name
51 """
Simon Glassa06a34b2016-07-25 18:59:04 -060052 def __init__(self, fdt, offset, name, path):
53 NodeBase.__init__(self, fdt, offset, name, path)
Simon Glassec564b42016-07-04 11:58:08 -060054
55 def Scan(self):
56 """Scan a node's properties and subnodes
57
58 This fills in the props and subnodes properties, recursively
59 searching into subnodes so that the entire tree is built.
60 """
61 for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
Simon Glassa06a34b2016-07-25 18:59:04 -060062 prop = Prop(self, name, byte_list_str)
Simon Glassec564b42016-07-04 11:58:08 -060063 self.props[name] = prop
64
65 for name in self._fdt.GetSubNodes(self.path):
66 sep = '' if self.path[-1] == '/' else '/'
67 path = self.path + sep + name
Simon Glassa06a34b2016-07-25 18:59:04 -060068 node = Node(self._fdt, 0, name, path)
Simon Glassec564b42016-07-04 11:58:08 -060069 self.subnodes.append(node)
70
71 node.Scan()
72
Simon Glass2a70d892016-07-25 18:59:14 -060073 def DeleteProp(self, prop_name):
74 """Delete a property of a node
75
76 The property is deleted using fdtput.
77
78 Args:
79 prop_name: Name of the property to delete
80 Raises:
81 CommandError if the property does not exist
82 """
83 args = [self._fdt._fname, '-d', self.path, prop_name]
84 command.Output('fdtput', *args)
85 del self.props[prop_name]
Simon Glassec564b42016-07-04 11:58:08 -060086
Simon Glassa06a34b2016-07-25 18:59:04 -060087class FdtFallback(Fdt):
88 """Provides simple access to a flat device tree blob using fdtget/fdtput
Simon Glassec564b42016-07-04 11:58:08 -060089
90 Properties:
Simon Glassa06a34b2016-07-25 18:59:04 -060091 See superclass
Simon Glassec564b42016-07-04 11:58:08 -060092 """
93
94 def __init__(self, fname):
Simon Glassa06a34b2016-07-25 18:59:04 -060095 Fdt.__init__(self, fname)
Simon Glass355c67c2016-07-25 18:59:10 -060096 if self._fname:
97 self._fname = fdt_util.EnsureCompiled(self._fname)
Simon Glassec564b42016-07-04 11:58:08 -060098
Simon Glassec564b42016-07-04 11:58:08 -060099 def GetSubNodes(self, node):
100 """Returns a list of sub-nodes of a given node
101
102 Args:
103 node: Node name to return children from
104
105 Returns:
106 List of children in the node (each a string node name)
107
108 Raises:
109 CmdError: if the node does not exist.
110 """
Simon Glassa06a34b2016-07-25 18:59:04 -0600111 out = command.Output('fdtget', self._fname, '-l', node)
Simon Glassec564b42016-07-04 11:58:08 -0600112 return out.strip().splitlines()
113
Simon Glass6b93c552016-07-25 18:59:11 -0600114 def GetProps(self, node):
Simon Glassec564b42016-07-04 11:58:08 -0600115 """Get all properties from a node
116
117 Args:
118 node: full path to node name to look in
Simon Glassec564b42016-07-04 11:58:08 -0600119
120 Returns:
121 A dictionary containing all the properties, indexed by node name.
122 The entries are simply strings - no decoding of lists or numbers
123 is done.
124
125 Raises:
126 CmdError: if the node does not exist.
127 """
Simon Glassa06a34b2016-07-25 18:59:04 -0600128 out = command.Output('fdtget', self._fname, node, '-p')
Simon Glassec564b42016-07-04 11:58:08 -0600129 props = out.strip().splitlines()
130 props_dict = {}
131 for prop in props:
132 name = prop
Simon Glassec564b42016-07-04 11:58:08 -0600133 props_dict[prop] = self.GetProp(node, name)
134 return props_dict
135
136 def GetProp(self, node, prop, default=None, typespec=None):
137 """Get a property from a device tree.
138
139 This looks up the given node and property, and returns the value as a
140 string,
141
142 If the node or property does not exist, this will return the default
143 value.
144
145 Args:
146 node: Full path to node to look up.
147 prop: Property name to look up.
148 default: Default value to return if nothing is present in the fdt,
149 or None to raise in this case. This will be converted to a
150 string.
151 typespec: Type character to use (None for default, 's' for string)
152
153 Returns:
154 string containing the property value.
155
156 Raises:
157 CmdError: if the property does not exist and no default is provided.
158 """
Simon Glassa06a34b2016-07-25 18:59:04 -0600159 args = [self._fname, node, prop, '-t', 'bx']
Simon Glassec564b42016-07-04 11:58:08 -0600160 if default is not None:
161 args += ['-d', str(default)]
162 if typespec is not None:
163 args += ['-t%s' % typespec]
164 out = command.Output('fdtget', *args)
165 return out.strip()
Simon Glassa06a34b2016-07-25 18:59:04 -0600166
167 @classmethod
168 def Node(self, fdt, offset, name, path):
169 """Create a new node
170
171 This is used by Fdt.Scan() to create a new node using the correct
172 class.
173
174 Args:
175 fdt: Fdt object
176 offset: Offset of node
177 name: Node name
178 path: Full path to node
179 """
180 node = Node(fdt, offset, name, path)
181 return node