blob: 5fbfc8877bd31777d2a8b68a45b05c59c0b0fd1d [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
16import command
17import tools
Simon Glassec564b42016-07-04 11:58:08 -060018
Simon Glass2a2d91d2018-07-06 10:27:28 -060019VERSION3 = sys.version_info > (3, 0)
20
21def get_plain_bytes(val):
22 """Handle Python 3 strings"""
23 if isinstance(val, bytes):
24 val = val.decode('utf-8')
25 return val.encode('raw_unicode_escape')
26
Simon Glassec564b42016-07-04 11:58:08 -060027def fdt32_to_cpu(val):
28 """Convert a device tree cell to an integer
29
30 Args:
31 Value to convert (4-character string representing the cell value)
32
33 Return:
34 A native-endian integer value
35 """
Simon Glass2a2d91d2018-07-06 10:27:28 -060036 if VERSION3:
37 # This code is not reached in Python 2
38 val = get_plain_bytes(val) # pragma: no cover
Simon Glass20024da2016-07-25 18:59:17 -060039 return struct.unpack('>I', val)[0]
Simon Glass355c67c2016-07-25 18:59:10 -060040
Simon Glassfbdfd222017-08-29 14:15:48 -060041def fdt_cells_to_cpu(val, cells):
42 """Convert one or two cells to a long integer
43
44 Args:
45 Value to convert (array of one or more 4-character strings)
46
47 Return:
48 A native-endian long value
49 """
Simon Glassc20ee0e2017-08-29 14:15:50 -060050 if not cells:
51 return 0
Simon Glassfbdfd222017-08-29 14:15:48 -060052 out = long(fdt32_to_cpu(val[0]))
53 if cells == 2:
54 out = out << 32 | fdt32_to_cpu(val[1])
55 return out
56
Simon Glassfe57c782018-07-06 10:27:37 -060057def EnsureCompiled(fname, capture_stderr=False):
Simon Glass355c67c2016-07-25 18:59:10 -060058 """Compile an fdt .dts source file into a .dtb binary blob if needed.
59
60 Args:
61 fname: Filename (if .dts it will be compiled). It not it will be
62 left alone
63
64 Returns:
65 Filename of resulting .dtb file
66 """
67 _, ext = os.path.splitext(fname)
68 if ext != '.dts':
69 return fname
70
71 dts_input = tools.GetOutputFilename('source.dts')
72 dtb_output = tools.GetOutputFilename('source.dtb')
73
74 search_paths = [os.path.join(os.getcwd(), 'include')]
75 root, _ = os.path.splitext(fname)
76 args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
77 args += ['-Ulinux']
78 for path in search_paths:
79 args.extend(['-I', path])
80 args += ['-o', dts_input, fname]
81 command.Run('cc', *args)
82
83 # If we don't have a directory, put it in the tools tempdir
84 search_list = []
85 for path in search_paths:
86 search_list.extend(['-i', path])
Simon Glassd09682e2017-11-12 21:52:09 -070087 args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
88 '-W', 'no-unit_address_vs_reg']
Simon Glass355c67c2016-07-25 18:59:10 -060089 args.extend(search_list)
90 args.append(dts_input)
Simon Glass3ed0de32017-12-24 12:12:07 -070091 dtc = os.environ.get('DTC') or 'dtc'
Simon Glassfe57c782018-07-06 10:27:37 -060092 command.Run(dtc, *args, capture_stderr=capture_stderr)
Simon Glass355c67c2016-07-25 18:59:10 -060093 return dtb_output
Simon Glass8f224b32016-07-25 18:59:18 -060094
95def GetInt(node, propname, default=None):
Simon Glassdc08ecc2018-07-17 13:25:31 -060096 """Get an integer from a property
97
98 Args:
99 node: Node object to read from
100 propname: property name to read
101 default: Default value to use if the node/property do not exist
102
103 Returns:
104 Integer value read, or default if none
105 """
Simon Glass8f224b32016-07-25 18:59:18 -0600106 prop = node.props.get(propname)
107 if not prop:
108 return default
Simon Glass2a2d91d2018-07-06 10:27:28 -0600109 if isinstance(prop.value, list):
110 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass8f224b32016-07-25 18:59:18 -0600111 "a single integer" % (node.name, propname))
Simon Glass2a2d91d2018-07-06 10:27:28 -0600112 value = fdt32_to_cpu(prop.value)
Simon Glass8f224b32016-07-25 18:59:18 -0600113 return value
114
115def GetString(node, propname, default=None):
Simon Glassdc08ecc2018-07-17 13:25:31 -0600116 """Get a string from a property
117
118 Args:
119 node: Node object to read from
120 propname: property name to read
121 default: Default value to use if the node/property do not exist
122
123 Returns:
124 String value read, or default if none
125 """
Simon Glass8f224b32016-07-25 18:59:18 -0600126 prop = node.props.get(propname)
127 if not prop:
128 return default
129 value = prop.value
Simon Glass2a2d91d2018-07-06 10:27:28 -0600130 if isinstance(value, list):
131 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass8f224b32016-07-25 18:59:18 -0600132 "a single string" % (node.name, propname))
133 return value
134
135def GetBool(node, propname, default=False):
Simon Glassdc08ecc2018-07-17 13:25:31 -0600136 """Get an boolean from a property
137
138 Args:
139 node: Node object to read from
140 propname: property name to read
141 default: Default value to use if the node/property do not exist
142
143 Returns:
144 Boolean value read, or default if none (if you set this to True the
145 function will always return True)
146 """
Simon Glass8f224b32016-07-25 18:59:18 -0600147 if propname in node.props:
148 return True
149 return default
Simon Glass53af22a2018-07-17 13:25:32 -0600150
Simon Glass3af8e492018-07-17 13:25:40 -0600151def GetByte(node, propname, default=None):
152 """Get an byte from a property
153
154 Args:
155 node: Node object to read from
156 propname: property name to read
157 default: Default value to use if the node/property do not exist
158
159 Returns:
160 Byte value read, or default if none
161 """
162 prop = node.props.get(propname)
163 if not prop:
164 return default
165 value = prop.value
166 if isinstance(value, list):
167 raise ValueError("Node '%s' property '%s' has list value: expecting "
168 "a single byte" % (node.name, propname))
169 if len(value) != 1:
170 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
171 (node.name, propname, len(value), 1))
172 return ord(value[0])
173
Simon Glass94a7c602018-07-17 13:25:46 -0600174def GetPhandleList(node, propname):
175 """Get a list of phandles from a property
176
177 Args:
178 node: Node object to read from
179 propname: property name to read
180
181 Returns:
182 List of phandles read, each an integer
183 """
184 prop = node.props.get(propname)
185 if not prop:
186 return None
187 value = prop.value
188 if not isinstance(value, list):
189 value = [value]
190 return [fdt32_to_cpu(v) for v in value]
191
Simon Glass53af22a2018-07-17 13:25:32 -0600192def GetDatatype(node, propname, datatype):
193 """Get a value of a given type from a property
194
195 Args:
196 node: Node object to read from
197 propname: property name to read
198 datatype: Type to read (str or int)
199
200 Returns:
201 value read, or None if none
202
203 Raises:
204 ValueError if datatype is not str or int
205 """
206 if datatype == str:
207 return GetString(node, propname)
208 elif datatype == int:
209 return GetInt(node, propname)
210 raise ValueError("fdt_util internal error: Unknown data type '%s'" %
211 datatype)