Merge branch 'master' of git://git.denx.de/u-boot-usb
[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     args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
72     args += ['-Ulinux']
73     for path in search_paths:
74         args.extend(['-I', path])
75     args += ['-o', dts_input, fname]
76     command.Run('cc', *args)
77
78     # If we don't have a directory, put it in the tools tempdir
79     search_list = []
80     for path in search_paths:
81         search_list.extend(['-i', path])
82     args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
83             '-W', 'no-unit_address_vs_reg']
84     args.extend(search_list)
85     args.append(dts_input)
86     dtc = os.environ.get('DTC') or 'dtc'
87     command.Run(dtc, *args, capture_stderr=capture_stderr)
88     return dtb_output
89
90 def GetInt(node, propname, default=None):
91     """Get an integer from a property
92
93     Args:
94         node: Node object to read from
95         propname: property name to read
96         default: Default value to use if the node/property do not exist
97
98     Returns:
99         Integer value read, or default if none
100     """
101     prop = node.props.get(propname)
102     if not prop:
103         return default
104     if isinstance(prop.value, list):
105         raise ValueError("Node '%s' property '%s' has list value: expecting "
106                          "a single integer" % (node.name, propname))
107     value = fdt32_to_cpu(prop.value)
108     return value
109
110 def GetString(node, propname, default=None):
111     """Get a string from a property
112
113     Args:
114         node: Node object to read from
115         propname: property name to read
116         default: Default value to use if the node/property do not exist
117
118     Returns:
119         String value read, or default if none
120     """
121     prop = node.props.get(propname)
122     if not prop:
123         return default
124     value = prop.value
125     if isinstance(value, list):
126         raise ValueError("Node '%s' property '%s' has list value: expecting "
127                          "a single string" % (node.name, propname))
128     return value
129
130 def GetBool(node, propname, default=False):
131     """Get an boolean from a property
132
133     Args:
134         node: Node object to read from
135         propname: property name to read
136         default: Default value to use if the node/property do not exist
137
138     Returns:
139         Boolean value read, or default if none (if you set this to True the
140             function will always return True)
141     """
142     if propname in node.props:
143         return True
144     return default
145
146 def GetByte(node, propname, default=None):
147     """Get an byte 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         Byte value read, or default if none
156     """
157     prop = node.props.get(propname)
158     if not prop:
159         return default
160     value = prop.value
161     if isinstance(value, list):
162         raise ValueError("Node '%s' property '%s' has list value: expecting "
163                          "a single byte" % (node.name, propname))
164     if len(value) != 1:
165         raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
166                          (node.name, propname, len(value), 1))
167     return ord(value[0])
168
169 def GetPhandleList(node, propname):
170     """Get a list of phandles from a property
171
172     Args:
173         node: Node object to read from
174         propname: property name to read
175
176     Returns:
177         List of phandles read, each an integer
178     """
179     prop = node.props.get(propname)
180     if not prop:
181         return None
182     value = prop.value
183     if not isinstance(value, list):
184         value = [value]
185     return [fdt32_to_cpu(v) for v in value]
186
187 def GetDatatype(node, propname, datatype):
188     """Get a value of a given type from a property
189
190     Args:
191         node: Node object to read from
192         propname: property name to read
193         datatype: Type to read (str or int)
194
195     Returns:
196         value read, or None if none
197
198     Raises:
199         ValueError if datatype is not str or int
200     """
201     if datatype == str:
202         return GetString(node, propname)
203     elif datatype == int:
204         return GetInt(node, propname)
205     raise ValueError("fdt_util internal error: Unknown data type '%s'" %
206                      datatype)