Merge tag 'xilinx-for-v2021.01' of https://gitlab.denx.de/u-boot/custodians/u-boot...
[platform/kernel/u-boot.git] / tools / dtoc / fdt_util.py
1 #!/usr/bin/python
2 # SPDX-License-Identifier: GPL-2.0+
3 #
4 # Copyright (C) 2016 Google, Inc
5 # Written by Simon Glass <sjg@chromium.org>
6 #
7
8 # 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
11 import os
12 import struct
13 import sys
14 import tempfile
15
16 from patman import command
17 from patman import tools
18
19 def 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     """
28     return struct.unpack('>I', val)[0]
29
30 def 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:
37         A native-endian integer value
38     """
39     if not cells:
40         return 0
41     out = int(fdt32_to_cpu(val[0]))
42     if cells == 2:
43         out = out << 32 | fdt32_to_cpu(val[1])
44     return out
45
46 def EnsureCompiled(fname, tmpdir=None, capture_stderr=False):
47     """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         tmpdir: Temporary directory for output files, or None to use the
53             tools-module output directory
54
55     Returns:
56         Filename of resulting .dtb file
57     """
58     _, ext = os.path.splitext(fname)
59     if ext != '.dts':
60         return fname
61
62     if tmpdir:
63         dts_input = os.path.join(tmpdir, 'source.dts')
64         dtb_output = os.path.join(tmpdir, 'source.dtb')
65     else:
66         dts_input = tools.GetOutputFilename('source.dts')
67         dtb_output = tools.GetOutputFilename('source.dtb')
68
69     search_paths = [os.path.join(os.getcwd(), 'include')]
70     root, _ = os.path.splitext(fname)
71     cc, args = tools.GetTargetCompileTool('cc')
72     args += ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
73     args += ['-Ulinux']
74     for path in search_paths:
75         args.extend(['-I', path])
76     args += ['-o', dts_input, fname]
77     command.Run(cc, *args)
78
79     # If we don't have a directory, put it in the tools tempdir
80     search_list = []
81     for path in search_paths:
82         search_list.extend(['-i', path])
83     dtc, args = tools.GetTargetCompileTool('dtc')
84     args += ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
85             '-W', 'no-unit_address_vs_reg']
86     args.extend(search_list)
87     args.append(dts_input)
88     command.Run(dtc, *args, capture_stderr=capture_stderr)
89     return dtb_output
90
91 def GetInt(node, propname, default=None):
92     """Get an integer from a property
93
94     Args:
95         node: Node object to read from
96         propname: property name to read
97         default: Default value to use if the node/property do not exist
98
99     Returns:
100         Integer value read, or default if none
101     """
102     prop = node.props.get(propname)
103     if not prop:
104         return default
105     if isinstance(prop.value, list):
106         raise ValueError("Node '%s' property '%s' has list value: expecting "
107                          "a single integer" % (node.name, propname))
108     value = fdt32_to_cpu(prop.value)
109     return value
110
111 def GetString(node, propname, default=None):
112     """Get a string from a property
113
114     Args:
115         node: Node object to read from
116         propname: property name to read
117         default: Default value to use if the node/property do not exist
118
119     Returns:
120         String value read, or default if none
121     """
122     prop = node.props.get(propname)
123     if not prop:
124         return default
125     value = prop.value
126     if isinstance(value, list):
127         raise ValueError("Node '%s' property '%s' has list value: expecting "
128                          "a single string" % (node.name, propname))
129     return value
130
131 def GetBool(node, propname, default=False):
132     """Get an boolean from a property
133
134     Args:
135         node: Node object to read from
136         propname: property name to read
137         default: Default value to use if the node/property do not exist
138
139     Returns:
140         Boolean value read, or default if none (if you set this to True the
141             function will always return True)
142     """
143     if propname in node.props:
144         return True
145     return default
146
147 def GetByte(node, propname, default=None):
148     """Get an byte from a property
149
150     Args:
151         node: Node object to read from
152         propname: property name to read
153         default: Default value to use if the node/property do not exist
154
155     Returns:
156         Byte value read, or default if none
157     """
158     prop = node.props.get(propname)
159     if not prop:
160         return default
161     value = prop.value
162     if isinstance(value, list):
163         raise ValueError("Node '%s' property '%s' has list value: expecting "
164                          "a single byte" % (node.name, propname))
165     if len(value) != 1:
166         raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
167                          (node.name, propname, len(value), 1))
168     return ord(value[0])
169
170 def GetPhandleList(node, propname):
171     """Get a list of phandles from a property
172
173     Args:
174         node: Node object to read from
175         propname: property name to read
176
177     Returns:
178         List of phandles read, each an integer
179     """
180     prop = node.props.get(propname)
181     if not prop:
182         return None
183     value = prop.value
184     if not isinstance(value, list):
185         value = [value]
186     return [fdt32_to_cpu(v) for v in value]
187
188 def GetDatatype(node, propname, datatype):
189     """Get a value of a given type from a property
190
191     Args:
192         node: Node object to read from
193         propname: property name to read
194         datatype: Type to read (str or int)
195
196     Returns:
197         value read, or None if none
198
199     Raises:
200         ValueError if datatype is not str or int
201     """
202     if datatype == str:
203         return GetString(node, propname)
204     elif datatype == int:
205         return GetInt(node, propname)
206     raise ValueError("fdt_util internal error: Unknown data type '%s'" %
207                      datatype)