aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile3
-rw-r--r--tools/binman/elf.py6
-rw-r--r--tools/binman/etype/fmap.py2
-rw-r--r--tools/binman/fdt_test.py14
-rw-r--r--tools/binman/fmap_util.py3
-rw-r--r--tools/buildman/builderthread.py14
-rw-r--r--tools/concurrencytest/concurrencytest.py4
-rw-r--r--tools/dtoc/dtb_platdata.py643
-rw-r--r--tools/dtoc/dtoc_test_scan_drivers.cxx2
-rw-r--r--tools/dtoc/dtoc_test_simple.dts5
-rw-r--r--tools/dtoc/fdt.py58
-rwxr-xr-xtools/dtoc/main.py49
-rw-r--r--tools/dtoc/src_scan.py185
-rwxr-xr-xtools/dtoc/test_dtoc.py539
-rwxr-xr-xtools/dtoc/test_fdt.py34
-rw-r--r--tools/dtoc/test_src_scan.py107
-rw-r--r--tools/mkeficapsule.c446
-rw-r--r--tools/patman/control.py6
-rw-r--r--tools/patman/func_test.py19
-rw-r--r--tools/patman/gitutil.py9
-rwxr-xr-xtools/patman/main.py2
-rw-r--r--tools/patman/series.py4
-rw-r--r--tools/patman/settings.py12
-rw-r--r--tools/patman/test_checkpatch.py28
-rw-r--r--tools/patman/tools.py93
-rwxr-xr-xtools/zynqmp_pm_cfg_obj_convert.py2
26 files changed, 1501 insertions, 788 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 253a6b9706..14fb0ed98f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -221,6 +221,9 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
hostprogs-$(CONFIG_ASN1_COMPILER) += asn1_compiler
HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
+mkeficapsule-objs := mkeficapsule.o $(LIBFDT_OBJS)
+hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
+
# We build some files with extra pedantic flags to try to minimize things
# that won't build on some weird host compiler -- though there are lots of
# exceptions for files that aren't complaint.
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 5e566e56cb..249074a334 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -158,9 +158,9 @@ def MakeElf(elf_fname, text, data):
# Spilt the text into two parts so that we can make the entry point two
# bytes after the start of the text section
- text_bytes1 = ['\t.byte\t%#x' % tools.ToByte(byte) for byte in text[:2]]
- text_bytes2 = ['\t.byte\t%#x' % tools.ToByte(byte) for byte in text[2:]]
- data_bytes = ['\t.byte\t%#x' % tools.ToByte(byte) for byte in data]
+ text_bytes1 = ['\t.byte\t%#x' % byte for byte in text[:2]]
+ text_bytes2 = ['\t.byte\t%#x' % byte for byte in text[2:]]
+ data_bytes = ['\t.byte\t%#x' % byte for byte in data]
with open(s_file, 'w') as fd:
print('''/* Auto-generated C program to produce an ELF file for testing */
diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py
index 3e9b815d11..fe81c6f64a 100644
--- a/tools/binman/etype/fmap.py
+++ b/tools/binman/etype/fmap.py
@@ -52,7 +52,7 @@ class Entry_fmap(Entry):
if pos is not None:
pos -= entry.section.GetRootSkipAtStart()
areas.append(fmap_util.FmapArea(pos or 0, entry.size or 0,
- tools.FromUnicode(entry.name), 0))
+ entry.name, 0))
entries = self.GetImage().GetEntries()
areas = []
diff --git a/tools/binman/fdt_test.py b/tools/binman/fdt_test.py
index c491d40e9e..3e12540f62 100644
--- a/tools/binman/fdt_test.py
+++ b/tools/binman/fdt_test.py
@@ -50,37 +50,37 @@ class TestFdt(unittest.TestCase):
self.assertEquals('me.bin', val)
prop = node.props['intval']
- self.assertEquals(fdt.TYPE_INT, prop.type)
+ self.assertEquals(fdt.Type.INT, prop.type)
self.assertEquals(3, fdt_util.GetInt(node, 'intval'))
prop = node.props['intarray']
- self.assertEquals(fdt.TYPE_INT, prop.type)
+ self.assertEquals(fdt.Type.INT, prop.type)
self.assertEquals(list, type(prop.value))
self.assertEquals(2, len(prop.value))
self.assertEquals([5, 6],
[fdt_util.fdt32_to_cpu(val) for val in prop.value])
prop = node.props['byteval']
- self.assertEquals(fdt.TYPE_BYTE, prop.type)
+ self.assertEquals(fdt.Type.BYTE, prop.type)
self.assertEquals(chr(8), prop.value)
prop = node.props['bytearray']
- self.assertEquals(fdt.TYPE_BYTE, prop.type)
+ self.assertEquals(fdt.Type.BYTE, prop.type)
self.assertEquals(list, type(prop.value))
self.assertEquals(str, type(prop.value[0]))
self.assertEquals(3, len(prop.value))
self.assertEquals([chr(1), '#', '4'], prop.value)
prop = node.props['longbytearray']
- self.assertEquals(fdt.TYPE_INT, prop.type)
+ self.assertEquals(fdt.Type.INT, prop.type)
self.assertEquals(0x090a0b0c, fdt_util.GetInt(node, 'longbytearray'))
prop = node.props['stringval']
- self.assertEquals(fdt.TYPE_STRING, prop.type)
+ self.assertEquals(fdt.Type.STRING, prop.type)
self.assertEquals('message2', fdt_util.GetString(node, 'stringval'))
prop = node.props['stringarray']
- self.assertEquals(fdt.TYPE_STRING, prop.type)
+ self.assertEquals(fdt.Type.STRING, prop.type)
self.assertEquals(list, type(prop.value))
self.assertEquals(3, len(prop.value))
self.assertEquals(['another', 'multi-word', 'message'], prop.value)
diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py
index 25fe60a9cc..b03fc28fbb 100644
--- a/tools/binman/fmap_util.py
+++ b/tools/binman/fmap_util.py
@@ -111,8 +111,7 @@ def EncodeFmap(image_size, name, areas):
ConvertName(names, params)
return struct.pack(fmt, *params)
- values = FmapHeader(FMAP_SIGNATURE, 1, 0, 0, image_size,
- tools.FromUnicode(name), len(areas))
+ values = FmapHeader(FMAP_SIGNATURE, 1, 0, 0, image_size, name, len(areas))
blob = _FormatBlob(FMAP_HEADER_FORMAT, FMAP_HEADER_NAMES, values)
for area in areas:
blob += _FormatBlob(FMAP_AREA_FORMAT, FMAP_AREA_NAMES, area)
diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py
index 48fcd6cf7e..d664868582 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -13,6 +13,7 @@ from patman import command
from patman import gitutil
RETURN_CODE_RETRY = -1
+BASE_ELF_FILENAMES = ['u-boot', 'spl/u-boot-spl', 'tpl/u-boot-tpl']
def Mkdir(dirname, parents = False):
"""Make a directory if it doesn't already exist.
@@ -240,6 +241,17 @@ class BuilderThread(threading.Thread):
args.extend(self.builder.toolchains.GetMakeArguments(brd))
args.extend(self.toolchain.MakeArgs())
+ # Remove any output targets. Since we use a build directory that
+ # was previously used by another board, it may have produced an
+ # SPL image. If we don't remove it (i.e. see do_config and
+ # self.mrproper below) then it will appear to be the output of
+ # this build, even if it does not produce SPL images.
+ build_dir = self.builder.GetBuildDir(commit_upto, brd.target)
+ for elf in BASE_ELF_FILENAMES:
+ fname = os.path.join(out_dir, elf)
+ if os.path.exists(fname):
+ os.remove(fname)
+
# If we need to reconfigure, do that now
if do_config:
config_out = ''
@@ -335,7 +347,7 @@ class BuilderThread(threading.Thread):
for var in sorted(env.keys()):
print('%s="%s"' % (var, env[var]), file=fd)
lines = []
- for fname in ['u-boot', 'spl/u-boot-spl']:
+ for fname in BASE_ELF_FILENAMES:
cmd = ['%snm' % self.toolchain.cross, '--size-sort', fname]
nm_result = command.RunPipe([cmd], capture=True,
capture_stderr=True, cwd=result.out_dir,
diff --git a/tools/concurrencytest/concurrencytest.py b/tools/concurrencytest/concurrencytest.py
index 418d7eed21..5e88b94f41 100644
--- a/tools/concurrencytest/concurrencytest.py
+++ b/tools/concurrencytest/concurrencytest.py
@@ -68,7 +68,7 @@ def fork_for_tests(concurrency_num=CPU_COUNT):
pid = os.fork()
if pid == 0:
try:
- stream = os.fdopen(c2pwrite, 'wb', 1)
+ stream = os.fdopen(c2pwrite, 'wb')
os.close(c2pread)
# Leave stderr and stdout open so we can see test noise
# Close stdin so that the child goes away if it decides to
@@ -92,7 +92,7 @@ def fork_for_tests(concurrency_num=CPU_COUNT):
os._exit(0)
else:
os.close(c2pwrite)
- stream = os.fdopen(c2pread, 'rb', 1)
+ stream = os.fdopen(c2pread, 'rb')
test = ProtocolTestCase(stream)
result.append(test)
return result
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 9b27aecc14..b7abaed67a 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -9,19 +9,24 @@
This supports converting device tree data to C structures definitions and
static data.
+
+See doc/driver-model/of-plat.rst for more informaiton
"""
import collections
import copy
+from enum import IntEnum
import os
import re
import sys
from dtoc import fdt
from dtoc import fdt_util
-from patman import tools
+from dtoc import src_scan
+from dtoc.src_scan import conv_name_to_c
-# When we see these properties we ignore them - i.e. do not create a structure member
+# When we see these properties we ignore them - i.e. do not create a structure
+# member
PROP_IGNORE_LIST = [
'#address-cells',
'#gpio-cells',
@@ -35,18 +40,29 @@ PROP_IGNORE_LIST = [
'u-boot,dm-spl',
]
-# C type declarations for the tyues we support
+# C type declarations for the types we support
TYPE_NAMES = {
- fdt.TYPE_INT: 'fdt32_t',
- fdt.TYPE_BYTE: 'unsigned char',
- fdt.TYPE_STRING: 'const char *',
- fdt.TYPE_BOOL: 'bool',
- fdt.TYPE_INT64: 'fdt64_t',
+ fdt.Type.INT: 'fdt32_t',
+ fdt.Type.BYTE: 'unsigned char',
+ fdt.Type.STRING: 'const char *',
+ fdt.Type.BOOL: 'bool',
+ fdt.Type.INT64: 'fdt64_t',
}
STRUCT_PREFIX = 'dtd_'
VAL_PREFIX = 'dtv_'
+class Ftype(IntEnum):
+ SOURCE, HEADER = range(2)
+
+
+# This holds information about each type of output file dtoc can create
+# type: Type of file (Ftype)
+# fname: Filename excluding directory, e.g. 'dt-plat.c'
+# hdr_comment: Comment explaining the purpose of the file
+OutputFile = collections.namedtuple('OutputFile',
+ ['ftype', 'fname', 'method', 'hdr_comment'])
+
# This holds information about a property which includes phandles.
#
# max_args: integer: Maximum number or arguments that any phandle uses (int).
@@ -62,32 +78,15 @@ PhandleInfo = collections.namedtuple('PhandleInfo', ['max_args', 'args'])
PhandleLink = collections.namedtuple('PhandleLink', ['var_node', 'dev_name'])
-def conv_name_to_c(name):
- """Convert a device-tree name to a C identifier
-
- This uses multiple replace() calls instead of re.sub() since it is faster
- (400ms for 1m calls versus 1000ms for the 're' version).
-
- Args:
- name: Name to convert
- Return:
- String containing the C version of this name
- """
- new = name.replace('@', '_at_')
- new = new.replace('-', '_')
- new = new.replace(',', '_')
- new = new.replace('.', '_')
- return new
-
def tab_to(num_tabs, line):
"""Append tabs to a line of text to reach a tab stop.
Args:
- num_tabs: Tab stop to obtain (0 = column 0, 1 = column 8, etc.)
- line: Line of text to append to
+ num_tabs (int): Tab stop to obtain (0 = column 0, 1 = column 8, etc.)
+ line (str): Line of text to append to
Returns:
- line with the correct number of tabs appeneded. If the line already
+ str: line with the correct number of tabs appeneded. If the line already
extends past that tab stop then a single space is appended.
"""
if len(line) >= num_tabs * 8:
@@ -103,37 +102,29 @@ def get_value(ftype, value):
For booleans this return 'true'
Args:
- type: Data type (fdt_util)
- value: Data value, as a string of bytes
+ ftype (fdt.Type): Data type (fdt_util)
+ value (bytes): Data value, as a string of bytes
+
+ Returns:
+ str: String representation of the value
"""
- if ftype == fdt.TYPE_INT:
- return '%#x' % fdt_util.fdt32_to_cpu(value)
- elif ftype == fdt.TYPE_BYTE:
- return '%#x' % tools.ToByte(value[0])
- elif ftype == fdt.TYPE_STRING:
+ if ftype == fdt.Type.INT:
+ val = '%#x' % fdt_util.fdt32_to_cpu(value)
+ elif ftype == fdt.Type.BYTE:
+ char = value[0]
+ val = '%#x' % (ord(char) if isinstance(char, str) else char)
+ elif ftype == fdt.Type.STRING:
# Handle evil ACPI backslashes by adding another backslash before them.
# So "\\_SB.GPO0" in the device tree effectively stays like that in C
- return '"%s"' % value.replace('\\', '\\\\')
- elif ftype == fdt.TYPE_BOOL:
- return 'true'
- elif ftype == fdt.TYPE_INT64:
- return '%#x' % value
-
-def get_compat_name(node):
- """Get the node's list of compatible string as a C identifiers
-
- Args:
- node: Node object to check
- Return:
- List of C identifiers for all the compatible strings
- """
- compat = node.props['compatible'].value
- if not isinstance(compat, list):
- compat = [compat]
- return [conv_name_to_c(c) for c in compat]
+ val = '"%s"' % value.replace('\\', '\\\\')
+ elif ftype == fdt.Type.BOOL:
+ val = 'true'
+ else: # ftype == fdt.Type.INT64:
+ val = '%#x' % value
+ return val
-class DtbPlatdata(object):
+class DtbPlatdata():
"""Provide a means to convert device tree binary data to platform data
The output of this process is C structures which can be used in space-
@@ -141,89 +132,103 @@ class DtbPlatdata(object):
code is not affordable.
Properties:
+ _scan: Scan object, for scanning and reporting on useful information
+ from the U-Boot source code
_fdt: Fdt object, referencing the device tree
_dtb_fname: Filename of the input device tree binary file
_valid_nodes: A list of Node object with compatible strings. The list
is ordered by conv_name_to_c(node.name)
_include_disabled: true to include nodes marked status = "disabled"
_outfile: The current output file (sys.stdout or a real file)
- _warning_disabled: true to disable warnings about driver names not found
_lines: Stashed list of output lines for outputting in the future
- _drivers: List of valid driver names found in drivers/
- _driver_aliases: Dict that holds aliases for driver names
- key: Driver alias declared with
- U_BOOT_DRIVER_ALIAS(driver_alias, driver_name)
- value: Driver name declared with U_BOOT_DRIVER(driver_name)
- _drivers_additional: List of additional drivers to use during scanning
+ _dirname: Directory to hold output files, or None for none (all files
+ go to stdout)
+ _struct_data (dict): OrderedDict of dtplat structures to output
+ key (str): Node name, as a C identifier
+ value: dict containing structure fields:
+ key (str): Field name
+ value: Prop object with field information
+ _basedir (str): Base directory of source tree
"""
- def __init__(self, dtb_fname, include_disabled, warning_disabled,
- drivers_additional=[]):
+ def __init__(self, scan, dtb_fname, include_disabled):
+ self._scan = scan
self._fdt = None
self._dtb_fname = dtb_fname
self._valid_nodes = None
self._include_disabled = include_disabled
self._outfile = None
- self._warning_disabled = warning_disabled
self._lines = []
- self._drivers = []
- self._driver_aliases = {}
- self._drivers_additional = drivers_additional
+ self._dirnames = [None] * len(Ftype)
+ self._struct_data = collections.OrderedDict()
+ self._basedir = None
- def get_normalized_compat_name(self, node):
- """Get a node's normalized compat name
+ def setup_output_dirs(self, output_dirs):
+ """Set up the output directories
- Returns a valid driver name by retrieving node's list of compatible
- string as a C identifier and performing a check against _drivers
- and a lookup in driver_aliases printing a warning in case of failure.
+ This should be done before setup_output() is called
Args:
- node: Node object to check
- Return:
- Tuple:
- Driver name associated with the first compatible string
- List of C identifiers for all the other compatible strings
- (possibly empty)
- In case of no match found, the return will be the same as
- get_compat_name()
+ output_dirs (tuple of str):
+ Directory to use for C output files.
+ Use None to write files relative current directory
+ Directory to use for H output files.
+ Defaults to the C output dir
"""
- compat_list_c = get_compat_name(node)
-
- for compat_c in compat_list_c:
- if not compat_c in self._drivers:
- compat_c = self._driver_aliases.get(compat_c)
- if not compat_c:
- continue
-
- aliases_c = compat_list_c
- if compat_c in aliases_c:
- aliases_c.remove(compat_c)
- return compat_c, aliases_c
-
- if not self._warning_disabled:
- print('WARNING: the driver %s was not found in the driver list'
- % (compat_list_c[0]))
-
- return compat_list_c[0], compat_list_c[1:]
-
- def setup_output(self, fname):
+ def process_dir(ftype, dirname):
+ if dirname:
+ os.makedirs(dirname, exist_ok=True)
+ self._dirnames[ftype] = dirname
+
+ if output_dirs:
+ c_dirname = output_dirs[0]
+ h_dirname = output_dirs[1] if len(output_dirs) > 1 else c_dirname
+ process_dir(Ftype.SOURCE, c_dirname)
+ process_dir(Ftype.HEADER, h_dirname)
+
+ def setup_output(self, ftype, fname):
"""Set up the output destination
Once this is done, future calls to self.out() will output to this
- file.
+ file. The file used is as follows:
+
+ self._dirnames[ftype] is None: output to fname, or stdout if None
+ self._dirnames[ftype] is not None: output to fname in that directory
+
+ Calling this function multiple times will close the old file and open
+ the new one. If they are the same file, nothing happens and output will
+ continue to the same file.
Args:
- fname: Filename to send output to, or '-' for stdout
+ ftype (str): Type of file to create ('c' or 'h')
+ fname (str): Filename to send output to. If there is a directory in
+ self._dirnames for this file type, it will be put in that
+ directory
"""
- if fname == '-':
- self._outfile = sys.stdout
+ dirname = self._dirnames[ftype]
+ if dirname:
+ pathname = os.path.join(dirname, fname)
+ if self._outfile:
+ self._outfile.close()
+ self._outfile = open(pathname, 'w')
+ elif fname:
+ if not self._outfile:
+ self._outfile = open(fname, 'w')
else:
- self._outfile = open(fname, 'w')
+ self._outfile = sys.stdout
+
+ def finish_output(self):
+ """Finish outputing to a file
+
+ This closes the output file, if one is in use
+ """
+ if self._outfile != sys.stdout:
+ self._outfile.close()
def out(self, line):
"""Output a string to the output file
Args:
- line: String to output
+ line (str): String to output
"""
self._outfile.write(line)
@@ -231,7 +236,7 @@ class DtbPlatdata(object):
"""Buffer up a string to send later
Args:
- line: String to add to our 'buffer' list
+ line (str): String to add to our 'buffer' list
"""
self._lines.append(line)
@@ -239,21 +244,26 @@ class DtbPlatdata(object):
"""Get the contents of the output buffer, and clear it
Returns:
- The output buffer, which is then cleared for future use
+ list(str): The output buffer, which is then cleared for future use
"""
lines = self._lines
self._lines = []
return lines
- def out_header(self):
- """Output a message indicating that this is an auto-generated file"""
+ def out_header(self, outfile):
+ """Output a message indicating that this is an auto-generated file
+
+ Args:
+ outfile: OutputFile describing the file being generated
+ """
self.out('''/*
* DO NOT MODIFY
*
- * This file was generated by dtoc from a .dtb (device tree binary) file.
+ * %s.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
*/
-''')
+''' % outfile.hdr_comment)
def get_phandle_argc(self, prop, node_name):
"""Check if a node contains phandles
@@ -262,9 +272,14 @@ class DtbPlatdata(object):
or not. As an interim measure, use a list of known property names.
Args:
- prop: Prop object to check
- Return:
- Number of argument cells is this is a phandle, else None
+ prop (fdt.Prop): Prop object to check
+ node_name (str): Node name, only used for raising an error
+ Returns:
+ int or None: Number of argument cells is this is a phandle,
+ else None
+ Raises:
+ ValueError: if the phandle cannot be parsed or the required property
+ is not present
"""
if prop.name in ['clocks', 'cd-gpios']:
if not isinstance(prop.value, list):
@@ -293,7 +308,7 @@ class DtbPlatdata(object):
break
if not cells:
raise ValueError("Node '%s' has no cells property" %
- (target.name))
+ (target.name))
num_args = fdt_util.fdt32_to_cpu(cells.value)
max_args = max(max_args, num_args)
args.append(num_args)
@@ -301,62 +316,6 @@ class DtbPlatdata(object):
return PhandleInfo(max_args, args)
return None
- def scan_driver(self, fn):
- """Scan a driver file to build a list of driver names and aliases
-
- This procedure will populate self._drivers and self._driver_aliases
-
- Args
- fn: Driver filename to scan
- """
- with open(fn, encoding='utf-8') as fd:
- try:
- buff = fd.read()
- except UnicodeDecodeError:
- # This seems to happen on older Python versions
- print("Skipping file '%s' due to unicode error" % fn)
- return
-
- # The following re will search for driver names declared as
- # U_BOOT_DRIVER(driver_name)
- drivers = re.findall('U_BOOT_DRIVER\((.*)\)', buff)
-
- for driver in drivers:
- self._drivers.append(driver)
-
- # The following re will search for driver aliases declared as
- # U_BOOT_DRIVER_ALIAS(alias, driver_name)
- driver_aliases = re.findall('U_BOOT_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)',
- buff)
-
- for alias in driver_aliases: # pragma: no cover
- if len(alias) != 2:
- continue
- self._driver_aliases[alias[1]] = alias[0]
-
- def scan_drivers(self):
- """Scan the driver folders to build a list of driver names and aliases
-
- This procedure will populate self._drivers and self._driver_aliases
-
- """
- basedir = sys.argv[0].replace('tools/dtoc/dtoc', '')
- if basedir == '':
- basedir = './'
- for (dirpath, dirnames, filenames) in os.walk(basedir):
- for fn in filenames:
- if not fn.endswith('.c'):
- continue
- self.scan_driver(dirpath + '/' + fn)
-
- for fn in self._drivers_additional:
- if not isinstance(fn, str) or len(fn) == 0:
- continue
- if fn[0] == '/':
- self.scan_driver(fn)
- else:
- self.scan_driver(basedir + '/' + fn)
-
def scan_dtb(self):
"""Scan the device tree to obtain a tree of nodes and properties
@@ -371,8 +330,8 @@ class DtbPlatdata(object):
This adds each node to self._valid_nodes.
Args:
- root: Root node for scan
- valid_nodes: List of Node objects to add to
+ root (Node): Root node for scan
+ valid_nodes (list of Node): List of Node objects to add to
"""
for node in root.subnodes:
if 'compatible' in node.props:
@@ -403,7 +362,7 @@ class DtbPlatdata(object):
"""Get the number of cells in addresses and sizes for this node
Args:
- node: Node to check
+ node (fdt.None): Node to check
Returns:
Tuple:
@@ -411,15 +370,15 @@ class DtbPlatdata(object):
Number of size cells for this node
"""
parent = node.parent
- na, ns = 2, 2
+ num_addr, num_size = 2, 2
if parent:
- na_prop = parent.props.get('#address-cells')
- ns_prop = parent.props.get('#size-cells')
- if na_prop:
- na = fdt_util.fdt32_to_cpu(na_prop.value)
- if ns_prop:
- ns = fdt_util.fdt32_to_cpu(ns_prop.value)
- return na, ns
+ addr_prop = parent.props.get('#address-cells')
+ size_prop = parent.props.get('#size-cells')
+ if addr_prop:
+ num_addr = fdt_util.fdt32_to_cpu(addr_prop.value)
+ if size_prop:
+ num_size = fdt_util.fdt32_to_cpu(size_prop.value)
+ return num_addr, num_size
def scan_reg_sizes(self):
"""Scan for 64-bit 'reg' properties and update the values
@@ -432,30 +391,31 @@ class DtbPlatdata(object):
reg = node.props.get('reg')
if not reg:
continue
- na, ns = self.get_num_cells(node)
- total = na + ns
+ num_addr, num_size = self.get_num_cells(node)
+ total = num_addr + num_size
- if reg.type != fdt.TYPE_INT:
+ if reg.type != fdt.Type.INT:
raise ValueError("Node '%s' reg property is not an int" %
node.name)
if len(reg.value) % total:
- raise ValueError("Node '%s' reg property has %d cells "
- 'which is not a multiple of na + ns = %d + %d)' %
- (node.name, len(reg.value), na, ns))
- reg.na = na
- reg.ns = ns
- if na != 1 or ns != 1:
- reg.type = fdt.TYPE_INT64
+ raise ValueError(
+ "Node '%s' reg property has %d cells "
+ 'which is not a multiple of na + ns = %d + %d)' %
+ (node.name, len(reg.value), num_addr, num_size))
+ reg.num_addr = num_addr
+ reg.num_size = num_size
+ if num_addr != 1 or num_size != 1:
+ reg.type = fdt.Type.INT64
i = 0
new_value = []
val = reg.value
if not isinstance(val, list):
val = [val]
while i < len(val):
- addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.na)
- i += na
- size = fdt_util.fdt_cells_to_cpu(val[i:], reg.ns)
- i += ns
+ addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.num_addr)
+ i += num_addr
+ size = fdt_util.fdt_cells_to_cpu(val[i:], reg.num_size)
+ i += num_size
new_value += [addr, size]
reg.value = new_value
@@ -470,16 +430,11 @@ class DtbPlatdata(object):
Once the widest property is determined, all other properties are
updated to match that width.
- Returns:
- dict containing structures:
- key (str): Node name, as a C identifier
- value: dict containing structure fields:
- key (str): Field name
- value: Prop object with field information
+ The results are written to self._struct_data
"""
- structs = collections.OrderedDict()
+ structs = self._struct_data
for node in self._valid_nodes:
- node_name, _ = self.get_normalized_compat_name(node)
+ node_name, _ = self._scan.get_normalized_compat_name(node)
fields = {}
# Get a list of all the valid properties in this node.
@@ -501,16 +456,12 @@ class DtbPlatdata(object):
else:
structs[node_name] = fields
- upto = 0
for node in self._valid_nodes:
- node_name, _ = self.get_normalized_compat_name(node)
+ node_name, _ = self._scan.get_normalized_compat_name(node)
struct = structs[node_name]
for name, prop in node.props.items():
if name not in PROP_IGNORE_LIST and name[0] != '#':
prop.Widen(struct[name])
- upto += 1
-
- return structs
def scan_phandles(self):
"""Figure out what phandles each node uses
@@ -540,22 +491,14 @@ class DtbPlatdata(object):
pos += 1 + args
- def generate_structs(self, structs):
+ def generate_structs(self):
"""Generate struct defintions for the platform data
This writes out the body of a header file consisting of structure
definitions for node in self._valid_nodes. See the documentation in
doc/driver-model/of-plat.rst for more information.
-
- Args:
- structs: dict containing structures:
- key (str): Node name, as a C identifier
- value: dict containing structure fields:
- key (str): Field name
- value: Prop object with field information
-
"""
- self.out_header()
+ structs = self._struct_data
self.out('#include <stdbool.h>\n')
self.out('#include <linux/libfdt.h>\n')
@@ -580,154 +523,198 @@ class DtbPlatdata(object):
self.out(';\n')
self.out('};\n')
- def output_node(self, node):
- """Output the C code for a node
+ def _output_list(self, node, prop):
+ """Output the C code for a devicetree property that holds a list
Args:
- node: node to output
+ node (fdt.Node): Node to output
+ prop (fdt.Prop): Prop to output
"""
- def _output_list(node, prop):
- """Output the C code for a devicetree property that holds a list
-
- Args:
- node (fdt.Node): Node to output
- prop (fdt.Prop): Prop to output
- """
- self.buf('{')
- vals = []
- # For phandles, output a reference to the platform data
- # of the target node.
- info = self.get_phandle_argc(prop, node.name)
- if info:
- # Process the list as pairs of (phandle, id)
- pos = 0
- item = 0
- for args in info.args:
- phandle_cell = prop.value[pos]
- phandle = fdt_util.fdt32_to_cpu(phandle_cell)
- target_node = self._fdt.phandle_to_node[phandle]
- name = conv_name_to_c(target_node.name)
- arg_values = []
- for i in range(args):
- arg_values.append(
- str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i])))
- pos += 1 + args
- vals.append('\t{%d, {%s}}' % (target_node.idx,
- ', '.join(arg_values)))
- item += 1
- for val in vals:
- self.buf('\n\t\t%s,' % val)
- else:
- for val in prop.value:
- vals.append(get_value(prop.type, val))
+ self.buf('{')
+ vals = []
+ # For phandles, output a reference to the platform data
+ # of the target node.
+ info = self.get_phandle_argc(prop, node.name)
+ if info:
+ # Process the list as pairs of (phandle, id)
+ pos = 0
+ for args in info.args:
+ phandle_cell = prop.value[pos]
+ phandle = fdt_util.fdt32_to_cpu(phandle_cell)
+ target_node = self._fdt.phandle_to_node[phandle]
+ arg_values = []
+ for i in range(args):
+ arg_values.append(
+ str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i])))
+ pos += 1 + args
+ vals.append('\t{%d, {%s}}' % (target_node.idx,
+ ', '.join(arg_values)))
+ for val in vals:
+ self.buf('\n\t\t%s,' % val)
+ else:
+ for val in prop.value:
+ vals.append(get_value(prop.type, val))
- # Put 8 values per line to avoid very long lines.
- for i in range(0, len(vals), 8):
- if i:
- self.buf(',\n\t\t')
- self.buf(', '.join(vals[i:i + 8]))
- self.buf('}')
+ # Put 8 values per line to avoid very long lines.
+ for i in range(0, len(vals), 8):
+ if i:
+ self.buf(',\n\t\t')
+ self.buf(', '.join(vals[i:i + 8]))
+ self.buf('}')
- struct_name, _ = self.get_normalized_compat_name(node)
- var_name = conv_name_to_c(node.name)
- self.buf('/* Node %s index %d */\n' % (node.path, node.idx))
- self.buf('static struct %s%s %s%s = {\n' %
- (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
- for pname in sorted(node.props):
- prop = node.props[pname]
- if pname in PROP_IGNORE_LIST or pname[0] == '#':
- continue
- member_name = conv_name_to_c(prop.name)
- self.buf('\t%s= ' % tab_to(3, '.' + member_name))
+ def _declare_device(self, var_name, struct_name, node_parent):
+ """Add a device declaration to the output
- # Special handling for lists
- if isinstance(prop.value, list):
- _output_list(node, prop)
- else:
- self.buf(get_value(prop.type, prop.value))
- self.buf(',\n')
- self.buf('};\n')
+ This declares a U_BOOT_DRVINFO() for the device being processed
- # Add a device declaration
- self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
+ Args:
+ var_name (str): C name for the node
+ struct_name (str): Name for the dt struct associated with the node
+ node_parent (Node): Parent of the node (or None if none)
+ """
+ self.buf('U_BOOT_DRVINFO(%s) = {\n' % var_name)
self.buf('\t.name\t\t= "%s",\n' % struct_name)
- self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
- self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
+ self.buf('\t.plat\t= &%s%s,\n' % (VAL_PREFIX, var_name))
+ self.buf('\t.plat_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
idx = -1
- if node.parent and node.parent in self._valid_nodes:
- idx = node.parent.idx
+ if node_parent and node_parent in self._valid_nodes:
+ idx = node_parent.idx
self.buf('\t.parent_idx\t= %d,\n' % idx)
self.buf('};\n')
self.buf('\n')
+ def _output_prop(self, node, prop):
+ """Output a line containing the value of a struct member
+
+ Args:
+ node (Node): Node being output
+ prop (Prop): Prop object to output
+ """
+ if prop.name in PROP_IGNORE_LIST or prop.name[0] == '#':
+ return
+ member_name = conv_name_to_c(prop.name)
+ self.buf('\t%s= ' % tab_to(3, '.' + member_name))
+
+ # Special handling for lists
+ if isinstance(prop.value, list):
+ self._output_list(node, prop)
+ else:
+ self.buf(get_value(prop.type, prop.value))
+ self.buf(',\n')
+
+ def _output_values(self, var_name, struct_name, node):
+ """Output the definition of a device's struct values
+
+ Args:
+ var_name (str): C name for the node
+ struct_name (str): Name for the dt struct associated with the node
+ node (Node): Node being output
+ """
+ self.buf('static struct %s%s %s%s = {\n' %
+ (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
+ for pname in sorted(node.props):
+ self._output_prop(node, node.props[pname])
+ self.buf('};\n')
+
+ def output_node(self, node):
+ """Output the C code for a node
+
+ Args:
+ node (fdt.Node): node to output
+ """
+ struct_name, _ = self._scan.get_normalized_compat_name(node)
+ var_name = conv_name_to_c(node.name)
+ self.buf('/* Node %s index %d */\n' % (node.path, node.idx))
+
+ self._output_values(var_name, struct_name, node)
+ self._declare_device(var_name, struct_name, node.parent)
+
self.out(''.join(self.get_buf()))
- def generate_tables(self):
+ def generate_plat(self):
"""Generate device defintions for the platform data
This writes out C platform data initialisation data and
- U_BOOT_DEVICE() declarations for each valid node. Where a node has
+ U_BOOT_DRVINFO() declarations for each valid node. Where a node has
multiple compatible strings, a #define is used to make them equivalent.
See the documentation in doc/driver-model/of-plat.rst for more
information.
"""
- self.out_header()
- self.out('/* Allow use of U_BOOT_DEVICE() in this file */\n')
- self.out('#define DT_PLATDATA_C\n')
+ self.out('/* Allow use of U_BOOT_DRVINFO() in this file */\n')
+ self.out('#define DT_PLAT_C\n')
self.out('\n')
self.out('#include <common.h>\n')
self.out('#include <dm.h>\n')
self.out('#include <dt-structs.h>\n')
self.out('\n')
- nodes_to_output = list(self._valid_nodes)
-
- # Keep outputing nodes until there is none left
- while nodes_to_output:
- node = nodes_to_output[0]
- # Output all the node's dependencies first
- for req_node in node.phandles:
- if req_node in nodes_to_output:
- self.output_node(req_node)
- nodes_to_output.remove(req_node)
- self.output_node(node)
- nodes_to_output.remove(node)
- # Define dm_populate_phandle_data() which will add the linking between
- # nodes using DM_GET_DEVICE
- # dtv_dmc_at_xxx.clocks[0].node = DM_GET_DEVICE(clock_controller_at_xxx)
- self.buf('void dm_populate_phandle_data(void) {\n')
- self.buf('}\n')
+ for node in self._valid_nodes:
+ self.output_node(node)
self.out(''.join(self.get_buf()))
-def run_steps(args, dtb_file, include_disabled, output, warning_disabled=False,
- drivers_additional=[]):
+
+# Types of output file we understand
+# key: Command used to generate this file
+# value: OutputFile for this command
+OUTPUT_FILES = {
+ 'struct':
+ OutputFile(Ftype.HEADER, 'dt-structs-gen.h',
+ DtbPlatdata.generate_structs,
+ 'Defines the structs used to hold devicetree data'),
+ 'platdata':
+ OutputFile(Ftype.SOURCE, 'dt-plat.c', DtbPlatdata.generate_plat,
+ 'Declares the U_BOOT_DRIVER() records and platform data'),
+ }
+
+
+def run_steps(args, dtb_file, include_disabled, output, output_dirs,
+ warning_disabled=False, drivers_additional=None, basedir=None):
"""Run all the steps of the dtoc tool
Args:
- args: List of non-option arguments provided to the problem
- dtb_file: Filename of dtb file to process
- include_disabled: True to include disabled nodes
- output: Name of output file
+ args (list): List of non-option arguments provided to the problem
+ dtb_file (str): Filename of dtb file to process
+ include_disabled (bool): True to include disabled nodes
+ output (str): Name of output file (None for stdout)
+ output_dirs (tuple of str):
+ Directory to put C output files
+ Directory to put H output files
+ warning_disabled (bool): True to avoid showing warnings about missing
+ drivers
+ drivers_additional (list): List of additional drivers to use during
+ scanning
+ basedir (str): Base directory of U-Boot source code. Defaults to the
+ grandparent of this file's directory
+ Raises:
+ ValueError: if args has no command, or an unknown command
"""
if not args:
- raise ValueError('Please specify a command: struct, platdata')
+ raise ValueError('Please specify a command: struct, platdata, all')
+ if output and output_dirs and any(output_dirs):
+ raise ValueError('Must specify either output or output_dirs, not both')
- plat = DtbPlatdata(dtb_file, include_disabled, warning_disabled, drivers_additional)
- plat.scan_drivers()
+ scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional)
+ plat = DtbPlatdata(scan, dtb_file, include_disabled)
+ scan.scan_drivers()
plat.scan_dtb()
plat.scan_tree()
plat.scan_reg_sizes()
- plat.setup_output(output)
- structs = plat.scan_structs()
+ plat.setup_output_dirs(output_dirs)
+ plat.scan_structs()
plat.scan_phandles()
- for cmd in args[0].split(','):
- if cmd == 'struct':
- plat.generate_structs(structs)
- elif cmd == 'platdata':
- plat.generate_tables()
- else:
- raise ValueError("Unknown command '%s': (use: struct, platdata)" %
- cmd)
+ cmds = args[0].split(',')
+ if 'all' in cmds:
+ cmds = sorted(OUTPUT_FILES.keys())
+ for cmd in cmds:
+ outfile = OUTPUT_FILES.get(cmd)
+ if not outfile:
+ raise ValueError("Unknown command '%s': (use: %s)" %
+ (cmd, ', '.join(sorted(OUTPUT_FILES.keys()))))
+ plat.setup_output(outfile.ftype,
+ outfile.fname if output_dirs else output)
+ plat.out_header(outfile)
+ outfile.method(plat)
+ plat.finish_output()
diff --git a/tools/dtoc/dtoc_test_scan_drivers.cxx b/tools/dtoc/dtoc_test_scan_drivers.cxx
index 557c692ba2..f448767670 100644
--- a/tools/dtoc/dtoc_test_scan_drivers.cxx
+++ b/tools/dtoc/dtoc_test_scan_drivers.cxx
@@ -1 +1 @@
-U_BOOT_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias2)
+DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias2)
diff --git a/tools/dtoc/dtoc_test_simple.dts b/tools/dtoc/dtoc_test_simple.dts
index fd168cb593..1c87b89192 100644
--- a/tools/dtoc/dtoc_test_simple.dts
+++ b/tools/dtoc/dtoc_test_simple.dts
@@ -44,11 +44,6 @@
longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
};
- spl-test4 {
- u-boot,dm-pre-reloc;
- compatible = "sandbox,spl-test.2";
- };
-
i2c@0 {
compatible = "sandbox,i2c-test";
u-boot,dm-pre-reloc;
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 03b86773d5..4a78c73725 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -5,6 +5,7 @@
# Written by Simon Glass <sjg@chromium.org>
#
+from enum import IntEnum
import struct
import sys
@@ -22,7 +23,25 @@ from patman import tools
# so it is fairly efficient.
# A list of types we support
-(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, TYPE_INT64) = range(5)
+class Type(IntEnum):
+ (BYTE, INT, STRING, BOOL, INT64) = range(5)
+
+ def is_wider_than(self, other):
+ """Check if another type is 'wider' than this one
+
+ A wider type is one that holds more information than an earlier one,
+ similar to the concept of type-widening in C.
+
+ This uses a simple arithmetic comparison, since type values are in order
+ from narrowest (BYTE) to widest (INT64).
+
+ Args:
+ other: Other type to compare against
+
+ Return:
+ True if the other type is wider
+ """
+ return self.value > other.value
def CheckErr(errnum, msg):
if errnum:
@@ -41,9 +60,9 @@ def BytesToValue(data):
Type of data
Data, either a single element or a list of elements. Each element
is one of:
- TYPE_STRING: str/bytes value from the property
- TYPE_INT: a byte-swapped integer stored as a 4-byte str/bytes
- TYPE_BYTE: a byte stored as a single-byte str/bytes
+ Type.STRING: str/bytes value from the property
+ Type.INT: a byte-swapped integer stored as a 4-byte str/bytes
+ Type.BYTE: a byte stored as a single-byte str/bytes
"""
data = bytes(data)
size = len(data)
@@ -63,21 +82,21 @@ def BytesToValue(data):
is_string = False
if is_string:
if count == 1:
- return TYPE_STRING, strings[0].decode()
+ return Type.STRING, strings[0].decode()
else:
- return TYPE_STRING, [s.decode() for s in strings[:-1]]
+ return Type.STRING, [s.decode() for s in strings[:-1]]
if size % 4:
if size == 1:
- return TYPE_BYTE, tools.ToChar(data[0])
+ return Type.BYTE, chr(data[0])
else:
- return TYPE_BYTE, [tools.ToChar(ch) for ch in list(data)]
+ return Type.BYTE, [chr(ch) for ch in list(data)]
val = []
for i in range(0, size, 4):
val.append(data[i:i + 4])
if size == 4:
- return TYPE_INT, val[0]
+ return Type.INT, val[0]
else:
- return TYPE_INT, val
+ return Type.INT, val
class Prop:
@@ -97,7 +116,7 @@ class Prop:
self.bytes = bytes(data)
self.dirty = False
if not data:
- self.type = TYPE_BOOL
+ self.type = Type.BOOL
self.value = True
return
self.type, self.value = BytesToValue(bytes(data))
@@ -128,15 +147,14 @@ class Prop:
update the current property to be like the second, since it is less
specific.
"""
- if newprop.type < self.type:
- # Special handling to convert an int into bytes
- if self.type == TYPE_INT and newprop.type == TYPE_BYTE:
+ if self.type.is_wider_than(newprop.type):
+ if self.type == Type.INT and newprop.type == Type.BYTE:
if type(self.value) == list:
new_value = []
for val in self.value:
- new_value += [tools.ToChar(by) for by in val]
+ new_value += [chr(by) for by in val]
else:
- new_value = [tools.ToChar(by) for by in self.value]
+ new_value = [chr(by) for by in self.value]
self.value = new_value
self.type = newprop.type
@@ -155,11 +173,11 @@ class Prop:
Returns:
A single value of the given type
"""
- if type == TYPE_BYTE:
+ if type == Type.BYTE:
return chr(0)
- elif type == TYPE_INT:
+ elif type == Type.INT:
return struct.pack('>I', 0);
- elif type == TYPE_STRING:
+ elif type == Type.STRING:
return ''
else:
return True
@@ -184,7 +202,7 @@ class Prop:
"""
self.bytes = struct.pack('>I', val);
self.value = self.bytes
- self.type = TYPE_INT
+ self.type = Type.INT
self.dirty = True
def SetData(self, bytes):
diff --git a/tools/dtoc/main.py b/tools/dtoc/main.py
index b94d9c301f..b0ad0f3952 100755
--- a/tools/dtoc/main.py
+++ b/tools/dtoc/main.py
@@ -13,11 +13,7 @@ having to link against libfdt. By putting the data from the device tree into
C structures, normal C code can be used. This helps to reduce the size of the
compiled program.
-Dtoc produces two output files:
-
- dt-structs.h - contains struct definitions
- dt-platdata.c - contains data from the device tree using the struct
- definitions, as well as U-Boot driver definitions.
+Dtoc produces several output files - see OUTPUT_FILES in dtb_platdata.py
This tool is used in U-Boot to provide device tree data to SPL without
increasing the code size of SPL. This supports the CONFIG_SPL_OF_PLATDATA
@@ -42,37 +38,27 @@ sys.path.insert(0, os.path.join(our_path,
from dtoc import dtb_platdata
from patman import test_util
-def run_tests(args):
+def run_tests(processes, args):
"""Run all the test we have for dtoc
Args:
+ processes: Number of processes to use to run tests (None=same as #CPUs)
args: List of positional args provided to dtoc. This can hold a test
name to execute (as in 'dtoc -t test_empty_file', for example)
"""
- import test_dtoc
+ from dtoc import test_src_scan
+ from dtoc import test_dtoc
result = unittest.TestResult()
sys.argv = [sys.argv[0]]
test_name = args and args[0] or None
- for module in (test_dtoc.TestDtoc,):
- if test_name:
- try:
- suite = unittest.TestLoader().loadTestsFromName(test_name, module)
- except AttributeError:
- continue
- else:
- suite = unittest.TestLoader().loadTestsFromTestCase(module)
- suite.run(result)
-
- print(result)
- for _, err in result.errors:
- print(err)
- for _, err in result.failures:
- print(err)
- if result.errors or result.failures:
- print('dtoc tests FAILED')
- return 1
- return 0
+
+ test_util.RunTestSuites(
+ result, debug=True, verbosity=1, test_preserve_dirs=False,
+ processes=processes, test_name=test_name, toolpath=[],
+ test_class_list=[test_dtoc.TestDtoc,test_src_scan.TestSrcScan])
+
+ return test_util.ReportResult('binman', test_name, result)
def RunTestCoverage():
"""Run the tests and check that we get 100% coverage"""
@@ -87,11 +73,15 @@ if __name__ != '__main__':
parser = OptionParser()
parser.add_option('-B', '--build-dir', type='string', default='b',
help='Directory containing the build output')
+parser.add_option('-c', '--c-output-dir', action='store',
+ help='Select output directory for C files')
+parser.add_option('-C', '--h-output-dir', action='store',
+ help='Select output directory for H files (defaults to --c-output-di)')
parser.add_option('-d', '--dtb-file', action='store',
help='Specify the .dtb input file')
parser.add_option('--include-disabled', action='store_true',
help='Include disabled nodes')
-parser.add_option('-o', '--output', action='store', default='-',
+parser.add_option('-o', '--output', action='store',
help='Select output filename')
parser.add_option('-P', '--processes', type=int,
help='set number of processes to use for running tests')
@@ -103,7 +93,7 @@ parser.add_option('-T', '--test-coverage', action='store_true',
# Run our meagre tests
if options.test:
- ret_code = run_tests(args)
+ ret_code = run_tests(options.processes, args)
sys.exit(ret_code)
elif options.test_coverage:
@@ -111,4 +101,5 @@ elif options.test_coverage:
else:
dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled,
- options.output)
+ options.output,
+ [options.c_output_dir, options.h_output_dir])
diff --git a/tools/dtoc/src_scan.py b/tools/dtoc/src_scan.py
new file mode 100644
index 0000000000..f63c9fc166
--- /dev/null
+++ b/tools/dtoc/src_scan.py
@@ -0,0 +1,185 @@
+#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2017 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+"""Scanning of U-Boot source for drivers and structs
+
+This scans the source tree to find out things about all instances of
+U_BOOT_DRIVER(), UCLASS_DRIVER and all struct declarations in header files.
+
+See doc/driver-model/of-plat.rst for more informaiton
+"""
+
+import os
+import re
+import sys
+
+
+def conv_name_to_c(name):
+ """Convert a device-tree name to a C identifier
+
+ This uses multiple replace() calls instead of re.sub() since it is faster
+ (400ms for 1m calls versus 1000ms for the 're' version).
+
+ Args:
+ name (str): Name to convert
+ Return:
+ str: String containing the C version of this name
+ """
+ new = name.replace('@', '_at_')
+ new = new.replace('-', '_')
+ new = new.replace(',', '_')
+ new = new.replace('.', '_')
+ return new
+
+def get_compat_name(node):
+ """Get the node's list of compatible string as a C identifiers
+
+ Args:
+ node (fdt.Node): Node object to check
+ Return:
+ list of str: List of C identifiers for all the compatible strings
+ """
+ compat = node.props['compatible'].value
+ if not isinstance(compat, list):
+ compat = [compat]
+ return [conv_name_to_c(c) for c in compat]
+
+
+class Driver:
+ """Information about a driver in U-Boot
+
+ Attributes:
+ name: Name of driver. For U_BOOT_DRIVER(x) this is 'x'
+ """
+ def __init__(self, name):
+ self.name = name
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def __repr__(self):
+ return "Driver(name='%s')" % self.name
+
+
+class Scanner:
+ """Scanning of the U-Boot source tree
+
+ Properties:
+ _basedir (str): Base directory of U-Boot source code. Defaults to the
+ grandparent of this file's directory
+ _drivers: Dict of valid driver names found in drivers/
+ key: Driver name
+ value: Driver for that driver
+ _driver_aliases: Dict that holds aliases for driver names
+ key: Driver alias declared with
+ DM_DRIVER_ALIAS(driver_alias, driver_name)
+ value: Driver name declared with U_BOOT_DRIVER(driver_name)
+ _warning_disabled: true to disable warnings about driver names not found
+ _drivers_additional (list or str): List of additional drivers to use
+ during scanning
+ """
+ def __init__(self, basedir, warning_disabled, drivers_additional):
+ """Set up a new Scanner
+ """
+ if not basedir:
+ basedir = sys.argv[0].replace('tools/dtoc/dtoc', '')
+ if basedir == '':
+ basedir = './'
+ self._basedir = basedir
+ self._drivers = {}
+ self._driver_aliases = {}
+ self._drivers_additional = drivers_additional or []
+ self._warning_disabled = warning_disabled
+
+ def get_normalized_compat_name(self, node):
+ """Get a node's normalized compat name
+
+ Returns a valid driver name by retrieving node's list of compatible
+ string as a C identifier and performing a check against _drivers
+ and a lookup in driver_aliases printing a warning in case of failure.
+
+ Args:
+ node (Node): Node object to check
+ Return:
+ Tuple:
+ Driver name associated with the first compatible string
+ List of C identifiers for all the other compatible strings
+ (possibly empty)
+ In case of no match found, the return will be the same as
+ get_compat_name()
+ """
+ compat_list_c = get_compat_name(node)
+
+ for compat_c in compat_list_c:
+ if not compat_c in self._drivers.keys():
+ compat_c = self._driver_aliases.get(compat_c)
+ if not compat_c:
+ continue
+
+ aliases_c = compat_list_c
+ if compat_c in aliases_c:
+ aliases_c.remove(compat_c)
+ return compat_c, aliases_c
+
+ if not self._warning_disabled:
+ print('WARNING: the driver %s was not found in the driver list'
+ % (compat_list_c[0]))
+
+ return compat_list_c[0], compat_list_c[1:]
+
+ def scan_driver(self, fname):
+ """Scan a driver file to build a list of driver names and aliases
+
+ This procedure will populate self._drivers and self._driver_aliases
+
+ Args
+ fname: Driver filename to scan
+ """
+ with open(fname, encoding='utf-8') as inf:
+ try:
+ buff = inf.read()
+ except UnicodeDecodeError:
+ # This seems to happen on older Python versions
+ print("Skipping file '%s' due to unicode error" % fname)
+ return
+
+ # The following re will search for driver names declared as
+ # U_BOOT_DRIVER(driver_name)
+ drivers = re.findall(r'U_BOOT_DRIVER\((.*)\)', buff)
+
+ for driver in drivers:
+ self._drivers[driver] = Driver(driver)
+
+ # The following re will search for driver aliases declared as
+ # DM_DRIVER_ALIAS(alias, driver_name)
+ driver_aliases = re.findall(
+ r'DM_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)',
+ buff)
+
+ for alias in driver_aliases: # pragma: no cover
+ if len(alias) != 2:
+ continue
+ self._driver_aliases[alias[1]] = alias[0]
+
+ def scan_drivers(self):
+ """Scan the driver folders to build a list of driver names and aliases
+
+ This procedure will populate self._drivers and self._driver_aliases
+ """
+ for (dirpath, _, filenames) in os.walk(self._basedir):
+ for fname in filenames:
+ if not fname.endswith('.c'):
+ continue
+ self.scan_driver(dirpath + '/' + fname)
+
+ for fname in self._drivers_additional:
+ if not isinstance(fname, str) or len(fname) == 0:
+ continue
+ if fname[0] == '/':
+ self.scan_driver(fname)
+ else:
+ self.scan_driver(self._basedir + '/' + fname)
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index a5836e04b7..d961d67b8f 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -10,29 +10,29 @@ tool.
"""
import collections
+import glob
import os
import struct
-import sys
-import tempfile
import unittest
-from dtoc import dtb_platdata
-from dtb_platdata import conv_name_to_c
-from dtb_platdata import get_compat_name
from dtb_platdata import get_value
from dtb_platdata import tab_to
+from dtoc import dtb_platdata
from dtoc import fdt
from dtoc import fdt_util
+from dtoc.src_scan import conv_name_to_c
+from dtoc.src_scan import get_compat_name
from patman import test_util
from patman import tools
-our_path = os.path.dirname(os.path.realpath(__file__))
+OUR_PATH = os.path.dirname(os.path.realpath(__file__))
HEADER = '''/*
* DO NOT MODIFY
*
- * This file was generated by dtoc from a .dtb (device tree binary) file.
+ * Defines the structs used to hold devicetree data.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
*/
#include <stdbool.h>
@@ -41,33 +41,33 @@ HEADER = '''/*
C_HEADER = '''/*
* DO NOT MODIFY
*
- * This file was generated by dtoc from a .dtb (device tree binary) file.
+ * Declares the U_BOOT_DRIVER() records and platform data.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
*/
-/* Allow use of U_BOOT_DEVICE() in this file */
-#define DT_PLATDATA_C
+/* Allow use of U_BOOT_DRVINFO() in this file */
+#define DT_PLAT_C
#include <common.h>
#include <dm.h>
#include <dt-structs.h>
'''
-C_EMPTY_POPULATE_PHANDLE_DATA = '''void dm_populate_phandle_data(void) {
-}
-'''
-
+# This is a test so is allowed to access private things in the module it is
+# testing
+# pylint: disable=W0212
def get_dtb_file(dts_fname, capture_stderr=False):
"""Compile a .dts file to a .dtb
Args:
- dts_fname: Filename of .dts file in the current directory
- capture_stderr: True to capture and discard stderr output
+ dts_fname (str): Filename of .dts file in the current directory
+ capture_stderr (bool): True to capture and discard stderr output
Returns:
- Filename of compiled file in output directory
+ str: Filename of compiled file in output directory
"""
- return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname),
+ return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, dts_fname),
capture_stderr=capture_stderr)
@@ -80,20 +80,21 @@ class TestDtoc(unittest.TestCase):
@classmethod
def tearDownClass(cls):
- tools._RemoveOutputDir()
+ tools.FinaliseOutputDir()
- def _WritePythonString(self, fname, data):
+ @staticmethod
+ def _write_python_string(fname, data):
"""Write a string with tabs expanded as done in this Python file
Args:
- fname: Filename to write to
- data: Raw string to convert
+ fname (str): Filename to write to
+ data (str): Raw string to convert
"""
data = data.replace('\t', '\\t')
- with open(fname, 'w') as fd:
- fd.write(data)
+ with open(fname, 'w') as fout:
+ fout.write(data)
- def _CheckStrings(self, expected, actual):
+ def _check_strings(self, expected, actual):
"""Check that a string matches its expected value
If the strings do not match, they are written to the /tmp directory in
@@ -101,18 +102,25 @@ class TestDtoc(unittest.TestCase):
easy comparison and update of the tests.
Args:
- expected: Expected string
- actual: Actual string
+ expected (str): Expected string
+ actual (str): Actual string
"""
if expected != actual:
- self._WritePythonString('/tmp/binman.expected', expected)
- self._WritePythonString('/tmp/binman.actual', actual)
+ self._write_python_string('/tmp/binman.expected', expected)
+ self._write_python_string('/tmp/binman.actual', actual)
print('Failures written to /tmp/binman.{expected,actual}')
- self.assertEquals(expected, actual)
+ self.assertEqual(expected, actual)
+ @staticmethod
+ def run_test(args, dtb_file, output):
+ """Run a test using dtoc
- def run_test(self, args, dtb_file, output):
- dtb_platdata.run_steps(args, dtb_file, False, output, True)
+ Args:
+ args (list of str): List of arguments for dtoc
+ dtb_file (str): Filename of .dtb file
+ output (str): Filename of output file
+ """
+ dtb_platdata.run_steps(args, dtb_file, False, output, [], True)
def test_name(self):
"""Test conversion of device tree names to C identifiers"""
@@ -134,13 +142,13 @@ class TestDtoc(unittest.TestCase):
def test_get_value(self):
"""Test operation of get_value() function"""
self.assertEqual('0x45',
- get_value(fdt.TYPE_INT, struct.pack('>I', 0x45)))
+ get_value(fdt.Type.INT, struct.pack('>I', 0x45)))
self.assertEqual('0x45',
- get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45)))
+ get_value(fdt.Type.BYTE, struct.pack('<I', 0x45)))
self.assertEqual('0x0',
- get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45)))
- self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test'))
- self.assertEqual('true', get_value(fdt.TYPE_BOOL, None))
+ get_value(fdt.Type.BYTE, struct.pack('>I', 0x45)))
+ self.assertEqual('"test"', get_value(fdt.Type.STRING, 'test'))
+ self.assertEqual('true', get_value(fdt.Type.BOOL, None))
def test_get_compat_name(self):
"""Test operation of get_compat_name() function"""
@@ -160,7 +168,7 @@ class TestDtoc(unittest.TestCase):
prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third'])
node = Node({'compatible': prop})
self.assertEqual((['rockchip_rk3399_sdhci_5_1',
- 'arasan_sdhci_5_1', 'third']),
+ 'arasan_sdhci_5_1', 'third']),
get_compat_name(node))
def test_empty_file(self):
@@ -175,17 +183,9 @@ class TestDtoc(unittest.TestCase):
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
lines = infile.read().splitlines()
- self.assertEqual(C_HEADER.splitlines() + [''] +
- C_EMPTY_POPULATE_PHANDLE_DATA.splitlines(), lines)
+ self.assertEqual(C_HEADER.splitlines() + [''], lines)
- def test_simple(self):
- """Test output from some simple nodes with various types of data"""
- dtb_file = get_dtb_file('dtoc_test_simple.dts')
- output = tools.GetOutputFilename('output')
- self.run_test(['struct'], dtb_file, output)
- with open(output) as infile:
- data = infile.read()
- self._CheckStrings(HEADER + '''
+ struct_text = HEADER + '''
struct dtd_sandbox_i2c_test {
};
struct dtd_sandbox_pmic_test {
@@ -204,21 +204,16 @@ struct dtd_sandbox_spl_test {
\tconst char *\tstringarray[3];
\tconst char *\tstringval;
};
-struct dtd_sandbox_spl_test_2 {
-};
-''', data)
+'''
- self.run_test(['platdata'], dtb_file, output)
- with open(output) as infile:
- data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ platdata_text = C_HEADER + '''
/* Node /i2c@0 index 0 */
static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
};
-U_BOOT_DEVICE(i2c_at_0) = {
+U_BOOT_DRVINFO(i2c_at_0) = {
\t.name\t\t= "sandbox_i2c_test",
-\t.platdata\t= &dtv_i2c_at_0,
-\t.platdata_size\t= sizeof(dtv_i2c_at_0),
+\t.plat\t= &dtv_i2c_at_0,
+\t.plat_size\t= sizeof(dtv_i2c_at_0),
\t.parent_idx\t= -1,
};
@@ -227,10 +222,10 @@ static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
\t.low_power\t\t= true,
\t.reg\t\t\t= {0x9, 0x0},
};
-U_BOOT_DEVICE(pmic_at_9) = {
+U_BOOT_DRVINFO(pmic_at_9) = {
\t.name\t\t= "sandbox_pmic_test",
-\t.platdata\t= &dtv_pmic_at_9,
-\t.platdata_size\t= sizeof(dtv_pmic_at_9),
+\t.plat\t= &dtv_pmic_at_9,
+\t.plat_size\t= sizeof(dtv_pmic_at_9),
\t.parent_idx\t= 0,
};
@@ -247,10 +242,10 @@ static struct dtd_sandbox_spl_test dtv_spl_test = {
\t.stringarray\t\t= {"multi-word", "message", ""},
\t.stringval\t\t= "message",
};
-U_BOOT_DEVICE(spl_test) = {
+U_BOOT_DRVINFO(spl_test) = {
\t.name\t\t= "sandbox_spl_test",
-\t.platdata\t= &dtv_spl_test,
-\t.platdata_size\t= sizeof(dtv_spl_test),
+\t.plat\t= &dtv_spl_test,
+\t.plat_size\t= sizeof(dtv_spl_test),
\t.parent_idx\t= -1,
};
@@ -266,10 +261,10 @@ static struct dtd_sandbox_spl_test dtv_spl_test2 = {
\t.stringarray\t\t= {"another", "multi-word", "message"},
\t.stringval\t\t= "message2",
};
-U_BOOT_DEVICE(spl_test2) = {
+U_BOOT_DRVINFO(spl_test2) = {
\t.name\t\t= "sandbox_spl_test",
-\t.platdata\t= &dtv_spl_test2,
-\t.platdata_size\t= sizeof(dtv_spl_test2),
+\t.plat\t= &dtv_spl_test2,
+\t.plat_size\t= sizeof(dtv_spl_test2),
\t.parent_idx\t= -1,
};
@@ -279,24 +274,35 @@ static struct dtd_sandbox_spl_test dtv_spl_test3 = {
\t\t0x0},
\t.stringarray\t\t= {"one", "", ""},
};
-U_BOOT_DEVICE(spl_test3) = {
+U_BOOT_DRVINFO(spl_test3) = {
\t.name\t\t= "sandbox_spl_test",
-\t.platdata\t= &dtv_spl_test3,
-\t.platdata_size\t= sizeof(dtv_spl_test3),
+\t.plat\t= &dtv_spl_test3,
+\t.plat_size\t= sizeof(dtv_spl_test3),
\t.parent_idx\t= -1,
};
-/* Node /spl-test4 index 5 */
-static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
-};
-U_BOOT_DEVICE(spl_test4) = {
-\t.name\t\t= "sandbox_spl_test_2",
-\t.platdata\t= &dtv_spl_test4,
-\t.platdata_size\t= sizeof(dtv_spl_test4),
-\t.parent_idx\t= -1,
-};
+'''
-''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
+ def test_simple(self):
+ """Test output from some simple nodes with various types of data"""
+ dtb_file = get_dtb_file('dtoc_test_simple.dts')
+ output = tools.GetOutputFilename('output')
+ self.run_test(['struct'], dtb_file, output)
+ with open(output) as infile:
+ data = infile.read()
+
+ self._check_strings(self.struct_text, data)
+
+ self.run_test(['platdata'], dtb_file, output)
+ with open(output) as infile:
+ data = infile.read()
+
+ self._check_strings(self.platdata_text, data)
+
+ # Try the 'all' command
+ self.run_test(['all'], dtb_file, output)
+ data = tools.ReadFile(output, binary=False)
+ self._check_strings(self.platdata_text + self.struct_text, data)
def test_driver_alias(self):
"""Test output from a device tree file with a driver alias"""
@@ -305,7 +311,7 @@ U_BOOT_DEVICE(spl_test4) = {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_sandbox_gpio {
\tconst char *\tgpio_bank_name;
\tbool\t\tgpio_controller;
@@ -316,54 +322,50 @@ struct dtd_sandbox_gpio {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /gpios@0 index 0 */
static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
\t.gpio_bank_name\t\t= "a",
\t.gpio_controller\t= true,
\t.sandbox_gpio_count\t= 0x14,
};
-U_BOOT_DEVICE(gpios_at_0) = {
+U_BOOT_DRVINFO(gpios_at_0) = {
\t.name\t\t= "sandbox_gpio",
-\t.platdata\t= &dtv_gpios_at_0,
-\t.platdata_size\t= sizeof(dtv_gpios_at_0),
+\t.plat\t= &dtv_gpios_at_0,
+\t.plat_size\t= sizeof(dtv_gpios_at_0),
\t.parent_idx\t= -1,
};
-void dm_populate_phandle_data(void) {
-}
''', data)
def test_invalid_driver(self):
"""Test output from a device tree file with an invalid driver"""
dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts')
output = tools.GetOutputFilename('output')
- with test_util.capture_sys_output() as (stdout, stderr):
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ with test_util.capture_sys_output() as _:
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, [])
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_invalid {
};
''', data)
- with test_util.capture_sys_output() as (stdout, stderr):
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ with test_util.capture_sys_output() as _:
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [])
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /spl-test index 0 */
static struct dtd_invalid dtv_spl_test = {
};
-U_BOOT_DEVICE(spl_test) = {
+U_BOOT_DRVINFO(spl_test) = {
\t.name\t\t= "invalid",
-\t.platdata\t= &dtv_spl_test,
-\t.platdata_size\t= sizeof(dtv_spl_test),
+\t.plat\t= &dtv_spl_test,
+\t.plat_size\t= sizeof(dtv_spl_test),
\t.parent_idx\t= -1,
};
-void dm_populate_phandle_data(void) {
-}
''', data)
def test_phandle(self):
@@ -373,7 +375,7 @@ void dm_populate_phandle_data(void) {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_source {
\tstruct phandle_2_arg clocks[4];
};
@@ -385,15 +387,15 @@ struct dtd_target {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /phandle2-target index 0 */
static struct dtd_target dtv_phandle2_target = {
\t.intval\t\t\t= 0x1,
};
-U_BOOT_DEVICE(phandle2_target) = {
+U_BOOT_DRVINFO(phandle2_target) = {
\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle2_target,
-\t.platdata_size\t= sizeof(dtv_phandle2_target),
+\t.plat\t= &dtv_phandle2_target,
+\t.plat_size\t= sizeof(dtv_phandle2_target),
\t.parent_idx\t= -1,
};
@@ -401,21 +403,10 @@ U_BOOT_DEVICE(phandle2_target) = {
static struct dtd_target dtv_phandle3_target = {
\t.intval\t\t\t= 0x2,
};
-U_BOOT_DEVICE(phandle3_target) = {
+U_BOOT_DRVINFO(phandle3_target) = {
\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle3_target,
-\t.platdata_size\t= sizeof(dtv_phandle3_target),
-\t.parent_idx\t= -1,
-};
-
-/* Node /phandle-target index 4 */
-static struct dtd_target dtv_phandle_target = {
-\t.intval\t\t\t= 0x0,
-};
-U_BOOT_DEVICE(phandle_target) = {
-\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle_target,
-\t.platdata_size\t= sizeof(dtv_phandle_target),
+\t.plat\t= &dtv_phandle3_target,
+\t.plat_size\t= sizeof(dtv_phandle3_target),
\t.parent_idx\t= -1,
};
@@ -427,10 +418,10 @@ static struct dtd_source dtv_phandle_source = {
\t\t\t{1, {12, 13}},
\t\t\t{4, {}},},
};
-U_BOOT_DEVICE(phandle_source) = {
+U_BOOT_DRVINFO(phandle_source) = {
\t.name\t\t= "source",
-\t.platdata\t= &dtv_phandle_source,
-\t.platdata_size\t= sizeof(dtv_phandle_source),
+\t.plat\t= &dtv_phandle_source,
+\t.plat_size\t= sizeof(dtv_phandle_source),
\t.parent_idx\t= -1,
};
@@ -439,15 +430,24 @@ static struct dtd_source dtv_phandle_source2 = {
\t.clocks\t\t\t= {
\t\t\t{4, {}},},
};
-U_BOOT_DEVICE(phandle_source2) = {
+U_BOOT_DRVINFO(phandle_source2) = {
\t.name\t\t= "source",
-\t.platdata\t= &dtv_phandle_source2,
-\t.platdata_size\t= sizeof(dtv_phandle_source2),
+\t.plat\t= &dtv_phandle_source2,
+\t.plat_size\t= sizeof(dtv_phandle_source2),
+\t.parent_idx\t= -1,
+};
+
+/* Node /phandle-target index 4 */
+static struct dtd_target dtv_phandle_target = {
+\t.intval\t\t\t= 0x0,
+};
+U_BOOT_DRVINFO(phandle_target) = {
+\t.name\t\t= "target",
+\t.plat\t= &dtv_phandle_target,
+\t.plat_size\t= sizeof(dtv_phandle_target),
\t.parent_idx\t= -1,
};
-void dm_populate_phandle_data(void) {
-}
''', data)
def test_phandle_single(self):
@@ -457,7 +457,7 @@ void dm_populate_phandle_data(void) {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_source {
\tstruct phandle_0_arg clocks[1];
};
@@ -473,49 +473,47 @@ struct dtd_target {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
-/* Node /phandle-target index 1 */
-static struct dtd_target dtv_phandle_target = {
-};
-U_BOOT_DEVICE(phandle_target) = {
-\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle_target,
-\t.platdata_size\t= sizeof(dtv_phandle_target),
-\t.parent_idx\t= -1,
-};
-
+ self._check_strings(C_HEADER + '''
/* Node /phandle-source2 index 0 */
static struct dtd_source dtv_phandle_source2 = {
\t.clocks\t\t\t= {
\t\t\t{1, {}},},
};
-U_BOOT_DEVICE(phandle_source2) = {
+U_BOOT_DRVINFO(phandle_source2) = {
\t.name\t\t= "source",
-\t.platdata\t= &dtv_phandle_source2,
-\t.platdata_size\t= sizeof(dtv_phandle_source2),
+\t.plat\t= &dtv_phandle_source2,
+\t.plat_size\t= sizeof(dtv_phandle_source2),
+\t.parent_idx\t= -1,
+};
+
+/* Node /phandle-target index 1 */
+static struct dtd_target dtv_phandle_target = {
+};
+U_BOOT_DRVINFO(phandle_target) = {
+\t.name\t\t= "target",
+\t.plat\t= &dtv_phandle_target,
+\t.plat_size\t= sizeof(dtv_phandle_target),
\t.parent_idx\t= -1,
};
-void dm_populate_phandle_data(void) {
-}
''', data)
def test_phandle_cd_gpio(self):
"""Test that phandle targets are generated when unsing cd-gpios"""
dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [], True)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /phandle2-target index 0 */
static struct dtd_target dtv_phandle2_target = {
\t.intval\t\t\t= 0x1,
};
-U_BOOT_DEVICE(phandle2_target) = {
+U_BOOT_DRVINFO(phandle2_target) = {
\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle2_target,
-\t.platdata_size\t= sizeof(dtv_phandle2_target),
+\t.plat\t= &dtv_phandle2_target,
+\t.plat_size\t= sizeof(dtv_phandle2_target),
\t.parent_idx\t= -1,
};
@@ -523,21 +521,10 @@ U_BOOT_DEVICE(phandle2_target) = {
static struct dtd_target dtv_phandle3_target = {
\t.intval\t\t\t= 0x2,
};
-U_BOOT_DEVICE(phandle3_target) = {
-\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle3_target,
-\t.platdata_size\t= sizeof(dtv_phandle3_target),
-\t.parent_idx\t= -1,
-};
-
-/* Node /phandle-target index 4 */
-static struct dtd_target dtv_phandle_target = {
-\t.intval\t\t\t= 0x0,
-};
-U_BOOT_DEVICE(phandle_target) = {
+U_BOOT_DRVINFO(phandle3_target) = {
\t.name\t\t= "target",
-\t.platdata\t= &dtv_phandle_target,
-\t.platdata_size\t= sizeof(dtv_phandle_target),
+\t.plat\t= &dtv_phandle3_target,
+\t.plat_size\t= sizeof(dtv_phandle3_target),
\t.parent_idx\t= -1,
};
@@ -549,10 +536,10 @@ static struct dtd_source dtv_phandle_source = {
\t\t\t{1, {12, 13}},
\t\t\t{4, {}},},
};
-U_BOOT_DEVICE(phandle_source) = {
+U_BOOT_DRVINFO(phandle_source) = {
\t.name\t\t= "source",
-\t.platdata\t= &dtv_phandle_source,
-\t.platdata_size\t= sizeof(dtv_phandle_source),
+\t.plat\t= &dtv_phandle_source,
+\t.plat_size\t= sizeof(dtv_phandle_source),
\t.parent_idx\t= -1,
};
@@ -561,15 +548,24 @@ static struct dtd_source dtv_phandle_source2 = {
\t.cd_gpios\t\t= {
\t\t\t{4, {}},},
};
-U_BOOT_DEVICE(phandle_source2) = {
+U_BOOT_DRVINFO(phandle_source2) = {
\t.name\t\t= "source",
-\t.platdata\t= &dtv_phandle_source2,
-\t.platdata_size\t= sizeof(dtv_phandle_source2),
+\t.plat\t= &dtv_phandle_source2,
+\t.plat_size\t= sizeof(dtv_phandle_source2),
+\t.parent_idx\t= -1,
+};
+
+/* Node /phandle-target index 4 */
+static struct dtd_target dtv_phandle_target = {
+\t.intval\t\t\t= 0x0,
+};
+U_BOOT_DRVINFO(phandle_target) = {
+\t.name\t\t= "target",
+\t.plat\t= &dtv_phandle_target,
+\t.plat_size\t= sizeof(dtv_phandle_target),
\t.parent_idx\t= -1,
};
-void dm_populate_phandle_data(void) {
-}
''', data)
def test_phandle_bad(self):
@@ -577,20 +573,20 @@ void dm_populate_phandle_data(void) {
dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts',
capture_stderr=True)
output = tools.GetOutputFilename('output')
- with self.assertRaises(ValueError) as e:
+ with self.assertRaises(ValueError) as exc:
self.run_test(['struct'], dtb_file, output)
self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
- str(e.exception))
+ str(exc.exception))
def test_phandle_bad2(self):
"""Test a phandle target missing its #*-cells property"""
dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts',
capture_stderr=True)
output = tools.GetOutputFilename('output')
- with self.assertRaises(ValueError) as e:
+ with self.assertRaises(ValueError) as exc:
self.run_test(['struct'], dtb_file, output)
self.assertIn("Node 'phandle-target' has no cells property",
- str(e.exception))
+ str(exc.exception))
def test_addresses64(self):
"""Test output from a node with a 'reg' property with na=2, ns=2"""
@@ -599,7 +595,7 @@ void dm_populate_phandle_data(void) {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_test1 {
\tfdt64_t\t\treg[2];
};
@@ -614,15 +610,15 @@ struct dtd_test3 {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /test1 index 0 */
static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x1234, 0x5678},
};
-U_BOOT_DEVICE(test1) = {
+U_BOOT_DRVINFO(test1) = {
\t.name\t\t= "test1",
-\t.platdata\t= &dtv_test1,
-\t.platdata_size\t= sizeof(dtv_test1),
+\t.plat\t= &dtv_test1,
+\t.plat_size\t= sizeof(dtv_test1),
\t.parent_idx\t= -1,
};
@@ -630,10 +626,10 @@ U_BOOT_DEVICE(test1) = {
static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
};
-U_BOOT_DEVICE(test2) = {
+U_BOOT_DRVINFO(test2) = {
\t.name\t\t= "test2",
-\t.platdata\t= &dtv_test2,
-\t.platdata_size\t= sizeof(dtv_test2),
+\t.plat\t= &dtv_test2,
+\t.plat_size\t= sizeof(dtv_test2),
\t.parent_idx\t= -1,
};
@@ -641,14 +637,14 @@ U_BOOT_DEVICE(test2) = {
static struct dtd_test3 dtv_test3 = {
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
};
-U_BOOT_DEVICE(test3) = {
+U_BOOT_DRVINFO(test3) = {
\t.name\t\t= "test3",
-\t.platdata\t= &dtv_test3,
-\t.platdata_size\t= sizeof(dtv_test3),
+\t.plat\t= &dtv_test3,
+\t.plat_size\t= sizeof(dtv_test3),
\t.parent_idx\t= -1,
};
-''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
+''', data)
def test_addresses32(self):
"""Test output from a node with a 'reg' property with na=1, ns=1"""
@@ -657,7 +653,7 @@ U_BOOT_DEVICE(test3) = {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_test1 {
\tfdt32_t\t\treg[2];
};
@@ -669,15 +665,15 @@ struct dtd_test2 {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /test1 index 0 */
static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x1234, 0x5678},
};
-U_BOOT_DEVICE(test1) = {
+U_BOOT_DRVINFO(test1) = {
\t.name\t\t= "test1",
-\t.platdata\t= &dtv_test1,
-\t.platdata_size\t= sizeof(dtv_test1),
+\t.plat\t= &dtv_test1,
+\t.plat_size\t= sizeof(dtv_test1),
\t.parent_idx\t= -1,
};
@@ -685,14 +681,14 @@ U_BOOT_DEVICE(test1) = {
static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
};
-U_BOOT_DEVICE(test2) = {
+U_BOOT_DRVINFO(test2) = {
\t.name\t\t= "test2",
-\t.platdata\t= &dtv_test2,
-\t.platdata_size\t= sizeof(dtv_test2),
+\t.plat\t= &dtv_test2,
+\t.plat_size\t= sizeof(dtv_test2),
\t.parent_idx\t= -1,
};
-''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
+''', data)
def test_addresses64_32(self):
"""Test output from a node with a 'reg' property with na=2, ns=1"""
@@ -701,7 +697,7 @@ U_BOOT_DEVICE(test2) = {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_test1 {
\tfdt64_t\t\treg[2];
};
@@ -716,15 +712,15 @@ struct dtd_test3 {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /test1 index 0 */
static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x123400000000, 0x5678},
};
-U_BOOT_DEVICE(test1) = {
+U_BOOT_DRVINFO(test1) = {
\t.name\t\t= "test1",
-\t.platdata\t= &dtv_test1,
-\t.platdata_size\t= sizeof(dtv_test1),
+\t.plat\t= &dtv_test1,
+\t.plat_size\t= sizeof(dtv_test1),
\t.parent_idx\t= -1,
};
@@ -732,10 +728,10 @@ U_BOOT_DEVICE(test1) = {
static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x1234567890123456, 0x98765432},
};
-U_BOOT_DEVICE(test2) = {
+U_BOOT_DRVINFO(test2) = {
\t.name\t\t= "test2",
-\t.platdata\t= &dtv_test2,
-\t.platdata_size\t= sizeof(dtv_test2),
+\t.plat\t= &dtv_test2,
+\t.plat_size\t= sizeof(dtv_test2),
\t.parent_idx\t= -1,
};
@@ -743,14 +739,14 @@ U_BOOT_DEVICE(test2) = {
static struct dtd_test3 dtv_test3 = {
\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
};
-U_BOOT_DEVICE(test3) = {
+U_BOOT_DRVINFO(test3) = {
\t.name\t\t= "test3",
-\t.platdata\t= &dtv_test3,
-\t.platdata_size\t= sizeof(dtv_test3),
+\t.plat\t= &dtv_test3,
+\t.plat_size\t= sizeof(dtv_test3),
\t.parent_idx\t= -1,
};
-''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
+''', data)
def test_addresses32_64(self):
"""Test output from a node with a 'reg' property with na=1, ns=2"""
@@ -759,7 +755,7 @@ U_BOOT_DEVICE(test3) = {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_test1 {
\tfdt64_t\t\treg[2];
};
@@ -774,15 +770,15 @@ struct dtd_test3 {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /test1 index 0 */
static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x1234, 0x567800000000},
};
-U_BOOT_DEVICE(test1) = {
+U_BOOT_DRVINFO(test1) = {
\t.name\t\t= "test1",
-\t.platdata\t= &dtv_test1,
-\t.platdata_size\t= sizeof(dtv_test1),
+\t.plat\t= &dtv_test1,
+\t.plat_size\t= sizeof(dtv_test1),
\t.parent_idx\t= -1,
};
@@ -790,10 +786,10 @@ U_BOOT_DEVICE(test1) = {
static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x12345678, 0x9876543210987654},
};
-U_BOOT_DEVICE(test2) = {
+U_BOOT_DRVINFO(test2) = {
\t.name\t\t= "test2",
-\t.platdata\t= &dtv_test2,
-\t.platdata_size\t= sizeof(dtv_test2),
+\t.plat\t= &dtv_test2,
+\t.plat_size\t= sizeof(dtv_test2),
\t.parent_idx\t= -1,
};
@@ -801,34 +797,35 @@ U_BOOT_DEVICE(test2) = {
static struct dtd_test3 dtv_test3 = {
\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
};
-U_BOOT_DEVICE(test3) = {
+U_BOOT_DRVINFO(test3) = {
\t.name\t\t= "test3",
-\t.platdata\t= &dtv_test3,
-\t.platdata_size\t= sizeof(dtv_test3),
+\t.plat\t= &dtv_test3,
+\t.plat_size\t= sizeof(dtv_test3),
\t.parent_idx\t= -1,
};
-''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
+''', data)
def test_bad_reg(self):
"""Test that a reg property with an invalid type generates an error"""
# Capture stderr since dtc will emit warnings for this file
dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True)
output = tools.GetOutputFilename('output')
- with self.assertRaises(ValueError) as e:
+ with self.assertRaises(ValueError) as exc:
self.run_test(['struct'], dtb_file, output)
self.assertIn("Node 'spl-test' reg property is not an int",
- str(e.exception))
+ str(exc.exception))
def test_bad_reg2(self):
"""Test that a reg property with an invalid cell count is detected"""
# Capture stderr since dtc will emit warnings for this file
dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True)
output = tools.GetOutputFilename('output')
- with self.assertRaises(ValueError) as e:
+ with self.assertRaises(ValueError) as exc:
self.run_test(['struct'], dtb_file, output)
- self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
- str(e.exception))
+ self.assertIn(
+ "Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
+ str(exc.exception))
def test_add_prop(self):
"""Test that a subequent node can add a new property to a struct"""
@@ -837,7 +834,7 @@ U_BOOT_DEVICE(test3) = {
self.run_test(['struct'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(HEADER + '''
+ self._check_strings(HEADER + '''
struct dtd_sandbox_spl_test {
\tfdt32_t\t\tintarray;
\tfdt32_t\t\tintval;
@@ -847,15 +844,15 @@ struct dtd_sandbox_spl_test {
self.run_test(['platdata'], dtb_file, output)
with open(output) as infile:
data = infile.read()
- self._CheckStrings(C_HEADER + '''
+ self._check_strings(C_HEADER + '''
/* Node /spl-test index 0 */
static struct dtd_sandbox_spl_test dtv_spl_test = {
\t.intval\t\t\t= 0x1,
};
-U_BOOT_DEVICE(spl_test) = {
+U_BOOT_DRVINFO(spl_test) = {
\t.name\t\t= "sandbox_spl_test",
-\t.platdata\t= &dtv_spl_test,
-\t.platdata_size\t= sizeof(dtv_spl_test),
+\t.plat\t= &dtv_spl_test,
+\t.plat_size\t= sizeof(dtv_spl_test),
\t.parent_idx\t= -1,
};
@@ -863,58 +860,70 @@ U_BOOT_DEVICE(spl_test) = {
static struct dtd_sandbox_spl_test dtv_spl_test2 = {
\t.intarray\t\t= 0x5,
};
-U_BOOT_DEVICE(spl_test2) = {
+U_BOOT_DRVINFO(spl_test2) = {
\t.name\t\t= "sandbox_spl_test",
-\t.platdata\t= &dtv_spl_test2,
-\t.platdata_size\t= sizeof(dtv_spl_test2),
+\t.plat\t= &dtv_spl_test2,
+\t.plat_size\t= sizeof(dtv_spl_test2),
\t.parent_idx\t= -1,
};
-''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
+''', data)
- def testStdout(self):
+ def test_stdout(self):
"""Test output to stdout"""
dtb_file = get_dtb_file('dtoc_test_simple.dts')
- with test_util.capture_sys_output() as (stdout, stderr):
- self.run_test(['struct'], dtb_file, '-')
+ with test_util.capture_sys_output() as (stdout, _):
+ self.run_test(['struct'], dtb_file, None)
+ self._check_strings(self.struct_text, stdout.getvalue())
- def testNoCommand(self):
+ def test_multi_to_file(self):
+ """Test output of multiple pieces to a single file"""
+ dtb_file = get_dtb_file('dtoc_test_simple.dts')
+ output = tools.GetOutputFilename('output')
+ self.run_test(['all'], dtb_file, output)
+ data = tools.ReadFile(output, binary=False)
+ self._check_strings(self.platdata_text + self.struct_text, data)
+
+ def test_no_command(self):
"""Test running dtoc without a command"""
- with self.assertRaises(ValueError) as e:
+ with self.assertRaises(ValueError) as exc:
self.run_test([], '', '')
self.assertIn("Please specify a command: struct, platdata",
- str(e.exception))
+ str(exc.exception))
- def testBadCommand(self):
+ def test_bad_command(self):
"""Test running dtoc with an invalid command"""
dtb_file = get_dtb_file('dtoc_test_simple.dts')
output = tools.GetOutputFilename('output')
- with self.assertRaises(ValueError) as e:
+ with self.assertRaises(ValueError) as exc:
self.run_test(['invalid-cmd'], dtb_file, output)
- self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
- str(e.exception))
-
- def testScanDrivers(self):
- """Test running dtoc with additional drivers to scan"""
- dtb_file = get_dtb_file('dtoc_test_simple.dts')
- output = tools.GetOutputFilename('output')
- with test_util.capture_sys_output() as (stdout, stderr):
- dtb_platdata.run_steps(['struct'], dtb_file, False, output, True,
- [None, '', 'tools/dtoc/dtoc_test_scan_drivers.cxx'])
-
- def testUnicodeError(self):
- """Test running dtoc with an invalid unicode file
+ self.assertIn("Unknown command 'invalid-cmd': (use: platdata, struct)",
+ str(exc.exception))
+
+ def test_output_conflict(self):
+ """Test a conflict between and output dirs and output file"""
+ with self.assertRaises(ValueError) as exc:
+ dtb_platdata.run_steps(['all'], None, False, 'out', ['cdir'], True)
+ self.assertIn("Must specify either output or output_dirs, not both",
+ str(exc.exception))
+
+ def test_output_dirs(self):
+ """Test outputting files to a directory"""
+ # Remove the directory so that files from other tests are not there
+ tools._RemoveOutputDir()
+ tools.PrepareOutputDir(None)
- To be able to perform this test without adding a weird text file which
- would produce issues when using checkpatch.pl or patman, generate the
- file at runtime and then process it.
- """
+ # This should create the .dts and .dtb in the output directory
dtb_file = get_dtb_file('dtoc_test_simple.dts')
- output = tools.GetOutputFilename('output')
- driver_fn = '/tmp/' + next(tempfile._get_candidate_names())
- with open(driver_fn, 'wb+') as df:
- df.write(b'\x81')
-
- with test_util.capture_sys_output() as (stdout, stderr):
- dtb_platdata.run_steps(['struct'], dtb_file, False, output, True,
- [driver_fn])
+ outdir = tools.GetOutputDir()
+ fnames = glob.glob(outdir + '/*')
+ self.assertEqual(2, len(fnames))
+
+ dtb_platdata.run_steps(['all'], dtb_file, False, None, [outdir], True)
+ fnames = glob.glob(outdir + '/*')
+ self.assertEqual(4, len(fnames))
+
+ leafs = set(os.path.basename(fname) for fname in fnames)
+ self.assertEqual(
+ {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'},
+ leafs)
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index cfe3e04c7a..dc6943f733 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -19,7 +19,7 @@ sys.path.insert(1, os.path.join(our_path, '..'))
from dtoc import fdt
from dtoc import fdt_util
from dtoc.fdt_util import fdt32_to_cpu
-from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
+from fdt import Type, BytesToValue
import libfdt
from patman import command
from patman import test_util
@@ -46,7 +46,7 @@ def _GetPropertyValue(dtb, node, prop_name):
# Add 12, which is sizeof(struct fdt_property), to get to start of data
offset = prop.GetOffset() + 12
data = dtb.GetContents()[offset:offset + len(prop.value)]
- return prop, [tools.ToChar(x) for x in data]
+ return prop, [chr(x) for x in data]
class TestFdt(unittest.TestCase):
@@ -127,7 +127,7 @@ class TestFdt(unittest.TestCase):
def testBytesToValue(self):
self.assertEqual(BytesToValue(b'this\0is\0'),
- (TYPE_STRING, ['this', 'is']))
+ (Type.STRING, ['this', 'is']))
class TestNode(unittest.TestCase):
"""Test operation of the Node class"""
@@ -249,46 +249,46 @@ class TestProp(unittest.TestCase):
def testMakeProp(self):
"""Test we can convert all the the types that are supported"""
prop = self._ConvertProp('boolval')
- self.assertEqual(fdt.TYPE_BOOL, prop.type)
+ self.assertEqual(Type.BOOL, prop.type)
self.assertEqual(True, prop.value)
prop = self._ConvertProp('intval')
- self.assertEqual(fdt.TYPE_INT, prop.type)
+ self.assertEqual(Type.INT, prop.type)
self.assertEqual(1, fdt32_to_cpu(prop.value))
prop = self._ConvertProp('intarray')
- self.assertEqual(fdt.TYPE_INT, prop.type)
+ self.assertEqual(Type.INT, prop.type)
val = [fdt32_to_cpu(val) for val in prop.value]
self.assertEqual([2, 3, 4], val)
prop = self._ConvertProp('byteval')
- self.assertEqual(fdt.TYPE_BYTE, prop.type)
+ self.assertEqual(Type.BYTE, prop.type)
self.assertEqual(5, ord(prop.value))
prop = self._ConvertProp('longbytearray')
- self.assertEqual(fdt.TYPE_BYTE, prop.type)
+ self.assertEqual(Type.BYTE, prop.type)
val = [ord(val) for val in prop.value]
self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
prop = self._ConvertProp('stringval')
- self.assertEqual(fdt.TYPE_STRING, prop.type)
+ self.assertEqual(Type.STRING, prop.type)
self.assertEqual('message', prop.value)
prop = self._ConvertProp('stringarray')
- self.assertEqual(fdt.TYPE_STRING, prop.type)
+ self.assertEqual(Type.STRING, prop.type)
self.assertEqual(['multi-word', 'message'], prop.value)
prop = self._ConvertProp('notstring')
- self.assertEqual(fdt.TYPE_BYTE, prop.type)
+ self.assertEqual(Type.BYTE, prop.type)
val = [ord(val) for val in prop.value]
self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
def testGetEmpty(self):
"""Tests the GetEmpty() function for the various supported types"""
- self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
- self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
- self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
- self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
+ self.assertEqual(True, fdt.Prop.GetEmpty(Type.BOOL))
+ self.assertEqual(chr(0), fdt.Prop.GetEmpty(Type.BYTE))
+ self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(Type.INT))
+ self.assertEqual('', fdt.Prop.GetEmpty(Type.STRING))
def testGetOffset(self):
"""Test we can get the offset of a property"""
@@ -304,13 +304,13 @@ class TestProp(unittest.TestCase):
# No action
prop2 = node2.props['intval']
prop.Widen(prop2)
- self.assertEqual(fdt.TYPE_INT, prop.type)
+ self.assertEqual(Type.INT, prop.type)
self.assertEqual(1, fdt32_to_cpu(prop.value))
# Convert singla value to array
prop2 = self.node.props['intarray']
prop.Widen(prop2)
- self.assertEqual(fdt.TYPE_INT, prop.type)
+ self.assertEqual(Type.INT, prop.type)
self.assertTrue(isinstance(prop.value, list))
# A 4-byte array looks like a single integer. When widened by a longer
diff --git a/tools/dtoc/test_src_scan.py b/tools/dtoc/test_src_scan.py
new file mode 100644
index 0000000000..7d686530d6
--- /dev/null
+++ b/tools/dtoc/test_src_scan.py
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2020 Google LLC
+#
+
+"""Tests for the src_scan module
+
+This includes unit tests for scanning of the source code
+"""
+
+import os
+import shutil
+import tempfile
+import unittest
+from unittest import mock
+
+from dtoc import src_scan
+from patman import test_util
+from patman import tools
+
+# This is a test so is allowed to access private things in the module it is
+# testing
+# pylint: disable=W0212
+
+class TestSrcScan(unittest.TestCase):
+ """Tests for src_scan"""
+ @classmethod
+ def setUpClass(cls):
+ tools.PrepareOutputDir(None)
+
+ @classmethod
+ def tearDownClass(cls):
+ tools.FinaliseOutputDir()
+
+ def test_simple(self):
+ """Simple test of scanning drivers"""
+ scan = src_scan.Scanner(None, True, None)
+ scan.scan_drivers()
+ self.assertIn('sandbox_gpio', scan._drivers)
+ self.assertIn('sandbox_gpio_alias', scan._driver_aliases)
+ self.assertEqual('sandbox_gpio',
+ scan._driver_aliases['sandbox_gpio_alias'])
+ self.assertNotIn('sandbox_gpio_alias2', scan._driver_aliases)
+
+ def test_additional(self):
+ """Test with additional drivers to scan"""
+ scan = src_scan.Scanner(
+ None, True, [None, '', 'tools/dtoc/dtoc_test_scan_drivers.cxx'])
+ scan.scan_drivers()
+ self.assertIn('sandbox_gpio_alias2', scan._driver_aliases)
+ self.assertEqual('sandbox_gpio',
+ scan._driver_aliases['sandbox_gpio_alias2'])
+
+ def test_unicode_error(self):
+ """Test running dtoc with an invalid unicode file
+
+ To be able to perform this test without adding a weird text file which
+ would produce issues when using checkpatch.pl or patman, generate the
+ file at runtime and then process it.
+ """
+ driver_fn = '/tmp/' + next(tempfile._get_candidate_names())
+ with open(driver_fn, 'wb+') as fout:
+ fout.write(b'\x81')
+
+ scan = src_scan.Scanner(None, True, [driver_fn])
+ with test_util.capture_sys_output() as (stdout, _):
+ scan.scan_drivers()
+ self.assertRegex(stdout.getvalue(),
+ r"Skipping file '.*' due to unicode error\s*")
+
+ def test_driver(self):
+ """Test the Driver class"""
+ drv1 = src_scan.Driver('fred')
+ drv2 = src_scan.Driver('mary')
+ drv3 = src_scan.Driver('fred')
+ self.assertEqual("Driver(name='fred')", str(drv1))
+ self.assertEqual(drv1, drv3)
+ self.assertNotEqual(drv1, drv2)
+ self.assertNotEqual(drv2, drv3)
+
+ def test_scan_dirs(self):
+ """Test scanning of source directories"""
+ def add_file(fname):
+ pathname = os.path.join(indir, fname)
+ dirname = os.path.dirname(pathname)
+ os.makedirs(dirname, exist_ok=True)
+ tools.WriteFile(pathname, '', binary=False)
+ fname_list.append(pathname)
+
+ try:
+ indir = tempfile.mkdtemp(prefix='dtoc.')
+
+ fname_list = []
+ add_file('fname.c')
+ add_file('dir/fname2.c')
+
+ # Mock out scan_driver and check that it is called with the
+ # expected files
+ with mock.patch.object(src_scan.Scanner, "scan_driver") as mocked:
+ scan = src_scan.Scanner(indir, True, None)
+ scan.scan_drivers()
+ self.assertEqual(2, len(mocked.mock_calls))
+ self.assertEqual(mock.call(fname_list[0]),
+ mocked.mock_calls[0])
+ self.assertEqual(mock.call(fname_list[1]),
+ mocked.mock_calls[1])
+ finally:
+ shutil.rmtree(indir)
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
new file mode 100644
index 0000000000..270943fc90
--- /dev/null
+++ b/tools/mkeficapsule.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Linaro Limited
+ * Author: AKASHI Takahiro
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/types.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "fdt_host.h"
+
+typedef __u8 u8;
+typedef __u16 u16;
+typedef __u32 u32;
+typedef __u64 u64;
+typedef __s16 s16;
+typedef __s32 s32;
+
+#define aligned_u64 __aligned_u64
+
+#define SIGNATURE_NODENAME "signature"
+#define OVERLAY_NODENAME "__overlay__"
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+#include <efi.h>
+#include <efi_api.h>
+
+static const char *tool_name = "mkeficapsule";
+
+efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
+efi_guid_t efi_guid_image_type_uboot_fit =
+ EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
+efi_guid_t efi_guid_image_type_uboot_raw =
+ EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
+
+static struct option options[] = {
+ {"fit", required_argument, NULL, 'f'},
+ {"raw", required_argument, NULL, 'r'},
+ {"index", required_argument, NULL, 'i'},
+ {"instance", required_argument, NULL, 'I'},
+ {"dtb", required_argument, NULL, 'D'},
+ {"public key", required_argument, NULL, 'K'},
+ {"overlay", no_argument, NULL, 'O'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0},
+};
+
+static void print_usage(void)
+{
+ printf("Usage: %s [options] <output file>\n"
+ "Options:\n"
+
+ "\t--fit <fit image> new FIT image file\n"
+ "\t--raw <raw image> new raw image file\n"
+ "\t--index <index> update image index\n"
+ "\t--instance <instance> update hardware instance\n"
+ "\t--public-key <key file> public key esl file\n"
+ "\t--dtb <dtb file> dtb file\n"
+ "\t--overlay the dtb file is an overlay\n"
+ "\t--help print a help message\n",
+ tool_name);
+}
+
+static int fdt_add_pub_key_data(void *sptr, void *dptr, size_t key_size,
+ bool overlay)
+{
+ int parent;
+ int ov_node;
+ int frag_node;
+ int ret = 0;
+
+ if (overlay) {
+ /*
+ * The signature would be stored in the
+ * first fragment node of the overlay
+ */
+ frag_node = fdt_first_subnode(dptr, 0);
+ if (frag_node == -FDT_ERR_NOTFOUND) {
+ fprintf(stderr,
+ "Couldn't find the fragment node: %s\n",
+ fdt_strerror(frag_node));
+ goto done;
+ }
+
+ ov_node = fdt_subnode_offset(dptr, frag_node, OVERLAY_NODENAME);
+ if (ov_node == -FDT_ERR_NOTFOUND) {
+ fprintf(stderr,
+ "Couldn't find the __overlay__ node: %s\n",
+ fdt_strerror(ov_node));
+ goto done;
+ }
+ } else {
+ ov_node = 0;
+ }
+
+ parent = fdt_subnode_offset(dptr, ov_node, SIGNATURE_NODENAME);
+ if (parent == -FDT_ERR_NOTFOUND) {
+ parent = fdt_add_subnode(dptr, ov_node, SIGNATURE_NODENAME);
+ if (parent < 0) {
+ ret = parent;
+ if (ret != -FDT_ERR_NOSPACE) {
+ fprintf(stderr,
+ "Couldn't create signature node: %s\n",
+ fdt_strerror(parent));
+ }
+ }
+ }
+ if (ret)
+ goto done;
+
+ /* Write the key to the FDT node */
+ ret = fdt_setprop(dptr, parent, "capsule-key",
+ sptr, key_size);
+
+done:
+ if (ret)
+ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+
+ return ret;
+}
+
+static int add_public_key(const char *pkey_file, const char *dtb_file,
+ bool overlay)
+{
+ int ret;
+ int srcfd = 0;
+ int destfd = 0;
+ void *sptr = NULL;
+ void *dptr = NULL;
+ off_t src_size;
+ struct stat pub_key;
+ struct stat dtb;
+
+ /* Find out the size of the public key */
+ srcfd = open(pkey_file, O_RDONLY);
+ if (srcfd == -1) {
+ fprintf(stderr, "%s: Can't open %s: %s\n",
+ __func__, pkey_file, strerror(errno));
+ goto err;
+ }
+
+ ret = fstat(srcfd, &pub_key);
+ if (ret == -1) {
+ fprintf(stderr, "%s: Can't stat %s: %s\n",
+ __func__, pkey_file, strerror(errno));
+ goto err;
+ }
+
+ src_size = pub_key.st_size;
+
+ /* mmap the public key esl file */
+ sptr = mmap(0, src_size, PROT_READ, MAP_SHARED, srcfd, 0);
+ if ((sptr == MAP_FAILED) || (errno != 0)) {
+ fprintf(stderr, "%s: Failed to mmap %s:%s\n",
+ __func__, pkey_file, strerror(errno));
+ goto err;
+ }
+
+ /* Open the dest FDT */
+ destfd = open(dtb_file, O_RDWR);
+ if (destfd == -1) {
+ fprintf(stderr, "%s: Can't open %s: %s\n",
+ __func__, dtb_file, strerror(errno));
+ goto err;
+ }
+
+ ret = fstat(destfd, &dtb);
+ if (ret == -1) {
+ fprintf(stderr, "%s: Can't stat %s: %s\n",
+ __func__, dtb_file, strerror(errno));
+ goto err;
+ }
+
+ dtb.st_size += src_size + 0x30;
+ if (ftruncate(destfd, dtb.st_size)) {
+ fprintf(stderr, "%s: Can't expand %s: %s\n",
+ __func__, dtb_file, strerror(errno));
+ goto err;;
+ }
+
+ errno = 0;
+ /* mmap the dtb file */
+ dptr = mmap(0, dtb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ destfd, 0);
+ if ((dptr == MAP_FAILED) || (errno != 0)) {
+ fprintf(stderr, "%s: Failed to mmap %s:%s\n",
+ __func__, dtb_file, strerror(errno));
+ goto err;
+ }
+
+ if (fdt_check_header(dptr)) {
+ fprintf(stderr, "%s: Invalid FDT header\n", __func__);
+ goto err;
+ }
+
+ ret = fdt_open_into(dptr, dptr, dtb.st_size);
+ if (ret) {
+ fprintf(stderr, "%s: Cannot expand FDT: %s\n",
+ __func__, fdt_strerror(ret));
+ goto err;
+ }
+
+ /* Copy the esl file to the expanded FDT */
+ ret = fdt_add_pub_key_data(sptr, dptr, src_size, overlay);
+ if (ret < 0) {
+ fprintf(stderr, "%s: Unable to add public key to the FDT\n",
+ __func__);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ if (sptr)
+ munmap(sptr, src_size);
+
+ if (dptr)
+ munmap(dptr, dtb.st_size);
+
+ if (srcfd >= 0)
+ close(srcfd);
+
+ if (destfd >= 0)
+ close(destfd);
+
+ return -1;
+}
+
+static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
+ unsigned long index, unsigned long instance)
+{
+ struct efi_capsule_header header;
+ struct efi_firmware_management_capsule_header capsule;
+ struct efi_firmware_management_capsule_image_header image;
+ FILE *f, *g;
+ struct stat bin_stat;
+ u8 *data;
+ size_t size;
+ u64 offset;
+
+#ifdef DEBUG
+ printf("For output: %s\n", path);
+ printf("\tbin: %s\n\ttype: %pUl\n" bin, guid);
+ printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
+#endif
+
+ g = fopen(bin, "r");
+ if (!g) {
+ printf("cannot open %s\n", bin);
+ return -1;
+ }
+ if (stat(bin, &bin_stat) < 0) {
+ printf("cannot determine the size of %s\n", bin);
+ goto err_1;
+ }
+ data = malloc(bin_stat.st_size);
+ if (!data) {
+ printf("cannot allocate memory: %lx\n", bin_stat.st_size);
+ goto err_1;
+ }
+ f = fopen(path, "w");
+ if (!f) {
+ printf("cannot open %s\n", path);
+ goto err_2;
+ }
+ header.capsule_guid = efi_guid_fm_capsule;
+ header.header_size = sizeof(header);
+ /* TODO: The current implementation ignores flags */
+ header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+ header.capsule_image_size = sizeof(header)
+ + sizeof(capsule) + sizeof(u64)
+ + sizeof(image)
+ + bin_stat.st_size;
+
+ size = fwrite(&header, 1, sizeof(header), f);
+ if (size < sizeof(header)) {
+ printf("write failed (%lx)\n", size);
+ goto err_3;
+ }
+
+ capsule.version = 0x00000001;
+ capsule.embedded_driver_count = 0;
+ capsule.payload_item_count = 1;
+ size = fwrite(&capsule, 1, sizeof(capsule), f);
+ if (size < (sizeof(capsule))) {
+ printf("write failed (%lx)\n", size);
+ goto err_3;
+ }
+ offset = sizeof(capsule) + sizeof(u64);
+ size = fwrite(&offset, 1, sizeof(offset), f);
+ if (size < sizeof(offset)) {
+ printf("write failed (%lx)\n", size);
+ goto err_3;
+ }
+
+ image.version = 0x00000003;
+ memcpy(&image.update_image_type_id, guid, sizeof(*guid));
+ image.update_image_index = index;
+ image.update_image_size = bin_stat.st_size;
+ image.update_vendor_code_size = 0; /* none */
+ image.update_hardware_instance = instance;
+ image.image_capsule_support = 0;
+
+ size = fwrite(&image, 1, sizeof(image), f);
+ if (size < sizeof(image)) {
+ printf("write failed (%lx)\n", size);
+ goto err_3;
+ }
+ size = fread(data, 1, bin_stat.st_size, g);
+ if (size < bin_stat.st_size) {
+ printf("read failed (%lx)\n", size);
+ goto err_3;
+ }
+ size = fwrite(data, 1, bin_stat.st_size, f);
+ if (size < bin_stat.st_size) {
+ printf("write failed (%lx)\n", size);
+ goto err_3;
+ }
+
+ fclose(f);
+ fclose(g);
+ free(data);
+
+ return 0;
+
+err_3:
+ fclose(f);
+err_2:
+ free(data);
+err_1:
+ fclose(g);
+
+ return -1;
+}
+
+/*
+ * Usage:
+ * $ mkeficapsule -f <firmware binary> <output file>
+ */
+int main(int argc, char **argv)
+{
+ char *file;
+ char *pkey_file;
+ char *dtb_file;
+ efi_guid_t *guid;
+ unsigned long index, instance;
+ int c, idx;
+ int ret;
+ bool overlay = false;
+
+ file = NULL;
+ pkey_file = NULL;
+ dtb_file = NULL;
+ guid = NULL;
+ index = 0;
+ instance = 0;
+ for (;;) {
+ c = getopt_long(argc, argv, "f:r:i:I:v:D:K:Oh", options, &idx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'f':
+ if (file) {
+ printf("Image already specified\n");
+ return -1;
+ }
+ file = optarg;
+ guid = &efi_guid_image_type_uboot_fit;
+ break;
+ case 'r':
+ if (file) {
+ printf("Image already specified\n");
+ return -1;
+ }
+ file = optarg;
+ guid = &efi_guid_image_type_uboot_raw;
+ break;
+ case 'i':
+ index = strtoul(optarg, NULL, 0);
+ break;
+ case 'I':
+ instance = strtoul(optarg, NULL, 0);
+ break;
+ case 'K':
+ if (pkey_file) {
+ printf("Public Key already specified\n");
+ return -1;
+ }
+ pkey_file = optarg;
+ break;
+ case 'D':
+ if (dtb_file) {
+ printf("DTB file already specified\n");
+ return -1;
+ }
+ dtb_file = optarg;
+ break;
+ case 'O':
+ overlay = true;
+ break;
+ case 'h':
+ print_usage();
+ return 0;
+ }
+ }
+
+ /* need a fit image file or raw image file */
+ if (!file && !pkey_file && !dtb_file) {
+ printf("%s: %d\n", __func__, __LINE__);
+ print_usage();
+ return -1;
+ }
+
+ if (pkey_file && dtb_file) {
+ ret = add_public_key(pkey_file, dtb_file, overlay);
+ if (ret == -1) {
+ printf("Adding public key to the dtb failed\n");
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (create_fwbin(argv[optind], file, guid, index, instance)
+ < 0) {
+ printf("Creating firmware capsule failed\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tools/patman/control.py b/tools/patman/control.py
index 2330682df4..ee9717cbf6 100644
--- a/tools/patman/control.py
+++ b/tools/patman/control.py
@@ -20,7 +20,7 @@ def setup():
"""Do required setup before doing anything"""
gitutil.Setup()
-def prepare_patches(col, branch, count, start, end, ignore_binary):
+def prepare_patches(col, branch, count, start, end, ignore_binary, signoff):
"""Figure out what patches to generate, then generate them
The patch files are written to the current directory, e.g. 0001_xxx.patch
@@ -56,7 +56,7 @@ def prepare_patches(col, branch, count, start, end, ignore_binary):
to_do = count - end
series = patchstream.get_metadata(branch, start, to_do)
cover_fname, patch_files = gitutil.CreatePatches(
- branch, start, to_do, ignore_binary, series)
+ branch, start, to_do, ignore_binary, series, signoff)
# Fix up the patch files to our liking, and insert the cover letter
patchstream.fix_patches(series, patch_files)
@@ -163,7 +163,7 @@ def send(args):
col = terminal.Color()
series, cover_fname, patch_files = prepare_patches(
col, args.branch, args.count, args.start, args.end,
- args.ignore_binary)
+ args.ignore_binary, args.add_signoff)
ok = check_patches(series, patch_files, args.check_patch,
args.verbose)
diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py
index 74a144dc2d..89072b1ae7 100644
--- a/tools/patman/func_test.py
+++ b/tools/patman/func_test.py
@@ -237,27 +237,26 @@ class TestFunctional(unittest.TestCase):
if 'Cc:' not in prev:
break
self.assertEqual('To: u-boot@lists.denx.de', prev)
- self.assertEqual('Cc: %s' % tools.FromUnicode(stefan), next(lines))
+ self.assertEqual('Cc: %s' % stefan, next(lines))
self.assertEqual('Version: 3', next(lines))
self.assertEqual('Prefix:\t RFC', next(lines))
self.assertEqual('Cover: 4 lines', next(lines))
self.assertEqual(' Cc: %s' % self.fred, next(lines))
- self.assertEqual(' Cc: %s' % tools.FromUnicode(self.leb),
+ self.assertEqual(' Cc: %s' % self.leb,
next(lines))
- self.assertEqual(' Cc: %s' % tools.FromUnicode(mel), next(lines))
+ self.assertEqual(' Cc: %s' % mel, next(lines))
self.assertEqual(' Cc: %s' % rick, next(lines))
expected = ('Git command: git send-email --annotate '
'--in-reply-to="%s" --to "u-boot@lists.denx.de" '
'--cc "%s" --cc-cmd "%s send --cc-cmd %s" %s %s'
% (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname,
' '.join(args)))
- self.assertEqual(expected, tools.ToUnicode(next(lines)))
+ self.assertEqual(expected, next(lines))
- self.assertEqual(('%s %s\0%s' % (args[0], rick, stefan)),
- tools.ToUnicode(cc_lines[0]))
+ self.assertEqual(('%s %s\0%s' % (args[0], rick, stefan)), cc_lines[0])
self.assertEqual(
'%s %s\0%s\0%s\0%s' % (args[1], self.fred, self.leb, rick, stefan),
- tools.ToUnicode(cc_lines[1]))
+ cc_lines[1])
expected = '''
This is a test of how the cover
@@ -476,7 +475,7 @@ complicated as possible''')
with capture_sys_output() as _:
_, cover_fname, patch_files = control.prepare_patches(
col, branch=None, count=-1, start=0, end=0,
- ignore_binary=False)
+ ignore_binary=False, signoff=True)
self.assertIsNone(cover_fname)
self.assertEqual(2, len(patch_files))
@@ -485,7 +484,7 @@ complicated as possible''')
with capture_sys_output() as _:
_, cover_fname, patch_files = control.prepare_patches(
col, branch='second', count=-1, start=0, end=0,
- ignore_binary=False)
+ ignore_binary=False, signoff=True)
self.assertIsNotNone(cover_fname)
self.assertEqual(3, len(patch_files))
@@ -493,7 +492,7 @@ complicated as possible''')
with capture_sys_output() as _:
_, cover_fname, patch_files = control.prepare_patches(
col, branch='second', count=-1, start=0, end=1,
- ignore_binary=False)
+ ignore_binary=False, signoff=True)
self.assertIsNotNone(cover_fname)
self.assertEqual(2, len(patch_files))
finally:
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index 31fb3b2829..bf1271ded7 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -305,7 +305,7 @@ def PruneWorktrees(git_dir):
if result.return_code != 0:
raise OSError('git worktree prune: %s' % result.stderr)
-def CreatePatches(branch, start, count, ignore_binary, series):
+def CreatePatches(branch, start, count, ignore_binary, series, signoff = True):
"""Create a series of patches from the top of the current branch.
The patch files are written to the current directory using
@@ -323,7 +323,9 @@ def CreatePatches(branch, start, count, ignore_binary, series):
"""
if series.get('version'):
version = '%s ' % series['version']
- cmd = ['git', 'format-patch', '-M', '--signoff']
+ cmd = ['git', 'format-patch', '-M' ]
+ if signoff:
+ cmd.append('--signoff')
if ignore_binary:
cmd.append('--no-binary')
if series.get('cover'):
@@ -383,7 +385,6 @@ def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
raw += LookupEmail(item, alias, raise_on_error=raise_on_error)
result = []
for item in raw:
- item = tools.FromUnicode(item)
if not item in result:
result.append(item)
if tag:
@@ -494,7 +495,7 @@ send --cc-cmd cc-fname" cover p1 p2'
if smtp_server:
cmd.append('--smtp-server=%s' % smtp_server)
if in_reply_to:
- cmd.append('--in-reply-to="%s"' % tools.FromUnicode(in_reply_to))
+ cmd.append('--in-reply-to="%s"' % in_reply_to)
if thread:
cmd.append('--thread')
diff --git a/tools/patman/main.py b/tools/patman/main.py
index 342fd446a1..c4e4d80d42 100755
--- a/tools/patman/main.py
+++ b/tools/patman/main.py
@@ -81,6 +81,8 @@ send.add_argument('--no-check', action='store_false', dest='check_patch',
help="Don't check for patch compliance")
send.add_argument('--no-tags', action='store_false', dest='process_tags',
default=True, help="Don't process subject tags as aliases")
+send.add_argument('--no-signoff', action='store_false', dest='add_signoff',
+ default=True, help="Don't add Signed-off-by to patches")
send.add_argument('--smtp-server', type=str,
help="Specify the SMTP server to 'git send-email'")
diff --git a/tools/patman/series.py b/tools/patman/series.py
index 1d92bdb910..a6746e87c4 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -272,7 +272,6 @@ class Series(dict):
for x in set(cc) & set(settings.bounces):
print(col.Color(col.YELLOW, 'Skipping "%s"' % x))
cc = set(cc) - set(settings.bounces)
- cc = [tools.FromUnicode(m) for m in cc]
if limit is not None:
cc = cc[:limit]
all_ccs += cc
@@ -281,11 +280,10 @@ class Series(dict):
if cover_fname:
cover_cc = gitutil.BuildEmailList(self.get('cover_cc', ''))
- cover_cc = [tools.FromUnicode(m) for m in cover_cc]
cover_cc = list(set(cover_cc + all_ccs))
if limit is not None:
cover_cc = cover_cc[:limit]
- cc_list = '\0'.join([tools.ToUnicode(x) for x in sorted(cover_cc)])
+ cc_list = '\0'.join([x for x in sorted(cover_cc)])
print(cover_fname, cc_list, file=fd)
fd.close()
diff --git a/tools/patman/settings.py b/tools/patman/settings.py
index 8c10eab264..13c1ee4f56 100644
--- a/tools/patman/settings.py
+++ b/tools/patman/settings.py
@@ -23,7 +23,12 @@ _default_settings = {
"u-boot": {},
"linux": {
"process_tags": "False",
- }
+ },
+ "gcc": {
+ "process_tags": "False",
+ "add_signoff": "False",
+ "check_patch": "False",
+ },
}
class _ProjectConfigParser(ConfigParser.SafeConfigParser):
@@ -112,7 +117,7 @@ class _ProjectConfigParser(ConfigParser.SafeConfigParser):
val = ConfigParser.SafeConfigParser.get(
self, section, option, *args, **kwargs
)
- return tools.ToUnicode(val)
+ return val
def items(self, section, *args, **kwargs):
"""Extend SafeConfigParser to add project_section to section.
@@ -147,8 +152,7 @@ class _ProjectConfigParser(ConfigParser.SafeConfigParser):
item_dict = dict(top_items)
item_dict.update(project_items)
- return {(tools.ToUnicode(item), tools.ToUnicode(val))
- for item, val in item_dict.items()}
+ return {(item, val) for item, val in item_dict.items()}
def ReadGitAliases(fname):
"""Read a git alias file. This is in the form used by git:
diff --git a/tools/patman/test_checkpatch.py b/tools/patman/test_checkpatch.py
index 1f7c38c4e9..a4fec1d4c1 100644
--- a/tools/patman/test_checkpatch.py
+++ b/tools/patman/test_checkpatch.py
@@ -411,6 +411,34 @@ index 0000000..2234c87
pm.add_line('common/main.c', 'if (CONFIG_IS_ENABLED(CONFIG_CLK))')
self.checkSingleMessage(pm, 'CONFIG_IS_ENABLED_CONFIG', 'error')
+ def check_struct(self, auto, suffix, warning):
+ """Check one of the warnings for struct naming
+
+ Args:
+ auto: Auto variable name, e.g. 'per_child_auto'
+ suffix: Suffix to expect on member, e.g. '_priv'
+ warning: Warning name, e.g. 'PRIV_AUTO'
+ """
+ pm = PatchMaker()
+ pm.add_line('common/main.c', '.%s = sizeof(struct(fred)),' % auto)
+ pm.add_line('common/main.c', '.%s = sizeof(struct(mary%s)),' %
+ (auto, suffix))
+ self.checkSingleMessage(
+ pm, warning, "struct 'fred' should have a %s suffix" % suffix)
+
+ def testDmDriverAuto(self):
+ """Check for the correct suffix on 'struct driver' auto members"""
+ self.check_struct('priv_auto', '_priv', 'PRIV_AUTO')
+ self.check_struct('plat_auto', '_plat', 'PLAT_AUTO')
+ self.check_struct('per_child_auto', '_priv', 'CHILD_PRIV_AUTO')
+ self.check_struct('per_child_plat_auto', '_plat', 'CHILD_PLAT_AUTO')
+
+ def testDmUclassAuto(self):
+ """Check for the correct suffix on 'struct uclass' auto members"""
+ # Some of these are omitted since they match those from struct driver
+ self.check_struct('per_device_auto', '_priv', 'DEVICE_PRIV_AUTO')
+ self.check_struct('per_device_plat_auto', '_plat', 'DEVICE_PLAT_AUTO')
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index 05b1a1d4b0..d8e01a3e60 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -94,6 +94,14 @@ def GetOutputFilename(fname):
"""
return os.path.join(outdir, fname)
+def GetOutputDir():
+ """Return the current output directory
+
+ Returns:
+ str: The output directory
+ """
+ return outdir
+
def _FinaliseForTest():
"""Remove the output directory (for use by tests)"""
global outdir
@@ -415,8 +423,6 @@ def WriteFile(fname, data, binary=True):
def GetBytes(byte, size):
"""Get a string of bytes of a given size
- This handles the unfortunate different between Python 2 and Python 2.
-
Args:
byte: Numeric byte value to use
size: Size of bytes/string to return
@@ -424,81 +430,7 @@ def GetBytes(byte, size):
Returns:
A bytes type with 'byte' repeated 'size' times
"""
- if sys.version_info[0] >= 3:
- data = bytes([byte]) * size
- else:
- data = chr(byte) * size
- return data
-
-def ToUnicode(val):
- """Make sure a value is a unicode string
-
- This allows some amount of compatibility between Python 2 and Python3. For
- the former, it returns a unicode object.
-
- Args:
- val: string or unicode object
-
- Returns:
- unicode version of val
- """
- if sys.version_info[0] >= 3:
- return val
- return val if isinstance(val, unicode) else val.decode('utf-8')
-
-def FromUnicode(val):
- """Make sure a value is a non-unicode string
-
- This allows some amount of compatibility between Python 2 and Python3. For
- the former, it converts a unicode object to a string.
-
- Args:
- val: string or unicode object
-
- Returns:
- non-unicode version of val
- """
- if sys.version_info[0] >= 3:
- return val
- return val if isinstance(val, str) else val.encode('utf-8')
-
-def ToByte(ch):
- """Convert a character to an ASCII value
-
- This is useful because in Python 2 bytes is an alias for str, but in
- Python 3 they are separate types. This function converts the argument to
- an ASCII value in either case.
-
- Args:
- ch: A string (Python 2) or byte (Python 3) value
-
- Returns:
- integer ASCII value for ch
- """
- return ord(ch) if type(ch) == str else ch
-
-def ToChar(byte):
- """Convert a byte to a character
-
- This is useful because in Python 2 bytes is an alias for str, but in
- Python 3 they are separate types. This function converts an ASCII value to
- a value with the appropriate type in either case.
-
- Args:
- byte: A byte or str value
- """
- return chr(byte) if type(byte) != str else byte
-
-def ToChars(byte_list):
- """Convert a list of bytes to a str/bytes type
-
- Args:
- byte_list: List of ASCII values representing the string
-
- Returns:
- string made by concatenating all the ASCII values
- """
- return ''.join([chr(byte) for byte in byte_list])
+ return bytes([byte]) * size
def ToBytes(string):
"""Convert a str type into a bytes type
@@ -507,12 +439,9 @@ def ToBytes(string):
string: string to convert
Returns:
- Python 3: A bytes type
- Python 2: A string type
+ A bytes type
"""
- if sys.version_info[0] >= 3:
- return string.encode('utf-8')
- return string
+ return string.encode('utf-8')
def ToString(bval):
"""Convert a bytes type into a str type
diff --git a/tools/zynqmp_pm_cfg_obj_convert.py b/tools/zynqmp_pm_cfg_obj_convert.py
index dd27f47921..0a44710e1e 100755
--- a/tools/zynqmp_pm_cfg_obj_convert.py
+++ b/tools/zynqmp_pm_cfg_obj_convert.py
@@ -289,7 +289,7 @@ code = in_file.read()
code = re.sub('//.*?\n|/\*.*?\*/', '', code, flags=re.DOTALL)
# remove everything outside the XPm_ConfigObject array definition
-code = re.search('const u32 XPm_ConfigObject.*= {\n(.*)};',
+code = re.search('const u32 XPm_ConfigObject.*=.*{\n(.*)};',
code, flags=re.DOTALL).group(1)
# Process each comma-separated array item