blob: f47879ac00637ef39e08c5b695fa0a6d6d0fd661 [file] [log] [blame]
Simon Glassfa8974d2016-07-04 11:58:08 -06001#!/usr/bin/python
Tom Rini10e47792018-05-06 17:58:06 -04002# SPDX-License-Identifier: GPL-2.0+
Simon Glassfa8974d2016-07-04 11:58:08 -06003#
4# Copyright (C) 2016 Google, Inc
5# Written by Simon Glass <sjg@chromium.org>
6#
Simon Glassfa8974d2016-07-04 11:58:08 -06007
Simon Glassfe599c72018-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 Glassefc9bf62016-07-25 18:59:10 -060011import os
Simon Glassfa8974d2016-07-04 11:58:08 -060012import struct
Paul Burton307f1fa2016-09-27 16:03:57 +010013import sys
Simon Glassefc9bf62016-07-25 18:59:10 -060014import tempfile
15
16import command
17import tools
Simon Glassfa8974d2016-07-04 11:58:08 -060018
Simon Glassfa8974d2016-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 Glass29462c32016-07-25 18:59:17 -060028 return struct.unpack('>I', val)[0]
Simon Glassefc9bf62016-07-25 18:59:10 -060029
Simon Glassfc3ae9c2017-08-29 14:15:48 -060030def fdt_cells_to_cpu(val, cells):
31 """Convert one or two cells to a long integer
32
33 Args:
34 Value to convert (array of one or more 4-character strings)
35
36 Return:
Simon Glassc69b4502019-05-17 22:00:42 -060037 A native-endian integer value
Simon Glassfc3ae9c2017-08-29 14:15:48 -060038 """
Simon Glass1b1fe412017-08-29 14:15:50 -060039 if not cells:
40 return 0
Simon Glassc69b4502019-05-17 22:00:42 -060041 out = int(fdt32_to_cpu(val[0]))
Simon Glassfc3ae9c2017-08-29 14:15:48 -060042 if cells == 2:
43 out = out << 32 | fdt32_to_cpu(val[1])
44 return out
45
Simon Glass3bce93d2018-07-06 10:27:37 -060046def EnsureCompiled(fname, capture_stderr=False):
Simon Glassefc9bf62016-07-25 18:59:10 -060047 """Compile an fdt .dts source file into a .dtb binary blob if needed.
48
49 Args:
50 fname: Filename (if .dts it will be compiled). It not it will be
51 left alone
52
53 Returns:
54 Filename of resulting .dtb file
55 """
56 _, ext = os.path.splitext(fname)
57 if ext != '.dts':
58 return fname
59
60 dts_input = tools.GetOutputFilename('source.dts')
61 dtb_output = tools.GetOutputFilename('source.dtb')
62
63 search_paths = [os.path.join(os.getcwd(), 'include')]
64 root, _ = os.path.splitext(fname)
65 args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
66 args += ['-Ulinux']
67 for path in search_paths:
68 args.extend(['-I', path])
69 args += ['-o', dts_input, fname]
70 command.Run('cc', *args)
71
72 # If we don't have a directory, put it in the tools tempdir
73 search_list = []
74 for path in search_paths:
75 search_list.extend(['-i', path])
Simon Glassc5c7b1a2017-11-12 21:52:09 -070076 args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
77 '-W', 'no-unit_address_vs_reg']
Simon Glassefc9bf62016-07-25 18:59:10 -060078 args.extend(search_list)
79 args.append(dts_input)
Simon Glassade2ef62017-12-24 12:12:07 -070080 dtc = os.environ.get('DTC') or 'dtc'
Simon Glass3bce93d2018-07-06 10:27:37 -060081 command.Run(dtc, *args, capture_stderr=capture_stderr)
Simon Glassefc9bf62016-07-25 18:59:10 -060082 return dtb_output
Simon Glass4066b312016-07-25 18:59:18 -060083
84def GetInt(node, propname, default=None):
Simon Glassfe599c72018-07-17 13:25:31 -060085 """Get an integer from a property
86
87 Args:
88 node: Node object to read from
89 propname: property name to read
90 default: Default value to use if the node/property do not exist
91
92 Returns:
93 Integer value read, or default if none
94 """
Simon Glass4066b312016-07-25 18:59:18 -060095 prop = node.props.get(propname)
96 if not prop:
97 return default
Simon Glass9c526332018-07-06 10:27:28 -060098 if isinstance(prop.value, list):
99 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass4066b312016-07-25 18:59:18 -0600100 "a single integer" % (node.name, propname))
Simon Glass9c526332018-07-06 10:27:28 -0600101 value = fdt32_to_cpu(prop.value)
Simon Glass4066b312016-07-25 18:59:18 -0600102 return value
103
104def GetString(node, propname, default=None):
Simon Glassfe599c72018-07-17 13:25:31 -0600105 """Get a string from a property
106
107 Args:
108 node: Node object to read from
109 propname: property name to read
110 default: Default value to use if the node/property do not exist
111
112 Returns:
113 String value read, or default if none
114 """
Simon Glass4066b312016-07-25 18:59:18 -0600115 prop = node.props.get(propname)
116 if not prop:
117 return default
118 value = prop.value
Simon Glass9c526332018-07-06 10:27:28 -0600119 if isinstance(value, list):
120 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass4066b312016-07-25 18:59:18 -0600121 "a single string" % (node.name, propname))
122 return value
123
124def GetBool(node, propname, default=False):
Simon Glassfe599c72018-07-17 13:25:31 -0600125 """Get an boolean from a property
126
127 Args:
128 node: Node object to read from
129 propname: property name to read
130 default: Default value to use if the node/property do not exist
131
132 Returns:
133 Boolean value read, or default if none (if you set this to True the
134 function will always return True)
135 """
Simon Glass4066b312016-07-25 18:59:18 -0600136 if propname in node.props:
137 return True
138 return default
Simon Glass91710b32018-07-17 13:25:32 -0600139
Simon Glass53f53992018-07-17 13:25:40 -0600140def GetByte(node, propname, default=None):
141 """Get an byte from a property
142
143 Args:
144 node: Node object to read from
145 propname: property name to read
146 default: Default value to use if the node/property do not exist
147
148 Returns:
149 Byte value read, or default if none
150 """
151 prop = node.props.get(propname)
152 if not prop:
153 return default
154 value = prop.value
155 if isinstance(value, list):
156 raise ValueError("Node '%s' property '%s' has list value: expecting "
157 "a single byte" % (node.name, propname))
158 if len(value) != 1:
159 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
160 (node.name, propname, len(value), 1))
161 return ord(value[0])
162
Simon Glasse2d65282018-07-17 13:25:46 -0600163def GetPhandleList(node, propname):
164 """Get a list of phandles from a property
165
166 Args:
167 node: Node object to read from
168 propname: property name to read
169
170 Returns:
171 List of phandles read, each an integer
172 """
173 prop = node.props.get(propname)
174 if not prop:
175 return None
176 value = prop.value
177 if not isinstance(value, list):
178 value = [value]
179 return [fdt32_to_cpu(v) for v in value]
180
Simon Glass91710b32018-07-17 13:25:32 -0600181def GetDatatype(node, propname, datatype):
182 """Get a value of a given type from a property
183
184 Args:
185 node: Node object to read from
186 propname: property name to read
187 datatype: Type to read (str or int)
188
189 Returns:
190 value read, or None if none
191
192 Raises:
193 ValueError if datatype is not str or int
194 """
195 if datatype == str:
196 return GetString(node, propname)
197 elif datatype == int:
198 return GetInt(node, propname)
199 raise ValueError("fdt_util internal error: Unknown data type '%s'" %
200 datatype)