blob: 19eb13aef335bd03864e0d71d0e9205135a09eae [file] [log] [blame]
Simon Glassec564b42016-07-04 11:58:08 -06001#!/usr/bin/python
Tom Rini83d290c2018-05-06 17:58:06 -04002# SPDX-License-Identifier: GPL-2.0+
Simon Glassec564b42016-07-04 11:58:08 -06003#
4# Copyright (C) 2016 Google, Inc
5# Written by Simon Glass <sjg@chromium.org>
6#
Simon Glassec564b42016-07-04 11:58:08 -06007
Simon Glassdc08ecc2018-07-17 13:25:31 -06008# Utility functions for reading from a device tree. Once the upstream pylibfdt
9# implementation advances far enough, we should be able to drop these.
10
Simon Glass355c67c2016-07-25 18:59:10 -060011import os
Simon Glassec564b42016-07-04 11:58:08 -060012import struct
Paul Burtonc4c5f9e2016-09-27 16:03:57 +010013import sys
Simon Glass355c67c2016-07-25 18:59:10 -060014import tempfile
15
Simon Glassbf776672020-04-17 18:09:04 -060016from patman import command
17from patman import tools
Simon Glassec564b42016-07-04 11:58:08 -060018
Simon Glassec564b42016-07-04 11:58:08 -060019def fdt32_to_cpu(val):
20 """Convert a device tree cell to an integer
21
22 Args:
23 Value to convert (4-character string representing the cell value)
24
25 Return:
26 A native-endian integer value
27 """
Simon Glass20024da2016-07-25 18:59:17 -060028 return struct.unpack('>I', val)[0]
Simon Glass355c67c2016-07-25 18:59:10 -060029
Simon Glassd866e622021-11-23 11:03:39 -070030def fdt64_to_cpu(val):
31 """Convert a device tree cell to an integer
32
33 Args:
34 val (list): Value to convert (list of 2 4-character strings representing
35 the cell value)
36
37 Return:
38 int: A native-endian integer value
39 """
40 return fdt32_to_cpu(val[0]) << 32 | fdt32_to_cpu(val[1])
41
Simon Glassfbdfd222017-08-29 14:15:48 -060042def fdt_cells_to_cpu(val, cells):
43 """Convert one or two cells to a long integer
44
45 Args:
46 Value to convert (array of one or more 4-character strings)
47
48 Return:
Simon Glass209a5592019-05-17 22:00:42 -060049 A native-endian integer value
Simon Glassfbdfd222017-08-29 14:15:48 -060050 """
Simon Glassc20ee0e2017-08-29 14:15:50 -060051 if not cells:
52 return 0
Simon Glass209a5592019-05-17 22:00:42 -060053 out = int(fdt32_to_cpu(val[0]))
Simon Glassfbdfd222017-08-29 14:15:48 -060054 if cells == 2:
55 out = out << 32 | fdt32_to_cpu(val[1])
56 return out
57
Simon Glassa004f292019-07-20 12:23:49 -060058def EnsureCompiled(fname, tmpdir=None, capture_stderr=False):
Simon Glass355c67c2016-07-25 18:59:10 -060059 """Compile an fdt .dts source file into a .dtb binary blob if needed.
60
61 Args:
62 fname: Filename (if .dts it will be compiled). It not it will be
63 left alone
Simon Glassa004f292019-07-20 12:23:49 -060064 tmpdir: Temporary directory for output files, or None to use the
65 tools-module output directory
Simon Glass355c67c2016-07-25 18:59:10 -060066
67 Returns:
68 Filename of resulting .dtb file
69 """
70 _, ext = os.path.splitext(fname)
71 if ext != '.dts':
72 return fname
73
Simon Glassa004f292019-07-20 12:23:49 -060074 if tmpdir:
75 dts_input = os.path.join(tmpdir, 'source.dts')
76 dtb_output = os.path.join(tmpdir, 'source.dtb')
77 else:
78 dts_input = tools.GetOutputFilename('source.dts')
79 dtb_output = tools.GetOutputFilename('source.dtb')
Simon Glass355c67c2016-07-25 18:59:10 -060080
81 search_paths = [os.path.join(os.getcwd(), 'include')]
82 root, _ = os.path.splitext(fname)
Alper Nebi Yasak1e4687a2020-09-06 14:46:05 +030083 cc, args = tools.GetTargetCompileTool('cc')
84 args += ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
Simon Glass355c67c2016-07-25 18:59:10 -060085 args += ['-Ulinux']
86 for path in search_paths:
87 args.extend(['-I', path])
88 args += ['-o', dts_input, fname]
Alper Nebi Yasak1e4687a2020-09-06 14:46:05 +030089 command.Run(cc, *args)
Simon Glass355c67c2016-07-25 18:59:10 -060090
91 # If we don't have a directory, put it in the tools tempdir
92 search_list = []
93 for path in search_paths:
94 search_list.extend(['-i', path])
Alper Nebi Yasak1e4687a2020-09-06 14:46:05 +030095 dtc, args = tools.GetTargetCompileTool('dtc')
96 args += ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
Simon Glassd09682e2017-11-12 21:52:09 -070097 '-W', 'no-unit_address_vs_reg']
Simon Glass355c67c2016-07-25 18:59:10 -060098 args.extend(search_list)
99 args.append(dts_input)
Simon Glassfe57c782018-07-06 10:27:37 -0600100 command.Run(dtc, *args, capture_stderr=capture_stderr)
Simon Glass355c67c2016-07-25 18:59:10 -0600101 return dtb_output
Simon Glass8f224b32016-07-25 18:59:18 -0600102
103def GetInt(node, propname, default=None):
Simon Glassdc08ecc2018-07-17 13:25:31 -0600104 """Get an integer from a property
105
106 Args:
107 node: Node object to read from
108 propname: property name to read
109 default: Default value to use if the node/property do not exist
110
111 Returns:
112 Integer value read, or default if none
113 """
Simon Glass8f224b32016-07-25 18:59:18 -0600114 prop = node.props.get(propname)
115 if not prop:
116 return default
Simon Glass2a2d91d2018-07-06 10:27:28 -0600117 if isinstance(prop.value, list):
118 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass8f224b32016-07-25 18:59:18 -0600119 "a single integer" % (node.name, propname))
Simon Glass2a2d91d2018-07-06 10:27:28 -0600120 value = fdt32_to_cpu(prop.value)
Simon Glass8f224b32016-07-25 18:59:18 -0600121 return value
122
Simon Glassd866e622021-11-23 11:03:39 -0700123def GetInt64(node, propname, default=None):
124 """Get a 64-bit integer from a property
125
126 Args:
127 node (Node): Node object to read from
128 propname (str): property name to read
129 default (int): Default value to use if the node/property do not exist
130
131 Returns:
132 int: value read, or default if none
133
134 Raises:
135 ValueError: Property is not of the correct size
136 """
137 prop = node.props.get(propname)
138 if not prop:
139 return default
140 if not isinstance(prop.value, list) or len(prop.value) != 2:
141 raise ValueError("Node '%s' property '%s' should be a list with 2 items for 64-bit values" %
142 (node.name, propname))
143 value = fdt64_to_cpu(prop.value)
144 return value
145
Simon Glass8f224b32016-07-25 18:59:18 -0600146def GetString(node, propname, default=None):
Simon Glassdc08ecc2018-07-17 13:25:31 -0600147 """Get a string from a property
148
149 Args:
150 node: Node object to read from
151 propname: property name to read
152 default: Default value to use if the node/property do not exist
153
154 Returns:
155 String value read, or default if none
156 """
Simon Glass8f224b32016-07-25 18:59:18 -0600157 prop = node.props.get(propname)
158 if not prop:
159 return default
160 value = prop.value
Simon Glass2a2d91d2018-07-06 10:27:28 -0600161 if isinstance(value, list):
162 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass8f224b32016-07-25 18:59:18 -0600163 "a single string" % (node.name, propname))
164 return value
165
Simon Glass1b5a5332021-11-23 21:09:51 -0700166def GetStringList(node, propname, default=None):
167 """Get a string list from a property
168
169 Args:
170 node (Node): Node object to read from
171 propname (str): property name to read
172 default (list of str): Default value to use if the node/property do not
173 exist, or None
174
175 Returns:
176 String value read, or default if none
177 """
178 prop = node.props.get(propname)
179 if not prop:
180 return default
181 value = prop.value
182 if not isinstance(value, list):
183 strval = GetString(node, propname)
184 return [strval]
185 return value
186
Simon Glass8f224b32016-07-25 18:59:18 -0600187def GetBool(node, propname, default=False):
Simon Glassdc08ecc2018-07-17 13:25:31 -0600188 """Get an boolean from a property
189
190 Args:
191 node: Node object to read from
192 propname: property name to read
193 default: Default value to use if the node/property do not exist
194
195 Returns:
196 Boolean value read, or default if none (if you set this to True the
197 function will always return True)
198 """
Simon Glass8f224b32016-07-25 18:59:18 -0600199 if propname in node.props:
200 return True
201 return default
Simon Glass53af22a2018-07-17 13:25:32 -0600202
Simon Glass3af8e492018-07-17 13:25:40 -0600203def GetByte(node, propname, default=None):
204 """Get an byte from a property
205
206 Args:
207 node: Node object to read from
208 propname: property name to read
209 default: Default value to use if the node/property do not exist
210
211 Returns:
212 Byte value read, or default if none
213 """
214 prop = node.props.get(propname)
215 if not prop:
216 return default
217 value = prop.value
218 if isinstance(value, list):
219 raise ValueError("Node '%s' property '%s' has list value: expecting "
220 "a single byte" % (node.name, propname))
221 if len(value) != 1:
222 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
223 (node.name, propname, len(value), 1))
224 return ord(value[0])
225
Simon Glass40b4d642021-11-23 11:03:40 -0700226def GetBytes(node, propname, size, default=None):
227 """Get a set of bytes from a property
228
229 Args:
230 node (Node): Node object to read from
231 propname (str): property name to read
232 size (int): Number of bytes to expect
233 default (bytes): Default value or None
234
235 Returns:
236 bytes: Bytes value read, or default if none
237 """
238 prop = node.props.get(propname)
239 if not prop:
240 return default
241 if len(prop.bytes) != size:
242 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
243 (node.name, propname, len(prop.bytes), size))
244 return prop.bytes
245
Simon Glass94a7c602018-07-17 13:25:46 -0600246def GetPhandleList(node, propname):
247 """Get a list of phandles from a property
248
249 Args:
250 node: Node object to read from
251 propname: property name to read
252
253 Returns:
254 List of phandles read, each an integer
255 """
256 prop = node.props.get(propname)
257 if not prop:
258 return None
259 value = prop.value
260 if not isinstance(value, list):
261 value = [value]
262 return [fdt32_to_cpu(v) for v in value]
263
Simon Glass53af22a2018-07-17 13:25:32 -0600264def GetDatatype(node, propname, datatype):
265 """Get a value of a given type from a property
266
267 Args:
268 node: Node object to read from
269 propname: property name to read
270 datatype: Type to read (str or int)
271
272 Returns:
273 value read, or None if none
274
275 Raises:
276 ValueError if datatype is not str or int
277 """
278 if datatype == str:
279 return GetString(node, propname)
280 elif datatype == int:
281 return GetInt(node, propname)
282 raise ValueError("fdt_util internal error: Unknown data type '%s'" %
283 datatype)