]>
Commit | Line | Data |
---|---|---|
ec564b47 SG |
1 | #!/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 | ||
9 | import command | |
a06a34b2 SG |
10 | import fdt |
11 | from fdt import Fdt, NodeBase, PropBase | |
ec564b47 SG |
12 | import fdt_util |
13 | import 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 | ||
a06a34b2 | 22 | class Prop(PropBase): |
ec564b47 SG |
23 | """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 | """ | |
a06a34b2 SG |
31 | def __init__(self, node, name, byte_list_str): |
32 | PropBase.__init__(self, node, 0, name) | |
ec564b47 | 33 | if not byte_list_str.strip(): |
bc1dea36 | 34 | self.type = fdt.TYPE_BOOL |
ec564b47 | 35 | return |
a06a34b2 SG |
36 | self.bytes = [chr(int(byte, 16)) |
37 | for byte in byte_list_str.strip().split(' ')] | |
bc1dea36 | 38 | self.type, self.value = self.BytesToValue(''.join(self.bytes)) |
ec564b47 | 39 | |
d6a33918 | 40 | |
a06a34b2 | 41 | class Node(NodeBase): |
ec564b47 SG |
42 | """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 | """ | |
a06a34b2 SG |
52 | def __init__(self, fdt, offset, name, path): |
53 | NodeBase.__init__(self, fdt, offset, name, path) | |
ec564b47 SG |
54 | |
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(): | |
a06a34b2 | 62 | prop = Prop(self, name, byte_list_str) |
ec564b47 SG |
63 | 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 | |
a06a34b2 | 68 | node = Node(self._fdt, 0, name, path) |
ec564b47 SG |
69 | self.subnodes.append(node) |
70 | ||
71 | node.Scan() | |
72 | ||
73 | ||
a06a34b2 SG |
74 | class FdtFallback(Fdt): |
75 | """Provides simple access to a flat device tree blob using fdtget/fdtput | |
ec564b47 SG |
76 | |
77 | Properties: | |
a06a34b2 | 78 | See superclass |
ec564b47 SG |
79 | """ |
80 | ||
81 | def __init__(self, fname): | |
a06a34b2 | 82 | Fdt.__init__(self, fname) |
355c67c3 SG |
83 | if self._fname: |
84 | self._fname = fdt_util.EnsureCompiled(self._fname) | |
ec564b47 | 85 | |
ec564b47 SG |
86 | def GetSubNodes(self, node): |
87 | """Returns a list of sub-nodes of a given node | |
88 | ||
89 | Args: | |
90 | node: Node name to return children from | |
91 | ||
92 | Returns: | |
93 | List of children in the node (each a string node name) | |
94 | ||
95 | Raises: | |
96 | CmdError: if the node does not exist. | |
97 | """ | |
a06a34b2 | 98 | out = command.Output('fdtget', self._fname, '-l', node) |
ec564b47 SG |
99 | return out.strip().splitlines() |
100 | ||
6b93c55f | 101 | def GetProps(self, node): |
ec564b47 SG |
102 | """Get all properties from a node |
103 | ||
104 | Args: | |
105 | node: full path to node name to look in | |
ec564b47 SG |
106 | |
107 | Returns: | |
108 | A dictionary containing all the properties, indexed by node name. | |
109 | The entries are simply strings - no decoding of lists or numbers | |
110 | is done. | |
111 | ||
112 | Raises: | |
113 | CmdError: if the node does not exist. | |
114 | """ | |
a06a34b2 | 115 | out = command.Output('fdtget', self._fname, node, '-p') |
ec564b47 SG |
116 | props = out.strip().splitlines() |
117 | props_dict = {} | |
118 | for prop in props: | |
119 | name = prop | |
ec564b47 SG |
120 | props_dict[prop] = self.GetProp(node, name) |
121 | return props_dict | |
122 | ||
123 | def GetProp(self, node, prop, default=None, typespec=None): | |
124 | """Get a property from a device tree. | |
125 | ||
126 | This looks up the given node and property, and returns the value as a | |
127 | string, | |
128 | ||
129 | If the node or property does not exist, this will return the default | |
130 | value. | |
131 | ||
132 | Args: | |
133 | node: Full path to node to look up. | |
134 | prop: Property name to look up. | |
135 | default: Default value to return if nothing is present in the fdt, | |
136 | or None to raise in this case. This will be converted to a | |
137 | string. | |
138 | typespec: Type character to use (None for default, 's' for string) | |
139 | ||
140 | Returns: | |
141 | string containing the property value. | |
142 | ||
143 | Raises: | |
144 | CmdError: if the property does not exist and no default is provided. | |
145 | """ | |
a06a34b2 | 146 | args = [self._fname, node, prop, '-t', 'bx'] |
ec564b47 SG |
147 | if default is not None: |
148 | args += ['-d', str(default)] | |
149 | if typespec is not None: | |
150 | args += ['-t%s' % typespec] | |
151 | out = command.Output('fdtget', *args) | |
152 | return out.strip() | |
a06a34b2 SG |
153 | |
154 | @classmethod | |
155 | def Node(self, fdt, offset, name, path): | |
156 | """Create a new node | |
157 | ||
158 | This is used by Fdt.Scan() to create a new node using the correct | |
159 | class. | |
160 | ||
161 | Args: | |
162 | fdt: Fdt object | |
163 | offset: Offset of node | |
164 | name: Node name | |
165 | path: Full path to node | |
166 | """ | |
167 | node = Node(fdt, offset, name, path) | |
168 | return node |