# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# Class for an image, the output of binman
#

from collections import OrderedDict
import fnmatch
from operator import attrgetter
import os
import re
import sys

from binman.entry import Entry
from binman.etype import fdtmap
from binman.etype import image_header
from binman.etype import section
from dtoc import fdt
from dtoc import fdt_util
from patman import tools
from patman import tout

class Image(section.Entry_section):
    """A Image, representing an output from binman

    An image is comprised of a collection of entries each containing binary
    data. The image size must be large enough to hold all of this data.

    This class implements the various operations needed for images.

    Attributes:
        filename: Output filename for image
        image_node: Name of node containing the description for this image
        fdtmap_dtb: Fdt object for the fdtmap when loading from a file
        fdtmap_data: Contents of the fdtmap when loading from a file
        allow_repack: True to add properties to allow the image to be safely
            repacked later
        test_section_timeout: Use a zero timeout for section multi-threading
            (for testing)

    Args:
        copy_to_orig: Copy offset/size to orig_offset/orig_size after reading
            from the device tree
        test: True if this is being called from a test of Images. This this case
            there is no device tree defining the structure of the section, so
            we create a section manually.
        ignore_missing: Ignore any missing entry arguments (i.e. don't raise an
            exception). This should be used if the Image is being loaded from
            a file rather than generated. In that case we obviously don't need
            the entry arguments since the contents already exists.
        use_expanded: True if we are updating the FDT wth entry offsets, etc.
            and should use the expanded versions of the U-Boot entries.
            Any entry type that includes a devicetree must put it in a
            separate entry so that it will be updated. For example. 'u-boot'
            normally just picks up 'u-boot.bin' which includes the
            devicetree, but this is not updateable, since it comes into
            binman as one piece and binman doesn't know that it is actually
            an executable followed by a devicetree. Of course it could be
            taught this, but then when reading an image (e.g. 'binman ls')
            it may need to be able to split the devicetree out of the image
            in order to determine the location of things. Instead we choose
            to ignore 'u-boot-bin' in this case, and build it ourselves in
            binman with 'u-boot-dtb.bin' and 'u-boot.dtb'. See
            Entry_u_boot_expanded and Entry_blob_phase for details.
        missing_etype: Use a default entry type ('blob') if the requested one
            does not exist in binman. This is useful if an image was created by
            binman a newer version of binman but we want to list it in an older
            version which does not support all the entry types.
        generate: If true, generator nodes are processed. If false they are
            ignored which is useful when an existing image is read back from a
            file.
    """
    def __init__(self, name, node, copy_to_orig=True, test=False,
                 ignore_missing=False, use_expanded=False, missing_etype=False,
                 generate=True):
        super().__init__(None, 'section', node, test=test)
        self.copy_to_orig = copy_to_orig
        self.name = 'main-section'
        self.image_name = name
        self._filename = '%s.bin' % self.image_name
        self.fdtmap_dtb = None
        self.fdtmap_data = None
        self.allow_repack = False
        self._ignore_missing = ignore_missing
        self.missing_etype = missing_etype
        self.use_expanded = use_expanded
        self.test_section_timeout = False
        self.bintools = {}
        self.generate = generate
        if not test:
            self.ReadNode()

    def ReadNode(self):
        super().ReadNode()
        filename = fdt_util.GetString(self._node, 'filename')
        if filename:
            self._filename = filename
        self.allow_repack = fdt_util.GetBool(self._node, 'allow-repack')

    @classmethod
    def FromFile(cls, fname):
        """Convert an image file into an Image for use in binman

        Args:
            fname: Filename of image file to read

        Returns:
            Image object on success

        Raises:
            ValueError if something goes wrong
        """
        data = tools.read_file(fname)
        size = len(data)

        # First look for an image header
        pos = image_header.LocateHeaderOffset(data)
        if pos is None:
            # Look for the FDT map
            pos = fdtmap.LocateFdtmap(data)
        if pos is None:
            raise ValueError('Cannot find FDT map in image')

        # We don't know the FDT size, so check its header first
        probe_dtb = fdt.Fdt.FromData(
            data[pos + fdtmap.FDTMAP_HDR_LEN:pos + 256])
        dtb_size = probe_dtb.GetFdtObj().totalsize()
        fdtmap_data = data[pos:pos + dtb_size + fdtmap.FDTMAP_HDR_LEN]
        fdt_data = fdtmap_data[fdtmap.FDTMAP_HDR_LEN:]
        out_fname = tools.get_output_filename('fdtmap.in.dtb')
        tools.write_file(out_fname, fdt_data)
        dtb = fdt.Fdt(out_fname)
        dtb.Scan()

        # Return an Image with the associated nodes
        root = dtb.GetRoot()
        image = Image('image', root, copy_to_orig=False, ignore_missing=True,
                      missing_etype=True, generate=False)

        image.image_node = fdt_util.GetString(root, 'image-node', 'image')
        image.fdtmap_dtb = dtb
        image.fdtmap_data = fdtmap_data
        image._data = data
        image._filename = fname
        image.image_name, _ = os.path.splitext(fname)
        return image

    def Raise(self, msg):
        """Convenience function to raise an error referencing an image"""
        raise ValueError("Image '%s': %s" % (self._node.path, msg))

    def PackEntries(self):
        """Pack all entries into the image"""
        super().Pack(0)

    def SetImagePos(self):
        # This first section in the image so it starts at 0
        super().SetImagePos(0)

    def ProcessEntryContents(self):
        """Call the ProcessContents() method for each entry

        This is intended to adjust the contents as needed by the entry type.

        Returns:
            True if the new data size is OK, False if expansion is needed
        """
        return super().ProcessContents()

    def WriteSymbols(self):
        """Write symbol values into binary files for access at run time"""
        super().WriteSymbols(self)

    def BuildImage(self):
        """Write the image to a file"""
        fname = tools.get_output_filename(self._filename)
        tout.info("Writing image to '%s'" % fname)
        with open(fname, 'wb') as fd:
            data = self.GetPaddedData()
            fd.write(data)
        tout.info("Wrote %#x bytes" % len(data))

    def WriteMap(self):
        """Write a map of the image to a .map file

        Returns:
            Filename of map file written
        """
        filename = '%s.map' % self.image_name
        fname = tools.get_output_filename(filename)
        with open(fname, 'w') as fd:
            print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
                  file=fd)
            super().WriteMap(fd, 0)
        return fname

    def BuildEntryList(self):
        """List the files in an image

        Returns:
            List of entry.EntryInfo objects describing all entries in the image
        """
        entries = []
        self.ListEntries(entries, 0)
        return entries

    def FindEntryPath(self, entry_path):
        """Find an entry at a given path in the image

        Args:
            entry_path: Path to entry (e.g. /ro-section/u-boot')

        Returns:
            Entry object corresponding to that past

        Raises:
            ValueError if no entry found
        """
        parts = entry_path.split('/')
        entries = self.GetEntries()
        parent = '/'
        for part in parts:
            entry = entries.get(part)
            if not entry:
                raise ValueError("Entry '%s' not found in '%s'" %
                                 (part, parent))
            parent = entry.GetPath()
            entries = entry.GetEntries()
        return entry

    def ReadData(self, decomp=True, alt_format=None):
        tout.debug("Image '%s' ReadData(), size=%#x" %
                   (self.GetPath(), len(self._data)))
        return self._data

    def GetListEntries(self, entry_paths):
        """List the entries in an image

        This decodes the supplied image and returns a list of entries from that
        image, preceded by a header.

        Args:
            entry_paths: List of paths to match (each can have wildcards). Only
                entries whose names match one of these paths will be printed

        Returns:
            String error message if something went wrong, otherwise
            3-Tuple:
                List of EntryInfo objects
                List of lines, each
                    List of text columns, each a string
                List of widths of each column
        """
        def _EntryToStrings(entry):
            """Convert an entry to a list of strings, one for each column

            Args:
                entry: EntryInfo object containing information to output

            Returns:
                List of strings, one for each field in entry
            """
            def _AppendHex(val):
                """Append a hex value, or an empty string if val is None

                Args:
                    val: Integer value, or None if none
                """
                args.append('' if val is None else '>%x' % val)

            args = ['  ' * entry.indent + entry.name]
            _AppendHex(entry.image_pos)
            _AppendHex(entry.size)
            args.append(entry.etype)
            _AppendHex(entry.offset)
            _AppendHex(entry.uncomp_size)
            return args

        def _DoLine(lines, line):
            """Add a line to the output list

            This adds a line (a list of columns) to the output list. It also updates
            the widths[] array with the maximum width of each column

            Args:
                lines: List of lines to add to
                line: List of strings, one for each column
            """
            for i, item in enumerate(line):
                widths[i] = max(widths[i], len(item))
            lines.append(line)

        def _NameInPaths(fname, entry_paths):
            """Check if a filename is in a list of wildcarded paths

            Args:
                fname: Filename to check
                entry_paths: List of wildcarded paths (e.g. ['*dtb*', 'u-boot*',
                                                             'section/u-boot'])

            Returns:
                True if any wildcard matches the filename (using Unix filename
                    pattern matching, not regular expressions)
                False if not
            """
            for path in entry_paths:
                if fnmatch.fnmatch(fname, path):
                    return True
            return False

        entries = self.BuildEntryList()

        # This is our list of lines. Each item in the list is a list of strings, one
        # for each column
        lines = []
        HEADER = ['Name', 'Image-pos', 'Size', 'Entry-type', 'Offset',
                  'Uncomp-size']
        num_columns = len(HEADER)

        # This records the width of each column, calculated as the maximum width of
        # all the strings in that column
        widths = [0] * num_columns
        _DoLine(lines, HEADER)

        # We won't print anything unless it has at least this indent. So at the
        # start we will print nothing, unless a path matches (or there are no
        # entry paths)
        MAX_INDENT = 100
        min_indent = MAX_INDENT
        path_stack = []
        path = ''
        indent = 0
        selected_entries = []
        for entry in entries:
            if entry.indent > indent:
                path_stack.append(path)
            elif entry.indent < indent:
                path_stack.pop()
            if path_stack:
                path = path_stack[-1] + '/' + entry.name
            indent = entry.indent

            # If there are entry paths to match and we are not looking at a
            # sub-entry of a previously matched entry, we need to check the path
            if entry_paths and indent <= min_indent:
                if _NameInPaths(path[1:], entry_paths):
                    # Print this entry and all sub-entries (=higher indent)
                    min_indent = indent
                else:
                    # Don't print this entry, nor any following entries until we get
                    # a path match
                    min_indent = MAX_INDENT
                    continue
            _DoLine(lines, _EntryToStrings(entry))
            selected_entries.append(entry)
        return selected_entries, lines, widths

    def LookupImageSymbol(self, sym_name, optional, msg, base_addr):
        """Look up a symbol in an ELF file

        Looks up a symbol in an ELF file. Only entry types which come from an
        ELF image can be used by this function.

        This searches through this image including all of its subsections.

        At present the only entry properties supported are:
            offset
            image_pos - 'base_addr' is added if this is not an end-at-4gb image
            size

        Args:
            sym_name: Symbol name in the ELF file to look up in the format
                _binman_<entry>_prop_<property> where <entry> is the name of
                the entry and <property> is the property to find (e.g.
                _binman_u_boot_prop_offset). As a special case, you can append
                _any to <entry> to have it search for any matching entry. E.g.
                _binman_u_boot_any_prop_offset will match entries called u-boot,
                u-boot-img and u-boot-nodtb)
            optional: True if the symbol is optional. If False this function
                will raise if the symbol is not found
            msg: Message to display if an error occurs
            base_addr: Base address of image. This is added to the returned
                image_pos in most cases so that the returned position indicates
                where the targeted entry/binary has actually been loaded. But
                if end-at-4gb is used, this is not done, since the binary is
                already assumed to be linked to the ROM position and using
                execute-in-place (XIP).

        Returns:
            Value that should be assigned to that symbol, or None if it was
                optional and not found

        Raises:
            ValueError if the symbol is invalid or not found, or references a
                property which is not supported
        """
        entries = OrderedDict()
        entries_by_name = {}
        self._CollectEntries(entries, entries_by_name, self)
        return self.LookupSymbol(sym_name, optional, msg, base_addr,
                                 entries_by_name)

    def CollectBintools(self):
        """Collect all the bintools used by this image

        Returns:
            Dict of bintools:
                key: name of tool
                value: Bintool object
        """
        bintools = {}
        super().AddBintools(bintools)
        self.bintools = bintools
        return bintools
