blob: 51bdbdcd3b2991d1088de4941f0b36fe4920b191 [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
166def GetBool(node, propname, default=False):
Simon Glassdc08ecc2018-07-17 13:25:31 -0600167 """Get an boolean from a property
168
169 Args:
170 node: Node object to read from
171 propname: property name to read
172 default: Default value to use if the node/property do not exist
173
174 Returns:
175 Boolean value read, or default if none (if you set this to True the
176 function will always return True)
177 """
Simon Glass8f224b32016-07-25 18:59:18 -0600178 if propname in node.props:
179 return True
180 return default
Simon Glass53af22a2018-07-17 13:25:32 -0600181
Simon Glass3af8e492018-07-17 13:25:40 -0600182def GetByte(node, propname, default=None):
183 """Get an byte from a property
184
185 Args:
186 node: Node object to read from
187 propname: property name to read
188 default: Default value to use if the node/property do not exist
189
190 Returns:
191 Byte value read, or default if none
192 """
193 prop = node.props.get(propname)
194 if not prop:
195 return default
196 value = prop.value
197 if isinstance(value, list):
198 raise ValueError("Node '%s' property '%s' has list value: expecting "
199 "a single byte" % (node.name, propname))
200 if len(value) != 1:
201 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
202 (node.name, propname, len(value), 1))
203 return ord(value[0])
204
Simon Glass40b4d642021-11-23 11:03:40 -0700205def GetBytes(node, propname, size, default=None):
206 """Get a set of bytes from a property
207
208 Args:
209 node (Node): Node object to read from
210 propname (str): property name to read
211 size (int): Number of bytes to expect
212 default (bytes): Default value or None
213
214 Returns:
215 bytes: Bytes value read, or default if none
216 """
217 prop = node.props.get(propname)
218 if not prop:
219 return default
220 if len(prop.bytes) != size:
221 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
222 (node.name, propname, len(prop.bytes), size))
223 return prop.bytes
224
Simon Glass94a7c602018-07-17 13:25:46 -0600225def GetPhandleList(node, propname):
226 """Get a list of phandles from a property
227
228 Args:
229 node: Node object to read from
230 propname: property name to read
231
232 Returns:
233 List of phandles read, each an integer
234 """
235 prop = node.props.get(propname)
236 if not prop:
237 return None
238 value = prop.value
239 if not isinstance(value, list):
240 value = [value]
241 return [fdt32_to_cpu(v) for v in value]
242
Simon Glass53af22a2018-07-17 13:25:32 -0600243def GetDatatype(node, propname, datatype):
244 """Get a value of a given type from a property
245
246 Args:
247 node: Node object to read from
248 propname: property name to read
249 datatype: Type to read (str or int)
250
251 Returns:
252 value read, or None if none
253
254 Raises:
255 ValueError if datatype is not str or int
256 """
257 if datatype == str:
258 return GetString(node, propname)
259 elif datatype == int:
260 return GetInt(node, propname)
261 raise ValueError("fdt_util internal error: Unknown data type '%s'" %
262 datatype)