#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
-# SPDX-License-Identifier: GPL-2.0+
-#
+
+# Utility functions for reading from a device tree. Once the upstream pylibfdt
+# implementation advances far enough, we should be able to drop these.
import os
import struct
import sys
import tempfile
-import command
-import tools
+from patman import command
+from patman import tools
def fdt32_to_cpu(val):
"""Convert a device tree cell to an integer
Return:
A native-endian integer value
"""
- if sys.version_info > (3, 0):
- if isinstance(val, bytes):
- val = val.decode('utf-8')
- val = val.encode('raw_unicode_escape')
return struct.unpack('>I', val)[0]
-def EnsureCompiled(fname):
+def fdt64_to_cpu(val):
+ """Convert a device tree cell to an integer
+
+ Args:
+ val (list): Value to convert (list of 2 4-character strings representing
+ the cell value)
+
+ Return:
+ int: A native-endian integer value
+ """
+ return fdt32_to_cpu(val[0]) << 32 | fdt32_to_cpu(val[1])
+
+def fdt_cells_to_cpu(val, cells):
+ """Convert one or two cells to a long integer
+
+ Args:
+ Value to convert (array of one or more 4-character strings)
+
+ Return:
+ A native-endian integer value
+ """
+ if not cells:
+ return 0
+ out = int(fdt32_to_cpu(val[0]))
+ if cells == 2:
+ out = out << 32 | fdt32_to_cpu(val[1])
+ return out
+
+def EnsureCompiled(fname, tmpdir=None, capture_stderr=False):
"""Compile an fdt .dts source file into a .dtb binary blob if needed.
Args:
fname: Filename (if .dts it will be compiled). It not it will be
left alone
+ tmpdir: Temporary directory for output files, or None to use the
+ tools-module output directory
Returns:
Filename of resulting .dtb file
if ext != '.dts':
return fname
- dts_input = tools.GetOutputFilename('source.dts')
- dtb_output = tools.GetOutputFilename('source.dtb')
+ if tmpdir:
+ dts_input = os.path.join(tmpdir, 'source.dts')
+ dtb_output = os.path.join(tmpdir, 'source.dtb')
+ else:
+ dts_input = tools.get_output_filename('source.dts')
+ dtb_output = tools.get_output_filename('source.dtb')
search_paths = [os.path.join(os.getcwd(), 'include')]
root, _ = os.path.splitext(fname)
- args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
+ cc, args = tools.get_target_compile_tool('cc')
+ args += ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
args += ['-Ulinux']
for path in search_paths:
args.extend(['-I', path])
args += ['-o', dts_input, fname]
- command.Run('cc', *args)
+ command.Run(cc, *args)
# If we don't have a directory, put it in the tools tempdir
search_list = []
for path in search_paths:
search_list.extend(['-i', path])
- args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb']
+ dtc, args = tools.get_target_compile_tool('dtc')
+ args += ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
+ '-W', 'no-unit_address_vs_reg']
args.extend(search_list)
args.append(dts_input)
- command.Run('dtc', *args)
+ command.Run(dtc, *args, capture_stderr=capture_stderr)
return dtb_output
def GetInt(node, propname, default=None):
+ """Get an integer from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ Integer value read, or default if none
+ """
prop = node.props.get(propname)
if not prop:
return default
- value = fdt32_to_cpu(prop.value)
- if type(value) == type(list):
- raise ValueError("Node '%s' property '%' has list value: expecting"
+ if isinstance(prop.value, list):
+ raise ValueError("Node '%s' property '%s' has list value: expecting "
"a single integer" % (node.name, propname))
+ value = fdt32_to_cpu(prop.value)
+ return value
+
+def GetInt64(node, propname, default=None):
+ """Get a 64-bit integer from a property
+
+ Args:
+ node (Node): Node object to read from
+ propname (str): property name to read
+ default (int): Default value to use if the node/property do not exist
+
+ Returns:
+ int: value read, or default if none
+
+ Raises:
+ ValueError: Property is not of the correct size
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return default
+ if not isinstance(prop.value, list) or len(prop.value) != 2:
+ raise ValueError("Node '%s' property '%s' should be a list with 2 items for 64-bit values" %
+ (node.name, propname))
+ value = fdt64_to_cpu(prop.value)
return value
def GetString(node, propname, default=None):
+ """Get a string from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ String value read, or default if none
+ """
prop = node.props.get(propname)
if not prop:
return default
value = prop.value
- if type(value) == type(list):
- raise ValueError("Node '%s' property '%' has list value: expecting"
+ if isinstance(value, list):
+ raise ValueError("Node '%s' property '%s' has list value: expecting "
"a single string" % (node.name, propname))
return value
+def GetStringList(node, propname, default=None):
+ """Get a string list from a property
+
+ Args:
+ node (Node): Node object to read from
+ propname (str): property name to read
+ default (list of str): Default value to use if the node/property do not
+ exist, or None
+
+ Returns:
+ String value read, or default if none
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return default
+ value = prop.value
+ if not isinstance(value, list):
+ strval = GetString(node, propname)
+ return [strval]
+ return value
+
def GetBool(node, propname, default=False):
+ """Get an boolean from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ Boolean value read, or default if none (if you set this to True the
+ function will always return True)
+ """
if propname in node.props:
return True
return default
+
+def GetByte(node, propname, default=None):
+ """Get an byte from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ Byte value read, or default if none
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return default
+ value = prop.value
+ if isinstance(value, list):
+ raise ValueError("Node '%s' property '%s' has list value: expecting "
+ "a single byte" % (node.name, propname))
+ if len(value) != 1:
+ raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
+ (node.name, propname, len(value), 1))
+ return ord(value[0])
+
+def GetBytes(node, propname, size, default=None):
+ """Get a set of bytes from a property
+
+ Args:
+ node (Node): Node object to read from
+ propname (str): property name to read
+ size (int): Number of bytes to expect
+ default (bytes): Default value or None
+
+ Returns:
+ bytes: Bytes value read, or default if none
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return default
+ if len(prop.bytes) != size:
+ raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
+ (node.name, propname, len(prop.bytes), size))
+ return prop.bytes
+
+def GetPhandleList(node, propname):
+ """Get a list of phandles from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+
+ Returns:
+ List of phandles read, each an integer
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return None
+ value = prop.value
+ if not isinstance(value, list):
+ value = [value]
+ return [fdt32_to_cpu(v) for v in value]
+
+def GetDatatype(node, propname, datatype):
+ """Get a value of a given type from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ datatype: Type to read (str or int)
+
+ Returns:
+ value read, or None if none
+
+ Raises:
+ ValueError if datatype is not str or int
+ """
+ if datatype == str:
+ return GetString(node, propname)
+ elif datatype == int:
+ return GetInt(node, propname)
+ raise ValueError("fdt_util internal error: Unknown data type '%s'" %
+ datatype)