blob: 23e26796c8fff84079870b0b5ad22dcb9c0316c5 [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 """
Paul Burton4ae65492016-09-27 16:03:56 +010061 for name, byte_list_str in self._fdt.GetProps(self.path).items():
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:
Simon Glass0734b702016-09-25 15:52:17 -0600163 args += ['-t', typespec]
Simon Glassec564b42016-07-04 11:58:08 -0600164 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