blob: 5b0f2a181b7cfd786888b4fa77325602dcf29759 [file] [log] [blame]
Simon Glassfa8974d2016-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 Glass1f941b62016-07-25 18:59:04 -060010import fdt
11from fdt import Fdt, NodeBase, PropBase
Simon Glassfa8974d2016-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 Glass1f941b62016-07-25 18:59:04 -060022class Prop(PropBase):
Simon Glassfa8974d2016-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 Glass1f941b62016-07-25 18:59:04 -060031 def __init__(self, node, name, byte_list_str):
32 PropBase.__init__(self, node, 0, name)
Simon Glassfa8974d2016-07-04 11:58:08 -060033 if not byte_list_str.strip():
Simon Glassb1a5e262016-07-25 18:59:05 -060034 self.type = fdt.TYPE_BOOL
Simon Glassfa8974d2016-07-04 11:58:08 -060035 return
Simon Glass1f941b62016-07-25 18:59:04 -060036 self.bytes = [chr(int(byte, 16))
37 for byte in byte_list_str.strip().split(' ')]
Simon Glassb1a5e262016-07-25 18:59:05 -060038 self.type, self.value = self.BytesToValue(''.join(self.bytes))
Simon Glassfa8974d2016-07-04 11:58:08 -060039
Simon Glass90313a92016-07-22 09:22:49 -060040
Simon Glass1f941b62016-07-25 18:59:04 -060041class Node(NodeBase):
Simon Glassfa8974d2016-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 Glass1f941b62016-07-25 18:59:04 -060052 def __init__(self, fdt, offset, name, path):
53 NodeBase.__init__(self, fdt, offset, name, path)
Simon Glassfa8974d2016-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 Glass1f941b62016-07-25 18:59:04 -060062 prop = Prop(self, name, byte_list_str)
Simon Glassfa8974d2016-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 Glass1f941b62016-07-25 18:59:04 -060068 node = Node(self._fdt, 0, name, path)
Simon Glassfa8974d2016-07-04 11:58:08 -060069 self.subnodes.append(node)
70
71 node.Scan()
72
73
Simon Glass1f941b62016-07-25 18:59:04 -060074class FdtFallback(Fdt):
75 """Provides simple access to a flat device tree blob using fdtget/fdtput
Simon Glassfa8974d2016-07-04 11:58:08 -060076
77 Properties:
Simon Glass1f941b62016-07-25 18:59:04 -060078 See superclass
Simon Glassfa8974d2016-07-04 11:58:08 -060079 """
80
81 def __init__(self, fname):
Simon Glass1f941b62016-07-25 18:59:04 -060082 Fdt.__init__(self, fname)
Simon Glassfa8974d2016-07-04 11:58:08 -060083
Simon Glassfa8974d2016-07-04 11:58:08 -060084 def GetSubNodes(self, node):
85 """Returns a list of sub-nodes of a given node
86
87 Args:
88 node: Node name to return children from
89
90 Returns:
91 List of children in the node (each a string node name)
92
93 Raises:
94 CmdError: if the node does not exist.
95 """
Simon Glass1f941b62016-07-25 18:59:04 -060096 out = command.Output('fdtget', self._fname, '-l', node)
Simon Glassfa8974d2016-07-04 11:58:08 -060097 return out.strip().splitlines()
98
99 def GetProps(self, node, convert_dashes=False):
100 """Get all properties from a node
101
102 Args:
103 node: full path to node name to look in
104 convert_dashes: True to convert - to _ in node names
105
106 Returns:
107 A dictionary containing all the properties, indexed by node name.
108 The entries are simply strings - no decoding of lists or numbers
109 is done.
110
111 Raises:
112 CmdError: if the node does not exist.
113 """
Simon Glass1f941b62016-07-25 18:59:04 -0600114 out = command.Output('fdtget', self._fname, node, '-p')
Simon Glassfa8974d2016-07-04 11:58:08 -0600115 props = out.strip().splitlines()
116 props_dict = {}
117 for prop in props:
118 name = prop
119 if convert_dashes:
120 prop = re.sub('-', '_', prop)
121 props_dict[prop] = self.GetProp(node, name)
122 return props_dict
123
124 def GetProp(self, node, prop, default=None, typespec=None):
125 """Get a property from a device tree.
126
127 This looks up the given node and property, and returns the value as a
128 string,
129
130 If the node or property does not exist, this will return the default
131 value.
132
133 Args:
134 node: Full path to node to look up.
135 prop: Property name to look up.
136 default: Default value to return if nothing is present in the fdt,
137 or None to raise in this case. This will be converted to a
138 string.
139 typespec: Type character to use (None for default, 's' for string)
140
141 Returns:
142 string containing the property value.
143
144 Raises:
145 CmdError: if the property does not exist and no default is provided.
146 """
Simon Glass1f941b62016-07-25 18:59:04 -0600147 args = [self._fname, node, prop, '-t', 'bx']
Simon Glassfa8974d2016-07-04 11:58:08 -0600148 if default is not None:
149 args += ['-d', str(default)]
150 if typespec is not None:
151 args += ['-t%s' % typespec]
152 out = command.Output('fdtget', *args)
153 return out.strip()
Simon Glass1f941b62016-07-25 18:59:04 -0600154
155 @classmethod
156 def Node(self, fdt, offset, name, path):
157 """Create a new node
158
159 This is used by Fdt.Scan() to create a new node using the correct
160 class.
161
162 Args:
163 fdt: Fdt object
164 offset: Offset of node
165 name: Node name
166 path: Full path to node
167 """
168 node = Node(fdt, offset, name, path)
169 return node