diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 14 | ||||
-rw-r--r-- | tools/dtoc/.gitignore | 1 | ||||
l--------- | tools/dtoc/dtoc | 1 | ||||
-rwxr-xr-x | tools/dtoc/dtoc.py | 394 | ||||
-rw-r--r-- | tools/dtoc/fdt.py | 180 | ||||
-rw-r--r-- | tools/dtoc/fdt_fallback.py | 213 | ||||
-rw-r--r-- | tools/dtoc/fdt_util.py | 86 | ||||
-rw-r--r-- | tools/env/fw_env.c | 250 | ||||
-rw-r--r-- | tools/env/fw_env.config | 7 | ||||
-rw-r--r-- | tools/env/fw_env.h | 115 | ||||
-rw-r--r-- | tools/fit_image.c | 7 | ||||
-rw-r--r-- | tools/image-host.c | 30 | ||||
-rw-r--r-- | tools/mkimage.c | 70 | ||||
-rw-r--r-- | tools/patman/patchstream.py | 38 | ||||
-rw-r--r-- | tools/rkcommon.c | 1 |
15 files changed, 1246 insertions, 161 deletions
diff --git a/tools/Makefile b/tools/Makefile index f72294a..421414b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -107,6 +107,20 @@ mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o +# Build a libfdt Python module if swig is available +# Use 'sudo apt-get install swig libpython-dev' to enable this +hostprogs-$(CONFIG_SPL_OF_PLATDATA) += \ + $(if $(shell which swig),_libfdt.so) +_libfdt.so-sharedobjs += $(LIBFDT_OBJS) +libfdt: + +tools/_libfdt.so: $(patsubst %.o,%.c,$(LIBFDT_OBJS)) tools/libfdt_wrap.c + python $(srctree)/lib/libfdt/setup.py "$(_hostc_flags)" $^ + mv _libfdt.so $@ + +tools/libfdt_wrap.c: $(srctree)/lib/libfdt/libfdt.swig + swig -python -o $@ $< + # TODO(sjg@chromium.org): Is this correct on Mac OS? ifneq ($(CONFIG_MX23)$(CONFIG_MX28),) diff --git a/tools/dtoc/.gitignore b/tools/dtoc/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/tools/dtoc/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/tools/dtoc/dtoc b/tools/dtoc/dtoc new file mode 120000 index 0000000..896ca44 --- /dev/null +++ b/tools/dtoc/dtoc @@ -0,0 +1 @@ +dtoc.py
\ No newline at end of file diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py new file mode 100755 index 0000000..ec80abe --- /dev/null +++ b/tools/dtoc/dtoc.py @@ -0,0 +1,394 @@ +#!/usr/bin/python +# +# Copyright (C) 2016 Google, Inc +# Written by Simon Glass <sjg@chromium.org> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +import copy +from optparse import OptionError, OptionParser +import os +import sys + +import fdt_util + +# Bring in the patman libraries +our_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(our_path, '../patman')) + +# Bring in either the normal fdt library (which relies on libfdt) or the +# fallback one (which uses fdtget and is slower). Both provide the same +# interfface for this file to use. +try: + from fdt import Fdt + import fdt + have_libfdt = True +except ImportError: + have_libfdt = False + from fdt_fallback import Fdt + import fdt_fallback as fdt + +import struct + +# When we see these properties we ignore them - i.e. do not create a structure member +PROP_IGNORE_LIST = [ + '#address-cells', + '#gpio-cells', + '#size-cells', + 'compatible', + 'linux,phandle', + "status", + 'phandle', + 'u-boot,dm-pre-reloc', +] + +# C type declarations for the tyues we support +TYPE_NAMES = { + fdt_util.TYPE_INT: 'fdt32_t', + fdt_util.TYPE_BYTE: 'unsigned char', + fdt_util.TYPE_STRING: 'const char *', + fdt_util.TYPE_BOOL: 'bool', +}; + +STRUCT_PREFIX = 'dtd_' +VAL_PREFIX = 'dtv_' + +def Conv_name_to_c(name): + """Convert a device-tree name to a C identifier + + Args: + name: Name to convert + Return: + String containing the C version of this name + """ + str = name.replace('@', '_at_') + str = str.replace('-', '_') + str = str.replace(',', '_') + str = str.replace('/', '__') + return str + +def TabTo(num_tabs, str): + if len(str) >= num_tabs * 8: + return str + ' ' + return str + '\t' * (num_tabs - len(str) / 8) + +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- + constrained encvironments where the ~3KB code overhead of device tree + code is not affordable. + + Properties: + 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 + _options: Command-line options + _phandle_node: A dict of nodes indexed by phandle number (1, 2...) + _outfile: The current output file (sys.stdout or a real file) + _lines: Stashed list of output lines for outputting in the future + _phandle_node: A dict of Nodes indexed by phandle (an integer) + """ + def __init__(self, dtb_fname, options): + self._dtb_fname = dtb_fname + self._valid_nodes = None + self._options = options + self._phandle_node = {} + self._outfile = None + self._lines = [] + + def SetupOutput(self, fname): + """Set up the output destination + + Once this is done, future calls to self.Out() will output to this + file. + + Args: + fname: Filename to send output to, or '-' for stdout + """ + if fname == '-': + self._outfile = sys.stdout + else: + self._outfile = open(fname, 'w') + + def Out(self, str): + """Output a string to the output file + + Args: + str: String to output + """ + self._outfile.write(str) + + def Buf(self, str): + """Buffer up a string to send later + + Args: + str: String to add to our 'buffer' list + """ + self._lines.append(str) + + def GetBuf(self): + """Get the contents of the output buffer, and clear it + + Returns: + The output buffer, which is then cleared for future use + """ + lines = self._lines + self._lines = [] + return lines + + def GetValue(self, type, value): + """Get a value as a C expression + + For integers this returns a byte-swapped (little-endian) hex string + For bytes this returns a hex string, e.g. 0x12 + For strings this returns a literal string enclosed in quotes + For booleans this return 'true' + + Args: + type: Data type (fdt_util) + value: Data value, as a string of bytes + """ + if type == fdt_util.TYPE_INT: + return '%#x' % fdt_util.fdt32_to_cpu(value) + elif type == fdt_util.TYPE_BYTE: + return '%#x' % ord(value[0]) + elif type == fdt_util.TYPE_STRING: + return '"%s"' % value + elif type == fdt_util.TYPE_BOOL: + return 'true' + + def GetCompatName(self, node): + """Get a node's first compatible string as a C identifier + + Args: + node: Node object to check + Return: + C identifier for the first compatible string + """ + compat = node.props['compatible'].value + if type(compat) == list: + compat = compat[0] + return Conv_name_to_c(compat) + + def ScanDtb(self): + """Scan the device tree to obtain a tree of notes and properties + + Once this is done, self.fdt.GetRoot() can be called to obtain the + device tree root node, and progress from there. + """ + self.fdt = Fdt(self._dtb_fname) + self.fdt.Scan() + + def ScanTree(self): + """Scan the device tree for useful information + + This fills in the following properties: + _phandle_node: A dict of Nodes indexed by phandle (an integer) + _valid_nodes: A list of nodes we wish to consider include in the + platform data + """ + node_list = [] + self._phandle_node = {} + for node in self.fdt.GetRoot().subnodes: + if 'compatible' in node.props: + status = node.props.get('status') + if (not options.include_disabled and not status or + status.value != 'disabled'): + node_list.append(node) + phandle_prop = node.props.get('phandle') + if phandle_prop: + phandle = phandle_prop.GetPhandle() + self._phandle_node[phandle] = node + + self._valid_nodes = node_list + + def IsPhandle(self, prop): + """Check if a node contains phandles + + We have no reliable way of detecting whether a node uses a phandle + or not. As an interim measure, use a list of known property names. + + Args: + prop: Prop object to check + Return: + True if the object value contains phandles, else False + """ + if prop.name in ['clocks']: + return True + return False + + def ScanStructs(self): + """Scan the device tree building up the C structures we will use. + + Build a dict keyed by C struct name containing a dict of Prop + object for each struct field (keyed by property name). Where the + same struct appears multiple times, try to use the 'widest' + property, i.e. the one with a type which can express all others. + + Once the widest property is determined, all other properties are + updated to match that width. + """ + structs = {} + for node in self._valid_nodes: + node_name = self.GetCompatName(node) + fields = {} + + # Get a list of all the valid properties in this node. + for name, prop in node.props.iteritems(): + if name not in PROP_IGNORE_LIST and name[0] != '#': + fields[name] = copy.deepcopy(prop) + + # If we've seen this node_name before, update the existing struct. + if node_name in structs: + struct = structs[node_name] + for name, prop in fields.iteritems(): + oldprop = struct.get(name) + if oldprop: + oldprop.Widen(prop) + else: + struct[name] = prop + + # Otherwise store this as a new struct. + else: + structs[node_name] = fields + + upto = 0 + for node in self._valid_nodes: + node_name = self.GetCompatName(node) + struct = structs[node_name] + for name, prop in node.props.iteritems(): + if name not in PROP_IGNORE_LIST and name[0] != '#': + prop.Widen(struct[name]) + upto += 1 + return structs + + def GenerateStructs(self, structs): + """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 + README.of-plat for more information. + """ + self.Out('#include <stdbool.h>\n') + self.Out('#include <libfdt.h>\n') + + # Output the struct definition + for name in sorted(structs): + self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name)); + for pname in sorted(structs[name]): + prop = structs[name][pname] + if self.IsPhandle(prop): + # For phandles, include a reference to the target + self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'), + Conv_name_to_c(prop.name), + len(prop.value) / 2)) + else: + ptype = TYPE_NAMES[prop.type] + self.Out('\t%s%s' % (TabTo(2, ptype), + Conv_name_to_c(prop.name))) + if type(prop.value) == list: + self.Out('[%d]' % len(prop.value)) + self.Out(';\n') + self.Out('};\n') + + def GenerateTables(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. See the + documentation in README.of-plat for more information. + """ + self.Out('#include <common.h>\n') + self.Out('#include <dm.h>\n') + self.Out('#include <dt-structs.h>\n') + self.Out('\n') + node_txt_list = [] + for node in self._valid_nodes: + struct_name = self.GetCompatName(node) + var_name = Conv_name_to_c(node.name) + self.Buf('static struct %s%s %s%s = {\n' % + (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) + for pname, prop in node.props.iteritems(): + if pname in PROP_IGNORE_LIST or pname[0] == '#': + continue + ptype = TYPE_NAMES[prop.type] + member_name = Conv_name_to_c(prop.name) + self.Buf('\t%s= ' % TabTo(3, '.' + member_name)) + + # Special handling for lists + if type(prop.value) == list: + self.Buf('{') + vals = [] + # For phandles, output a reference to the platform data + # of the target node. + if self.IsPhandle(prop): + # Process the list as pairs of (phandle, id) + it = iter(prop.value) + for phandle_cell, id_cell in zip(it, it): + phandle = fdt_util.fdt32_to_cpu(phandle_cell) + id = fdt_util.fdt32_to_cpu(id_cell) + target_node = self._phandle_node[phandle] + name = Conv_name_to_c(target_node.name) + vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id)) + else: + for val in prop.value: + vals.append(self.GetValue(prop.type, val)) + self.Buf(', '.join(vals)) + self.Buf('}') + else: + self.Buf(self.GetValue(prop.type, prop.value)) + self.Buf(',\n') + self.Buf('};\n') + + # Add a device declaration + self.Buf('U_BOOT_DEVICE(%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('};\n') + self.Buf('\n') + + # Output phandle target nodes first, since they may be referenced + # by others + if 'phandle' in node.props: + self.Out(''.join(self.GetBuf())) + else: + node_txt_list.append(self.GetBuf()) + + # Output all the nodes which are not phandle targets themselves, but + # may reference them. This avoids the need for forward declarations. + for node_txt in node_txt_list: + self.Out(''.join(node_txt)) + + +if __name__ != "__main__": + pass + +parser = OptionParser() +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='-', + help='Select output filename') +(options, args) = parser.parse_args() + +if not args: + raise ValueError('Please specify a command: struct, platdata') + +plat = DtbPlatdata(options.dtb_file, options) +plat.ScanDtb() +plat.ScanTree() +plat.SetupOutput(options.output) +structs = plat.ScanStructs() + +for cmd in args[0].split(','): + if cmd == 'struct': + plat.GenerateStructs(structs) + elif cmd == 'platdata': + plat.GenerateTables() + else: + raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py new file mode 100644 index 0000000..1d913a9 --- /dev/null +++ b/tools/dtoc/fdt.py @@ -0,0 +1,180 @@ +#!/usr/bin/python +# +# Copyright (C) 2016 Google, Inc +# Written by Simon Glass <sjg@chromium.org> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +import fdt_util +import libfdt +import sys + +# This deals with a device tree, presenting it as a list of Node and Prop +# objects, representing nodes and properties, respectively. +# +# This implementation uses a libfdt Python library to access the device tree, +# so it is fairly efficient. + +class Prop: + """A device tree property + + Properties: + name: Property name (as per the device tree) + value: Property value as a string of bytes, or a list of strings of + bytes + type: Value type + """ + def __init__(self, name, bytes): + self.name = name + self.value = None + if not bytes: + self.type = fdt_util.TYPE_BOOL + self.value = True + return + self.type, self.value = fdt_util.BytesToValue(bytes) + + def GetPhandle(self): + """Get a (single) phandle value from a property + + Gets the phandle valuie from a property and returns it as an integer + """ + return fdt_util.fdt32_to_cpu(self.value[:4]) + + def Widen(self, newprop): + """Figure out which property type is more general + + Given a current property and a new property, this function returns the + one that is less specific as to type. The less specific property will + be ble to represent the data in the more specific property. This is + used for things like: + + node1 { + compatible = "fred"; + value = <1>; + }; + node1 { + compatible = "fred"; + value = <1 2>; + }; + + He we want to use an int array for 'value'. The first property + suggests that a single int is enough, but the second one shows that + it is not. Calling this function with these two propertes would + update the current property to be like the second, since it is less + specific. + """ + if newprop.type < self.type: + self.type = newprop.type + + if type(newprop.value) == list and type(self.value) != list: + self.value = [self.value] + + if type(self.value) == list and len(newprop.value) > len(self.value): + val = fdt_util.GetEmpty(self.type) + while len(self.value) < len(newprop.value): + self.value.append(val) + + +class Node: + """A device tree node + + Properties: + offset: Integer offset in the device tree + name: Device tree node tname + path: Full path to node, along with the node name itself + _fdt: Device tree object + subnodes: A list of subnodes for this node, each a Node object + props: A dict of properties for this node, each a Prop object. + Keyed by property name + """ + def __init__(self, fdt, offset, name, path): + self.offset = offset + self.name = name + self.path = path + self._fdt = fdt + self.subnodes = [] + self.props = {} + + def Scan(self): + """Scan a node's properties and subnodes + + This fills in the props and subnodes properties, recursively + searching into subnodes so that the entire tree is built. + """ + self.props = self._fdt.GetProps(self.path) + + offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.offset) + while offset >= 0: + sep = '' if self.path[-1] == '/' else '/' + name = libfdt.Name(self._fdt.GetFdt(), offset) + path = self.path + sep + name + node = Node(self._fdt, offset, name, path) + self.subnodes.append(node) + + node.Scan() + offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset) + + +class Fdt: + """Provides simple access to a flat device tree blob. + + Properties: + fname: Filename of fdt + _root: Root of device tree (a Node object) + """ + + def __init__(self, fname): + self.fname = fname + with open(fname) as fd: + self._fdt = fd.read() + + def GetFdt(self): + """Get the contents of the FDT + + Returns: + The FDT contents as a string of bytes + """ + return self._fdt + + def Scan(self): + """Scan a device tree, building up a tree of Node objects + + This fills in the self._root property + """ + self._root = Node(self, 0, '/', '/') + self._root.Scan() + + def GetRoot(self): + """Get the root Node of the device tree + + Returns: + The root Node object + """ + return self._root + + def GetProps(self, node): + """Get all properties from a node. + + Args: + node: Full path to node name to look in. + + Returns: + A dictionary containing all the properties, indexed by node name. + The entries are Prop objects. + + Raises: + ValueError: if the node does not exist. + """ + offset = libfdt.fdt_path_offset(self._fdt, node) + if offset < 0: + libfdt.Raise(offset) + props_dict = {} + poffset = libfdt.fdt_first_property_offset(self._fdt, offset) + while poffset >= 0: + dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset) + prop = Prop(libfdt.String(self._fdt, dprop.nameoff), libfdt.Data(dprop)) + props_dict[prop.name] = prop + + poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) + return props_dict diff --git a/tools/dtoc/fdt_fallback.py b/tools/dtoc/fdt_fallback.py new file mode 100644 index 0000000..9ed11e4 --- /dev/null +++ b/tools/dtoc/fdt_fallback.py @@ -0,0 +1,213 @@ +#!/usr/bin/python +# +# Copyright (C) 2016 Google, Inc +# Written by Simon Glass <sjg@chromium.org> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +import command +import fdt_util +import sys + +# This deals with a device tree, presenting it as a list of Node and Prop +# objects, representing nodes and properties, respectively. +# +# This implementation uses the fdtget tool to access the device tree, so it +# is not very efficient for larger trees. The tool is called once for each +# node and property in the tree. + +class Prop: + """A device tree property + + Properties: + name: Property name (as per the device tree) + value: Property value as a string of bytes, or a list of strings of + bytes + type: Value type + """ + def __init__(self, name, byte_list_str): + self.name = name + self.value = None + if not byte_list_str.strip(): + self.type = fdt_util.TYPE_BOOL + return + bytes = [chr(int(byte, 16)) for byte in byte_list_str.strip().split(' ')] + self.type, self.value = fdt_util.BytesToValue(''.join(bytes)) + + def GetPhandle(self): + """Get a (single) phandle value from a property + + Gets the phandle valuie from a property and returns it as an integer + """ + return fdt_util.fdt32_to_cpu(self.value[:4]) + + def Widen(self, newprop): + """Figure out which property type is more general + + Given a current property and a new property, this function returns the + one that is less specific as to type. The less specific property will + be ble to represent the data in the more specific property. This is + used for things like: + + node1 { + compatible = "fred"; + value = <1>; + }; + node1 { + compatible = "fred"; + value = <1 2>; + }; + + He we want to use an int array for 'value'. The first property + suggests that a single int is enough, but the second one shows that + it is not. Calling this function with these two propertes would + update the current property to be like the second, since it is less + specific. + """ + if newprop.type < self.type: + self.type = newprop.type + + if type(newprop.value) == list and type(self.value) != list: + self.value = newprop.value + + if type(self.value) == list and len(newprop.value) > len(self.value): + val = fdt_util.GetEmpty(self.type) + while len(self.value) < len(newprop.value): + self.value.append(val) + + +class Node: + """A device tree node + + Properties: + name: Device tree node tname + path: Full path to node, along with the node name itself + _fdt: Device tree object + subnodes: A list of subnodes for this node, each a Node object + props: A dict of properties for this node, each a Prop object. + Keyed by property name + """ + def __init__(self, fdt, name, path): + self.name = name + self.path = path + self._fdt = fdt + self.subnodes = [] + self.props = {} + + def Scan(self): + """Scan a node's properties and subnodes + + This fills in the props and subnodes properties, recursively + searching into subnodes so that the entire tree is built. + """ + for name, byte_list_str in self._fdt.GetProps(self.path).iteritems(): + prop = Prop(name, byte_list_str) + self.props[name] = prop + + for name in self._fdt.GetSubNodes(self.path): + sep = '' if self.path[-1] == '/' else '/' + path = self.path + sep + name + node = Node(self._fdt, name, path) + self.subnodes.append(node) + + node.Scan() + + +class Fdt: + """Provides simple access to a flat device tree blob. + + Properties: + fname: Filename of fdt + _root: Root of device tree (a Node object) + """ + + def __init__(self, fname): + self.fname = fname + + def Scan(self): + """Scan a device tree, building up a tree of Node objects + + This fills in the self._root property + """ + self._root = Node(self, '/', '/') + self._root.Scan() + + def GetRoot(self): + """Get the root Node of the device tree + + Returns: + The root Node object + """ + return self._root + + def GetSubNodes(self, node): + """Returns a list of sub-nodes of a given node + + Args: + node: Node name to return children from + + Returns: + List of children in the node (each a string node name) + + Raises: + CmdError: if the node does not exist. + """ + out = command.Output('fdtget', self.fname, '-l', node) + return out.strip().splitlines() + + def GetProps(self, node, convert_dashes=False): + """Get all properties from a node + + Args: + node: full path to node name to look in + convert_dashes: True to convert - to _ in node names + + Returns: + A dictionary containing all the properties, indexed by node name. + The entries are simply strings - no decoding of lists or numbers + is done. + + Raises: + CmdError: if the node does not exist. + """ + out = command.Output('fdtget', self.fname, node, '-p') + props = out.strip().splitlines() + props_dict = {} + for prop in props: + name = prop + if convert_dashes: + prop = re.sub('-', '_', prop) + props_dict[prop] = self.GetProp(node, name) + return props_dict + + def GetProp(self, node, prop, default=None, typespec=None): + """Get a property from a device tree. + + This looks up the given node and property, and returns the value as a + string, + + If the node or property does not exist, this will return the default + value. + + Args: + node: Full path to node to look up. + prop: Property name to look up. + default: Default value to return if nothing is present in the fdt, + or None to raise in this case. This will be converted to a + string. + typespec: Type character to use (None for default, 's' for string) + + Returns: + string containing the property value. + + Raises: + CmdError: if the property does not exist and no default is provided. + """ + args = [self.fname, node, prop, '-t', 'bx'] + if default is not None: + args += ['-d', str(default)] + if typespec is not None: + args += ['-t%s' % typespec] + out = command.Output('fdtget', *args) + return out.strip() diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py new file mode 100644 index 0000000..929b524 --- /dev/null +++ b/tools/dtoc/fdt_util.py @@ -0,0 +1,86 @@ +#!/usr/bin/python +# +# Copyright (C) 2016 Google, Inc +# Written by Simon Glass <sjg@chromium.org> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +import struct + +# A list of types we support +(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4) + +def BytesToValue(bytes): + """Converts a string of bytes into a type and value + + Args: + A string containing bytes + + Return: + A tuple: + Type of data + Data, either a single element or a list of elements. Each element + is one of: + TYPE_STRING: string value from the property + TYPE_INT: a byte-swapped integer stored as a 4-byte string + TYPE_BYTE: a byte stored as a single-byte string + """ + size = len(bytes) + strings = bytes.split('\0') + is_string = True + count = len(strings) - 1 + if count > 0 and not strings[-1]: + for string in strings[:-1]: + if not string: + is_string = False + break + for ch in string: + if ch < ' ' or ch > '~': + is_string = False + break + else: + is_string = False + if is_string: + if count == 1: + return TYPE_STRING, strings[0] + else: + return TYPE_STRING, strings[:-1] + if size % 4: + if size == 1: + return TYPE_BYTE, bytes[0] + else: + return TYPE_BYTE, list(bytes) + val = [] + for i in range(0, size, 4): + val.append(bytes[i:i + 4]) + if size == 4: + return TYPE_INT, val[0] + else: + return TYPE_INT, val + +def GetEmpty(type): + """Get an empty / zero value of the given type + + Returns: + A single value of the given type + """ + if type == TYPE_BYTE: + return chr(0) + elif type == TYPE_INT: + return struct.pack('<I', 0); + elif type == TYPE_STRING: + return '' + else: + return True + +def fdt32_to_cpu(val): + """Convert a device tree cell to an integer + + Args: + Value to convert (4-character string representing the cell value) + + Return: + A native-endian integer value + """ + return struct.unpack(">I", val)[0] diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 692abda..6b0dcaa 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -14,6 +14,7 @@ #include <errno.h> #include <env_flags.h> #include <fcntl.h> +#include <linux/fs.h> #include <linux/stringify.h> #include <ctype.h> #include <stdio.h> @@ -51,7 +52,7 @@ struct env_opts default_opts = { struct envdev_s { const char *devname; /* Device name */ - ulong devoff; /* Device offset */ + long long devoff; /* Device offset */ ulong env_size; /* environment size */ ulong erase_size; /* device erase size */ ulong env_sectors; /* number of environment sectors */ @@ -121,7 +122,6 @@ static unsigned char obsolete_flag = 0; #include <env_default.h> static int flash_io (int mode); -static char *envmatch (char * s1, char * s2); static int parse_config(struct env_opts *opts); #if defined(CONFIG_FILE) @@ -147,6 +147,24 @@ static char *skip_blanks(char *s) } /* + * s1 is either a simple 'name', or a 'name=value' pair. + * s2 is a 'name=value' pair. + * If the names match, return the value of s2, else NULL. + */ +static char *envmatch(char *s1, char *s2) +{ + if (s1 == NULL || s2 == NULL) + return NULL; + + while (*s1 == *s2++) + if (*s1++ == '=') + return s2; + if (*s1 == '\0' && *(s2 - 1) == '=') + return s2; + return NULL; +} + +/** * Search the environment for a variable. * Return the value, if found, or NULL, if not found. */ @@ -232,9 +250,14 @@ int parse_aes_key(char *key, uint8_t *bin_key) */ int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts) { - char *env, *nxt; int i, rc = 0; + if (value_only && argc != 1) { + fprintf(stderr, + "## Error: `-n' option requires exactly one argument\n"); + return -1; + } + if (!opts) opts = &default_opts; @@ -242,6 +265,7 @@ int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts) return -1; if (argc == 0) { /* Print all env variables */ + char *env, *nxt; for (env = environment.data; *env; env = nxt + 1) { for (nxt = env; *nxt; ++nxt) { if (nxt >= &environment.data[ENV_SIZE]) { @@ -256,39 +280,23 @@ int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts) return 0; } - if (value_only && argc != 1) { - fprintf(stderr, - "## Error: `-n' option requires exactly one argument\n"); - return -1; - } - - for (i = 0; i < argc; ++i) { /* print single env variables */ + for (i = 0; i < argc; ++i) { /* print a subset of env variables */ char *name = argv[i]; char *val = NULL; - for (env = environment.data; *env; env = nxt + 1) { - - for (nxt = env; *nxt; ++nxt) { - if (nxt >= &environment.data[ENV_SIZE]) { - fprintf (stderr, "## Error: " - "environment not terminated\n"); - return -1; - } - } - val = envmatch (name, env); - if (val) { - if (!value_only) { - fputs (name, stdout); - putc ('=', stdout); - } - puts (val); - break; - } - } + val = fw_getenv(name); if (!val) { fprintf (stderr, "## Error: \"%s\" not defined\n", name); rc = -1; + continue; + } + + if (value_only) { + puts(val); + break; } + + printf("%s=%s\n", name, val); } return rc; @@ -483,7 +491,7 @@ int fw_setenv(int argc, char *argv[], struct env_opts *opts) valc = argc - 1; if (env_flags_validate_env_set_params(name, valv, valc) < 0) - return 1; + return -1; len = 0; for (i = 0; i < valc; ++i) { @@ -653,8 +661,8 @@ static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart) if (badblock) { #ifdef DEBUG - fprintf (stderr, "Bad block at 0x%llx, " - "skipping\n", *blockstart); + fprintf (stderr, "Bad block at 0x%llx, skipping\n", + (unsigned long long) *blockstart); #endif return badblock; } @@ -741,7 +749,8 @@ static int flash_read_buf (int dev, int fd, void *buf, size_t count, } #ifdef DEBUG fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n", - rc, blockstart + block_seek, DEVNAME(dev)); + rc, (unsigned long long) blockstart + block_seek, + DEVNAME(dev)); #endif processed += readlen; readlen = min (blocklen, count - processed); @@ -839,8 +848,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count, if (block_seek + count != write_total) { if (block_seek != 0) fprintf(stderr, " and "); - fprintf(stderr, "0x%lx - 0x%x", - block_seek + count, write_total - 1); + fprintf(stderr, "0x%lx - 0x%lx", + (unsigned long) block_seek + count, + (unsigned long) write_total - 1); } fprintf(stderr, "\n"); #endif @@ -903,8 +913,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count, } #ifdef DEBUG - fprintf(stderr, "Write 0x%x bytes at 0x%llx\n", erasesize, - blockstart); + fprintf(stderr, "Write 0x%llx bytes at 0x%llx\n", + (unsigned long long) erasesize, + (unsigned long long) blockstart); #endif if (write (fd, data + processed, erasesize) != erasesize) { fprintf (stderr, "Write error on %s: %s\n", @@ -994,7 +1005,7 @@ static int flash_write (int fd_current, int fd_target, int dev_target) } #ifdef DEBUG - fprintf(stderr, "Writing new environment at 0x%lx on %s\n", + fprintf(stderr, "Writing new environment at 0x%llx on %s\n", DEVOFFSET (dev_target), DEVNAME (dev_target)); #endif @@ -1010,7 +1021,7 @@ static int flash_write (int fd_current, int fd_target, int dev_target) offsetof (struct env_image_redundant, flags); #ifdef DEBUG fprintf(stderr, - "Setting obsolete flag in environment at 0x%lx on %s\n", + "Setting obsolete flag in environment at 0x%llx on %s\n", DEVOFFSET (dev_current), DEVNAME (dev_current)); #endif flash_flag_obsolete (dev_current, fd_current, offset); @@ -1021,41 +1032,10 @@ static int flash_write (int fd_current, int fd_target, int dev_target) static int flash_read (int fd) { - struct mtd_info_user mtdinfo; - struct stat st; int rc; - rc = fstat(fd, &st); - if (rc < 0) { - fprintf(stderr, "Cannot stat the file %s\n", - DEVNAME(dev_current)); - return -1; - } - - if (S_ISCHR(st.st_mode)) { - rc = ioctl(fd, MEMGETINFO, &mtdinfo); - if (rc < 0) { - fprintf(stderr, "Cannot get MTD information for %s\n", - DEVNAME(dev_current)); - return -1; - } - if (mtdinfo.type != MTD_NORFLASH && - mtdinfo.type != MTD_NANDFLASH && - mtdinfo.type != MTD_DATAFLASH && - mtdinfo.type != MTD_UBIVOLUME) { - fprintf (stderr, "Unsupported flash type %u on %s\n", - mtdinfo.type, DEVNAME(dev_current)); - return -1; - } - } else { - memset(&mtdinfo, 0, sizeof(mtdinfo)); - mtdinfo.type = MTD_ABSENT; - } - - DEVTYPE(dev_current) = mtdinfo.type; - rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE, - DEVOFFSET (dev_current), mtdinfo.type); + DEVOFFSET(dev_current), DEVTYPE(dev_current)); if (rc != CUR_ENVSIZE) return -1; @@ -1121,25 +1101,6 @@ exit: } /* - * s1 is either a simple 'name', or a 'name=value' pair. - * s2 is a 'name=value' pair. - * If the names match, return the value of s2, else NULL. - */ - -static char *envmatch (char * s1, char * s2) -{ - if (s1 == NULL || s2 == NULL) - return NULL; - - while (*s1 == *s2++) - if (*s1++ == '=') - return s2; - if (*s1 == '\0' && *(s2 - 1) == '=') - return s2; - return NULL; -} - -/* * Prevent confusion if running from erased flash memory */ int fw_env_open(struct env_opts *opts) @@ -1328,10 +1289,75 @@ int fw_env_open(struct env_opts *opts) return 0; } +static int check_device_config(int dev) +{ + struct stat st; + int fd, rc = 0; + + fd = open(DEVNAME(dev), O_RDONLY); + if (fd < 0) { + fprintf(stderr, + "Cannot open %s: %s\n", + DEVNAME(dev), strerror(errno)); + return -1; + } + + rc = fstat(fd, &st); + if (rc < 0) { + fprintf(stderr, "Cannot stat the file %s\n", + DEVNAME(dev)); + goto err; + } + + if (S_ISCHR(st.st_mode)) { + struct mtd_info_user mtdinfo; + rc = ioctl(fd, MEMGETINFO, &mtdinfo); + if (rc < 0) { + fprintf(stderr, "Cannot get MTD information for %s\n", + DEVNAME(dev)); + goto err; + } + if (mtdinfo.type != MTD_NORFLASH && + mtdinfo.type != MTD_NANDFLASH && + mtdinfo.type != MTD_DATAFLASH && + mtdinfo.type != MTD_UBIVOLUME) { + fprintf(stderr, "Unsupported flash type %u on %s\n", + mtdinfo.type, DEVNAME(dev)); + goto err; + } + DEVTYPE(dev) = mtdinfo.type; + } else { + uint64_t size; + DEVTYPE(dev) = MTD_ABSENT; + + /* + * Check for negative offsets, treat it as backwards offset + * from the end of the block device + */ + if (DEVOFFSET(dev) < 0) { + rc = ioctl(fd, BLKGETSIZE64, &size); + if (rc < 0) { + fprintf(stderr, "Could not get block device size on %s\n", + DEVNAME(dev)); + goto err; + } + + DEVOFFSET(dev) = DEVOFFSET(dev) + size; +#ifdef DEBUG + fprintf(stderr, "Calculated device offset 0x%llx on %s\n", + DEVOFFSET(dev), DEVNAME(dev)); +#endif + } + } + +err: + close(fd); + return rc; +} static int parse_config(struct env_opts *opts) { - struct stat st; + int rc; if (!opts) opts = &default_opts; @@ -1375,25 +1401,21 @@ static int parse_config(struct env_opts *opts) HaveRedundEnv = 1; #endif #endif - if (stat (DEVNAME (0), &st)) { - fprintf (stderr, - "Cannot access MTD device %s: %s\n", - DEVNAME (0), strerror (errno)); - return -1; - } + rc = check_device_config(0); + if (rc < 0) + return rc; - if (HaveRedundEnv && stat (DEVNAME (1), &st)) { - fprintf (stderr, - "Cannot access MTD device %s: %s\n", - DEVNAME (1), strerror (errno)); - return -1; - } + if (HaveRedundEnv) { + rc = check_device_config(1); + if (rc < 0) + return rc; - if (HaveRedundEnv && ENVSIZE(0) != ENVSIZE(1)) { - ENVSIZE(0) = ENVSIZE(1) = min(ENVSIZE(0), ENVSIZE(1)); - fprintf(stderr, - "Redundant environments have inequal size, set to 0x%08lx\n", - ENVSIZE(1)); + if (ENVSIZE(0) != ENVSIZE(1)) { + ENVSIZE(0) = ENVSIZE(1) = min(ENVSIZE(0), ENVSIZE(1)); + fprintf(stderr, + "Redundant environments have inequal size, set to 0x%08lx\n", + ENVSIZE(1)); + } } usable_envsize = CUR_ENVSIZE - sizeof(uint32_t); @@ -1424,12 +1446,12 @@ static int get_config (char *fname) if (dump[0] == '#') continue; - rc = sscanf (dump, "%ms %lx %lx %lx %lx", - &devname, - &DEVOFFSET (i), - &ENVSIZE (i), - &DEVESIZE (i), - &ENVSECTORS (i)); + rc = sscanf(dump, "%ms %lli %lx %lx %lx", + &devname, + &DEVOFFSET(i), + &ENVSIZE(i), + &DEVESIZE(i), + &ENVSECTORS(i)); if (rc < 3) continue; diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config index 6f216f9..7916ebd 100644 --- a/tools/env/fw_env.config +++ b/tools/env/fw_env.config @@ -2,8 +2,9 @@ # Up to two entries are valid, in this case the redundant # environment sector is assumed present. # Notice, that the "Number of sectors" is not required on NOR and SPI-dataflash. -# Futhermore, if the Flash sector size is ommitted, this value is assumed to +# Futhermore, if the Flash sector size is omitted, this value is assumed to # be the same as the Environment size, which is valid for NOR and SPI-dataflash +# Device offset must be prefixed with 0x to be parsed as a hexadecimal value. # NOR example # MTD device name Device offset Env. size Flash sector size Number of sectors @@ -18,8 +19,12 @@ # NAND example #/dev/mtd0 0x4000 0x4000 0x20000 2 +# On a block device a negative offset is treated as a backwards offset from the +# end of the device/partition, rather than a forwards offset from the start. + # Block device example #/dev/mmcblk0 0xc0000 0x20000 +#/dev/mmcblk0 -0x20000 0x20000 # VFAT example #/boot/uboot.env 0x0000 0x4000 diff --git a/tools/env/fw_env.h b/tools/env/fw_env.h index dac964d..436eca9 100644 --- a/tools/env/fw_env.h +++ b/tools/env/fw_env.h @@ -67,12 +67,125 @@ struct env_opts { int parse_aes_key(char *key, uint8_t *bin_key); +/** + * fw_printenv() - print one or several environment variables + * + * @argc: number of variables names to be printed, prints all if 0 + * @argv: array of variable names to be printed, if argc != 0 + * @value_only: do not repeat the variable name, print the bare value, + * only one variable allowed with this option, argc must be 1 + * @opts: encryption key, configuration file, defaults are used if NULL + * + * Description: + * Uses fw_env_open, fw_getenv + * + * Return: + * 0 on success, -1 on failure (modifies errno) + */ int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts); -char *fw_getenv(char *name); + +/** + * fw_setenv() - adds or removes one variable to the environment + * + * @argc: number of strings in argv, argv[0] is variable name, + * argc==1 means erase variable, argc > 1 means add a variable + * @argv: argv[0] is variable name, argv[1..argc-1] are concatenated separated + * by single blank and set as the new value of the variable + * @opts: how to retrieve environment from flash, defaults are used if NULL + * + * Description: + * Uses fw_env_open, fw_env_write, fw_env_close + * + * Return: + * 0 on success, -1 on failure (modifies errno) + * + * ERRORS: + * EROFS - some variables ("ethaddr", "serial#") cannot be modified + */ int fw_setenv(int argc, char *argv[], struct env_opts *opts); + +/** + * fw_parse_script() - adds or removes multiple variables with a batch script + * + * @fname: batch script file name + * @opts: encryption key, configuration file, defaults are used if NULL + * + * Description: + * Uses fw_env_open, fw_env_write, fw_env_close + * + * Return: + * 0 success, -1 on failure (modifies errno) + * + * Script Syntax: + * + * key [ [space]+ value] + * + * lines starting with '#' treated as comment + * + * A variable without value will be deleted. Any number of spaces are allowed + * between key and value. The value starts with the first non-space character + * and ends with newline. No comments allowed on these lines. Spaces inside + * the value are preserved verbatim. + * + * Script Example: + * + * netdev eth0 + * + * kernel_addr 400000 + * + * foo spaces are copied verbatim + * + * # delete variable bar + * + * bar + */ int fw_parse_script(char *fname, struct env_opts *opts); + + +/** + * fw_env_open() - read enviroment from flash into RAM cache + * + * @opts: encryption key, configuration file, defaults are used if NULL + * + * Return: + * 0 on success, -1 on failure (modifies errno) + */ int fw_env_open(struct env_opts *opts); + +/** + * fw_getenv() - lookup variable in the RAM cache + * + * @name: variable to be searched + * Return: + * pointer to start of value, NULL if not found + */ +char *fw_getenv(char *name); + +/** + * fw_env_write() - modify a variable held in the RAM cache + * + * @name: variable + * @value: delete variable if NULL, otherwise create or overwrite the variable + * + * This is called in sequence to update the environment in RAM without updating + * the copy in flash after each set + * + * Return: + * 0 on success, -1 on failure (modifies errno) + * + * ERRORS: + * EROFS - some variables ("ethaddr", "serial#") cannot be modified + */ int fw_env_write(char *name, char *value); + +/** + * fw_env_close - write the environment from RAM cache back to flash + * + * @opts: encryption key, configuration file, defaults are used if NULL + * + * Return: + * 0 on success, -1 on failure (modifies errno) + */ int fw_env_close(struct env_opts *opts); unsigned long crc32(unsigned long, const unsigned char *, unsigned); diff --git a/tools/fit_image.c b/tools/fit_image.c index 58aa8e2..10fd6d4 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -195,7 +195,8 @@ static int fit_write_images(struct image_tool_params *params, char *fdt) fdt_begin_node(fdt, str); fdt_property_string(fdt, "description", params->imagename); fdt_property_string(fdt, "type", typename); - fdt_property_string(fdt, "arch", genimg_get_arch_name(params->arch)); + fdt_property_string(fdt, "arch", + genimg_get_arch_short_name(params->arch)); fdt_property_string(fdt, "os", genimg_get_os_short_name(params->os)); fdt_property_string(fdt, "compression", genimg_get_comp_short_name(params->comp)); @@ -650,8 +651,8 @@ static int fit_handle_file(struct image_tool_params *params) } if (ret) { - fprintf(stderr, "%s Can't add hashes to FIT blob\n", - params->cmdname); + fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n", + params->cmdname, ret); goto err_system; } diff --git a/tools/image-host.c b/tools/image-host.c index 7effb6c..1104695 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -38,7 +38,7 @@ static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, printf("Can't set hash '%s' property for '%s' node(%s)\n", FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), fdt_strerror(ret)); - return -1; + return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; } return 0; @@ -64,25 +64,27 @@ static int fit_image_process_hash(void *fit, const char *image_name, const char *node_name; int value_len; char *algo; + int ret; node_name = fit_get_name(fit, noffset, NULL); if (fit_image_hash_get_algo(fit, noffset, &algo)) { printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", node_name, image_name); - return -1; + return -ENOENT; } if (calculate_hash(data, size, algo, value, &value_len)) { printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", algo, node_name, image_name); - return -1; + return -EPROTONOSUPPORT; } - if (fit_set_hash_value(fit, noffset, value, value_len)) { + ret = fit_set_hash_value(fit, noffset, value, value_len); + if (ret) { printf("Can't set hash value for '%s' hash node in '%s' image node\n", node_name, image_name); - return -1; + return ret; } return 0; @@ -236,12 +238,18 @@ static int fit_image_process_sig(const char *keydir, void *keydest, /* Get keyname again, as FDT has changed and invalidated our pointer */ info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); - /* Write the public key into the supplied FDT file */ - if (keydest && info.algo->add_verify_data(&info, keydest)) { - printf("Failed to add verification data for '%s' signature node in '%s' image node\n", - node_name, image_name); + if (keydest) + ret = info.algo->add_verify_data(&info, keydest); + else return -1; - } + + /* + * Write the public key into the supplied FDT file; this might fail + * several times, since we try signing with successively increasing + * size values + */ + if (keydest && ret) + return ret; return 0; } @@ -322,7 +330,7 @@ int fit_image_add_verification_data(const char *keydir, void *keydest, comment, require_keys); } if (ret) - return -1; + return ret; } return 0; diff --git a/tools/mkimage.c b/tools/mkimage.c index ff3024a..d993958 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -25,45 +25,47 @@ static struct image_tool_params params = { .imagename2 = "", }; -static int h_compare_image_name(const void *vtype1, const void *vtype2) +static enum ih_category cur_category; + +static int h_compare_category_name(const void *vtype1, const void *vtype2) { const int *type1 = vtype1; const int *type2 = vtype2; - const char *name1 = genimg_get_type_short_name(*type1); - const char *name2 = genimg_get_type_short_name(*type2); + const char *name1 = genimg_get_cat_short_name(cur_category, *type1); + const char *name2 = genimg_get_cat_short_name(cur_category, *type2); return strcmp(name1, name2); } -/* Show all image types supported by mkimage */ -static void show_image_types(void) +static int show_valid_options(enum ih_category category) { - struct image_type_params *tparams; - int order[IH_TYPE_COUNT]; + int *order; int count; - int type; + int item; int i; + count = genimg_get_cat_count(category); + order = calloc(count, sizeof(*order)); + if (!order) + return -ENOMEM; + /* Sort the names in order of short name for easier reading */ - memset(order, '\0', sizeof(order)); - for (count = 0, type = 0; type < IH_TYPE_COUNT; type++) { - tparams = imagetool_get_type(type); - if (tparams) - order[count++] = type; - } - qsort(order, count, sizeof(int), h_compare_image_name); + for (item = 0; item < count; item++) + order[item] = item; + cur_category = category; + qsort(order, count, sizeof(int), h_compare_category_name); - fprintf(stderr, "\nInvalid image type. Supported image types:\n"); + fprintf(stderr, "\nInvalid %s, supported are:\n", + genimg_get_cat_desc(category)); for (i = 0; i < count; i++) { - type = order[i]; - tparams = imagetool_get_type(type); - if (tparams) { - fprintf(stderr, "\t%-15s %s\n", - genimg_get_type_short_name(type), - genimg_get_type_name(type)); - } + item = order[i]; + fprintf(stderr, "\t%-15s %s\n", + genimg_get_cat_short_name(category, item), + genimg_get_cat_name(category, item)); } fprintf(stderr, "\n"); + + return 0; } static void usage(const char *msg) @@ -150,8 +152,10 @@ static void process_args(int argc, char **argv) break; case 'A': params.arch = genimg_get_arch_id(optarg); - if (params.arch < 0) + if (params.arch < 0) { + show_valid_options(IH_ARCH); usage("Invalid architecture"); + } break; case 'b': if (add_content(IH_TYPE_FLATDT, optarg)) { @@ -166,8 +170,10 @@ static void process_args(int argc, char **argv) break; case 'C': params.comp = genimg_get_comp_id(optarg); - if (params.comp < 0) + if (params.comp < 0) { + show_valid_options(IH_COMP); usage("Invalid compression type"); + } break; case 'd': params.datafile = optarg; @@ -197,7 +203,6 @@ static void process_args(int argc, char **argv) * The flattened image tree (FIT) format * requires a flattened device tree image type */ - params.fit_image_type = params.type; params.type = IH_TYPE_FLATDT; params.fflag = 1; break; @@ -215,8 +220,10 @@ static void process_args(int argc, char **argv) break; case 'O': params.os = genimg_get_os_id(optarg); - if (params.os < 0) + if (params.os < 0) { + show_valid_options(IH_OS); usage("Invalid operating system"); + } break; case 'p': params.external_offset = strtoull(optarg, &ptr, 16); @@ -225,6 +232,7 @@ static void process_args(int argc, char **argv) params.cmdname, optarg); exit(EXIT_FAILURE); } + break; case 'q': params.quiet = 1; break; @@ -244,7 +252,7 @@ static void process_args(int argc, char **argv) case 'T': type = genimg_get_type_id(optarg); if (type < 0) { - show_image_types(); + show_valid_options(IH_TYPE); usage("Invalid image type"); } break; @@ -272,9 +280,12 @@ static void process_args(int argc, char **argv) * will always be IH_TYPE_FLATDT in this case). */ if (params.type == IH_TYPE_FLATDT) { - params.fit_image_type = type; + params.fit_image_type = type ? type : IH_TYPE_KERNEL; + /* For auto_its, datafile is always 'auto' */ if (!params.auto_its) params.datafile = datafile; + else if (!params.datafile) + usage("Missing data file for auto-FIT (use -d)"); } else if (type != IH_TYPE_INVALID) { params.type = type; } @@ -283,7 +294,6 @@ static void process_args(int argc, char **argv) usage("Missing output filename"); } - int main(int argc, char **argv) { int ifd = -1; diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py index 27d031e..69d5cfb 100644 --- a/tools/patman/patchstream.py +++ b/tools/patman/patchstream.py @@ -112,6 +112,14 @@ class PatchStream: if self.commit and self.is_log: self.series.AddCommit(self.commit) self.commit = None + # If 'END' is missing in a 'Cover-letter' section, and that section + # happens to show up at the very end of the commit message, this is + # the chance for us to fix it up. + if self.in_section == 'cover' and self.is_log: + self.series.cover = self.section + self.in_section = None + self.skip_blank = True + self.section = [] def ProcessLine(self, line): """Process a single line of a patch file or commit log @@ -150,6 +158,7 @@ class PatchStream: # Handle state transition and skipping blank lines series_tag_match = re_series_tag.match(line) commit_tag_match = re_commit_tag.match(line) + cover_match = re_cover.match(line) cover_cc_match = re_cover_cc.match(line) signoff_match = re_signoff.match(line) tag_match = None @@ -168,6 +177,33 @@ class PatchStream: elif commit_match: self.state = STATE_MSG_HEADER + # If a tag is detected, or a new commit starts + if series_tag_match or commit_tag_match or \ + cover_match or cover_cc_match or signoff_match or \ + self.state == STATE_MSG_HEADER: + # but we are already in a section, this means 'END' is missing + # for that section, fix it up. + if self.in_section: + self.warn.append("Missing 'END' in section '%s'" % self.in_section) + if self.in_section == 'cover': + self.series.cover = self.section + elif self.in_section == 'notes': + if self.is_log: + self.series.notes += self.section + elif self.in_section == 'commit-notes': + if self.is_log: + self.commit.notes += self.section + else: + self.warn.append("Unknown section '%s'" % self.in_section) + self.in_section = None + self.skip_blank = True + self.section = [] + # but we are already in a change list, that means a blank line + # is missing, fix it up. + if self.in_change: + self.warn.append("Missing 'blank line' in section 'Series-changes'") + self.in_change = 0 + # If we are in a section, keep collecting lines until we see END if self.in_section: if line == 'END': @@ -203,7 +239,7 @@ class PatchStream: self.skip_blank = False # Detect the start of a cover letter section - elif re_cover.match(line): + elif cover_match: self.in_section = 'cover' self.skip_blank = False diff --git a/tools/rkcommon.c b/tools/rkcommon.c index 72621fd..0a072aa 100644 --- a/tools/rkcommon.c +++ b/tools/rkcommon.c @@ -56,6 +56,7 @@ struct spl_info { static struct spl_info spl_infos[] = { { "rk3036", "RK30", 0x1000 }, { "rk3288", "RK32", 0x8000 }, + { "rk3399", "RK33", 0x20000 }, }; static unsigned char rc4_key[16] = { |