# Copyright (c) 2018 Foundries.io
#
# SPDX-License-Identifier: Apache-2.0

import abc
import argparse
import os
import pathlib
import pickle
import platform
import shutil
import subprocess
import sys

from west import manifest
from west.commands import Verbosity
from west.util import quote_sh_list

from build_helpers import find_build_dir, is_zephyr_build, \
    FIND_BUILD_DIR_DESCRIPTION
from runners.core import BuildConfiguration
from zcmake import CMakeCache
from zephyr_ext_common import Forceable, ZEPHYR_SCRIPTS

# This is needed to load edt.pickle files.
sys.path.insert(0, str(ZEPHYR_SCRIPTS / 'dts' / 'python-devicetree' / 'src'))

SIGN_DESCRIPTION = '''\
This command automates some of the drudgery of creating signed Zephyr
binaries for chain-loading by a bootloader.

In the simplest usage, run this from your build directory:

   west sign -t your_tool -- ARGS_FOR_YOUR_TOOL

The "ARGS_FOR_YOUR_TOOL" value can be any additional arguments you want to
pass to the tool, such as the location of a signing key etc. Depending on
which sort of ARGS_FOR_YOUR_TOOLS you use, the `--` separator/sentinel may
not always be required. To avoid ambiguity and having to find and
understand POSIX 12.2 Guideline 10, always use `--`.

See tool-specific help below for details.'''

SIGN_EPILOG = '''\
imgtool
-------

To build a signed binary you can load with MCUboot using imgtool,
run this from your build directory:

   west sign -t imgtool -- --key YOUR_SIGNING_KEY.pem

For this to work, either imgtool must be installed (e.g. using pip3),
or you must pass the path to imgtool.py using the -p option.

Assuming your binary was properly built for processing and handling by
imgtool, this creates zephyr.signed.bin and zephyr.signed.hex
files which are ready for use by your bootloader.

The version number, image header size, alignment, and slot sizes are
determined from the build directory using .config and the device tree.
As shown above, extra arguments after a '--' are passed to imgtool
directly.

rimage
------

To create a signed binary with the rimage tool, run this from your build
directory:

   west sign -t rimage -- -k YOUR_SIGNING_KEY.pem

For this to work, either rimage must be installed or you must pass
the path to rimage using the -p option.

You can also pass additional arguments to rimage thanks to [sign] and
[rimage] sections in your west config file(s); this is especially useful
when invoking west sign _indirectly_ through CMake/ninja. See how at
https://docs.zephyrproject.org/latest/develop/west/sign.html
'''

class ToggleAction(argparse.Action):

    def __call__(self, parser, args, ignored, option):
        setattr(args, self.dest, not option.startswith('--no-'))


class Sign(Forceable):
    def __init__(self):
        super(Sign, self).__init__(
            'sign',
            # Keep this in sync with the string in west-commands.yml.
            'sign a Zephyr binary for bootloader chain-loading',
            SIGN_DESCRIPTION,
            accepts_unknown_args=False)

    def do_add_parser(self, parser_adder):
        parser = parser_adder.add_parser(
            self.name,
            epilog=SIGN_EPILOG,
            help=self.help,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description=self.description)

        parser.add_argument('-d', '--build-dir',
                            help=FIND_BUILD_DIR_DESCRIPTION)
        parser.add_argument('-q', '--quiet', action='store_true',
                            help='suppress non-error output')
        self.add_force_arg(parser)

        # general options
        group = parser.add_argument_group('tool control options')
        group.add_argument('-t', '--tool', choices=['imgtool', 'rimage'],
                           help='''image signing tool name; imgtool and rimage
                           are currently supported (imgtool is deprecated)''')
        group.add_argument('-p', '--tool-path', default=None,
                           help='''path to the tool itself, if needed''')
        group.add_argument('-D', '--tool-data', default=None,
                           help='''path to a tool-specific data/configuration directory, if needed''')
        group.add_argument('--if-tool-available', action='store_true',
                           help='''Do not fail if the rimage tool is not found or the rimage signing
schema (rimage "target") is not defined in board.cmake.''')
        group.add_argument('tool_args', nargs='*', metavar='tool_opt',
                           help='extra option(s) to pass to the signing tool')

        # bin file options
        group = parser.add_argument_group('binary (.bin) file options')
        group.add_argument('--bin', '--no-bin', dest='gen_bin', nargs=0,
                           action=ToggleAction,
                           help='''produce a signed .bin file?
                           (default: yes, if supported and unsigned bin
                           exists)''')
        group.add_argument('-B', '--sbin', metavar='BIN',
                           help='''signed .bin file name
                           (default: zephyr.signed.bin in the build
                           directory, next to zephyr.bin)''')

        # hex file options
        group = parser.add_argument_group('Intel HEX (.hex) file options')
        group.add_argument('--hex', '--no-hex', dest='gen_hex', nargs=0,
                           action=ToggleAction,
                           help='''produce a signed .hex file?
                           (default: yes, if supported and unsigned hex
                           exists)''')
        group.add_argument('-H', '--shex', metavar='HEX',
                           help='''signed .hex file name
                           (default: zephyr.signed.hex in the build
                           directory, next to zephyr.hex)''')

        return parser

    def do_run(self, args, ignored):
        self.args = args        # for check_force

        # Find the build directory and parse .config and DT.
        build_dir = find_build_dir(args.build_dir)
        self.check_force(os.path.isdir(build_dir),
                         'no such build directory {}'.format(build_dir))
        self.check_force(is_zephyr_build(build_dir),
                         "build directory {} doesn't look like a Zephyr build "
                         'directory'.format(build_dir))
        build_conf = BuildConfiguration(build_dir)

        if not args.tool:
            args.tool = self.config_get('sign.tool')

        # Decide on output formats.
        formats = []
        bin_exists = build_conf.getboolean('CONFIG_BUILD_OUTPUT_BIN')
        if args.gen_bin:
            self.check_force(bin_exists,
                             '--bin given but CONFIG_BUILD_OUTPUT_BIN not set '
                             "in build directory's ({}) .config".
                             format(build_dir))
            formats.append('bin')
        elif args.gen_bin is None and bin_exists:
            formats.append('bin')

        hex_exists = build_conf.getboolean('CONFIG_BUILD_OUTPUT_HEX')
        if args.gen_hex:
            self.check_force(hex_exists,
                             '--hex given but CONFIG_BUILD_OUTPUT_HEX not set '
                             "in build directory's ({}) .config".
                             format(build_dir))
            formats.append('hex')
        elif args.gen_hex is None and hex_exists:
            formats.append('hex')

        # Delegate to the signer.
        if args.tool == 'imgtool':
            if args.if_tool_available:
                self.die('imgtool does not support --if-tool-available')
            signer = ImgtoolSigner()
        elif args.tool == 'rimage':
            signer = RimageSigner()
        # (Add support for other signers here in elif blocks)
        else:
            if args.tool is None:
                self.die('one --tool is required')
            else:
                self.die(f'invalid tool: {args.tool}')

        signer.sign(self, build_dir, build_conf, formats)


class Signer(abc.ABC):
    '''Common abstract superclass for signers.

    To add support for a new tool, subclass this and add support for
    it in the Sign.do_run() method.'''

    @abc.abstractmethod
    def sign(self, command, build_dir, build_conf, formats):
        '''Abstract method to perform a signature; subclasses must implement.

        :param command: the Sign instance
        :param build_dir: the build directory
        :param build_conf: BuildConfiguration for build directory
        :param formats: list of formats to generate ('bin', 'hex')
        '''


class ImgtoolSigner(Signer):

    def sign(self, command, build_dir, build_conf, formats):
        if not formats:
            return

        args = command.args
        b = pathlib.Path(build_dir)

        command.wrn("west sign using imgtool is deprecated and will be removed in a future release")

        imgtool = self.find_imgtool(command, args)
        # The vector table offset and application version are set in Kconfig:
        appver = self.get_cfg(command, build_conf, 'CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION')
        vtoff = self.get_cfg(command, build_conf, 'CONFIG_ROM_START_OFFSET')
        # Flash device write alignment and the partition's slot size
        # come from devicetree:
        flash = self.edt_flash_node(command, b, args.quiet)
        align, addr, size = self.edt_flash_params(command, flash)

        if not build_conf.getboolean('CONFIG_BOOTLOADER_MCUBOOT'):
            command.wrn("CONFIG_BOOTLOADER_MCUBOOT is not set to y in "
                        f"{build_conf.path}; this probably won't work")

        kernel = build_conf.get('CONFIG_KERNEL_BIN_NAME', 'zephyr')

        if 'bin' in formats:
            in_bin = b / 'zephyr' / f'{kernel}.bin'
            if not in_bin.is_file():
                command.die(f"no unsigned .bin found at {in_bin}")
            in_bin = os.fspath(in_bin)
        else:
            in_bin = None
        if 'hex' in formats:
            in_hex = b / 'zephyr' / f'{kernel}.hex'
            if not in_hex.is_file():
                command.die(f"no unsigned .hex found at {in_hex}")
            in_hex = os.fspath(in_hex)
        else:
            in_hex = None

        if not args.quiet:
            command.banner('image configuration:')
            command.inf('partition offset: {0} (0x{0:x})'.format(addr))
            command.inf('partition size: {0} (0x{0:x})'.format(size))
            command.inf('rom start offset: {0} (0x{0:x})'.format(vtoff))

        # Base sign command.
        sign_base = imgtool + ['sign',
                               '--version', str(appver),
                               '--align', str(align),
                               '--header-size', str(vtoff),
                               '--slot-size', str(size)]
        sign_base.extend(args.tool_args)

        if not args.quiet:
            command.banner('signing binaries')
        if in_bin:
            out_bin = args.sbin or str(b / 'zephyr' / 'zephyr.signed.bin')
            sign_bin = sign_base + [in_bin, out_bin]
            if not args.quiet:
                command.inf(f'unsigned bin: {in_bin}')
                command.inf(f'signed bin:   {out_bin}')
                command.dbg(quote_sh_list(sign_bin))
            subprocess.check_call(sign_bin, stdout=subprocess.PIPE if args.quiet else None)
        if in_hex:
            out_hex = args.shex or str(b / 'zephyr' / 'zephyr.signed.hex')
            sign_hex = sign_base + [in_hex, out_hex]
            if not args.quiet:
                command.inf(f'unsigned hex: {in_hex}')
                command.inf(f'signed hex:   {out_hex}')
                command.dbg(quote_sh_list(sign_hex))
            subprocess.check_call(sign_hex, stdout=subprocess.PIPE if args.quiet else None)

    @staticmethod
    def find_imgtool(cmd, args):
        if args.tool_path:
            imgtool = args.tool_path
            if not os.path.isfile(imgtool):
                cmd.die(f'--tool-path {imgtool}: no such file')
        else:
            imgtool = shutil.which('imgtool') or shutil.which('imgtool.py')
            if not imgtool:
                cmd.die('imgtool not found; either install it',
                        '(e.g. "pip3 install imgtool") or provide --tool-path')

        if platform.system() == 'Windows' and imgtool.endswith('.py'):
            # Windows users may not be able to run .py files
            # as executables in subprocesses, regardless of
            # what the mode says. Always run imgtool as
            # 'python path/to/imgtool.py' instead of
            # 'path/to/imgtool.py' in these cases.
            # https://github.com/zephyrproject-rtos/zephyr/issues/31876
            return [sys.executable, imgtool]

        return [imgtool]

    @staticmethod
    def get_cfg(command, build_conf, item):
        try:
            return build_conf[item]
        except KeyError:
            command.check_force(
                False, "build .config is missing a {} value".format(item))
            return None

    @staticmethod
    def edt_flash_node(cmd, b, quiet=False):
        # Get the EDT Node corresponding to the zephyr,flash chosen DT
        # node; 'b' is the build directory as a pathlib object.

        # Ensure the build directory has a compiled DTS file
        # where we expect it to be.
        dts = b / 'zephyr' / 'zephyr.dts'
        if not quiet:
            cmd.dbg('DTS file:', dts, level=Verbosity.DBG_MORE)
        edt_pickle = b / 'zephyr' / 'edt.pickle'
        if not edt_pickle.is_file():
            cmd.die("can't load devicetree; expected to find:", edt_pickle)

        # Load the devicetree.
        with open(edt_pickle, 'rb') as f:
            edt = pickle.load(f)

        # By convention, the zephyr,flash chosen node contains the
        # partition information about the zephyr image to sign.
        flash = edt.chosen_node('zephyr,flash')
        if not flash:
            cmd.die('devicetree has no chosen zephyr,flash node;',
                    "can't infer flash write block or slot0_partition slot sizes")

        return flash

    @staticmethod
    def edt_flash_params(cmd, flash):
        # Get the flash device's write alignment and offset from the
        # slot0_partition and the size from slot1_partition , out of the
        # build directory's devicetree. slot1_partition size is used,
        # when available, because in swap-move mode it can be one sector
        # smaller. When not available, fallback to slot0_partition (single slot dfu).

        # The node must have a "partitions" child node, which in turn
        # must have child nodes with label slot0_partition and may have a child node
        # with label slot1_partition. By convention, the slots for consumption by
        # imgtool are linked into these partitions.
        if 'partitions' not in flash.children:
            cmd.die("DT zephyr,flash chosen node has no partitions,",
                    "can't find partitions for MCUboot slots")

        partitions = flash.children['partitions']
        slots = {
            label: node for node in partitions.children.values()
                        for label in node.labels
                        if label in set(['slot0_partition', 'slot1_partition'])
        }

        if 'slot0_partition' not in slots:
            cmd.die("DT zephyr,flash chosen node has no slot0_partition partition,",
                    "can't determine its address")

        # Die on missing or zero alignment or slot_size.
        if "write-block-size" not in flash.props:
            cmd.die('DT zephyr,flash node has no write-block-size;',
                    "can't determine imgtool write alignment")
        align = flash.props['write-block-size'].val
        if align == 0:
            cmd.die('expected nonzero flash alignment, but got '
                    'DT flash device write-block-size {}'.format(align))

        # The partitions node, and its subnode, must provide
        # the size of slot1_partition or slot0_partition partition via the regs property.
        slot_key = 'slot1_partition' if 'slot1_partition' in slots else 'slot0_partition'
        if not slots[slot_key].regs:
            cmd.die(f'{slot_key} flash partition has no regs property;',
                    "can't determine size of slot")

        # always use addr of slot0_partition, which is where slots are run
        addr = slots['slot0_partition'].regs[0].addr

        size = slots[slot_key].regs[0].size
        if size == 0:
            cmd.die('expected nonzero slot size for {}'.format(slot_key))

        return (align, addr, size)

class RimageSigner(Signer):

    def rimage_config_dir(self):
        'Returns the rimage/config/ directory with the highest precedence'
        args = self.command.args
        if args.tool_data:
            conf_dir = pathlib.Path(args.tool_data)
        elif self.cmake_cache.get('RIMAGE_CONFIG_PATH'):
            conf_dir = pathlib.Path(self.cmake_cache['RIMAGE_CONFIG_PATH'])
        else:
            conf_dir = self.sof_src_dir / 'tools' / 'rimage' / 'config'
        self.command.dbg(f'rimage config directory={conf_dir}')
        return conf_dir

    def preprocess_toml(self, config_dir, toml_basename, subdir):
        'Runs the C pre-processor on config_dir/toml_basename.h'

        compiler_path = self.cmake_cache.get("CMAKE_C_COMPILER")
        preproc_cmd = [compiler_path, '-E', str(config_dir / (toml_basename + '.h'))]
        # -P removes line markers to keep the .toml output reproducible.  To
        # trace #includes, temporarily comment out '-P' (-f*-prefix-map
        # unfortunately don't seem to make any difference here and they're
        # gcc-specific)
        preproc_cmd += ['-P']

        # "REM" escapes _leading_ '#' characters from cpp and allows
        # such comments to be preserved in generated/*.toml files:
        #
        #      REM # my comment...
        #
        # Note _trailing_ '#' characters and comments are ignored by cpp
        # and don't need any REM trick.
        preproc_cmd += ['-DREM=']

        preproc_cmd += ['-I', str(self.sof_src_dir / 'src')]
        preproc_cmd += ['-imacros',
                        str(pathlib.Path('zephyr') / 'include' / 'generated' / 'zephyr' / 'autoconf.h')]
        preproc_cmd += ['-o', str(subdir / 'rimage_config.toml')]
        self.command.inf(quote_sh_list(preproc_cmd))
        subprocess.run(preproc_cmd, check=True, cwd=self.build_dir)

    def sign(self, command, build_dir, build_conf, formats):
        self.command = command
        args = command.args

        b = pathlib.Path(build_dir)
        self.build_dir = b
        cache = CMakeCache.from_build_dir(build_dir)
        self.cmake_cache = cache

        # Warning: RIMAGE_TARGET in Zephyr is a duplicate of
        # CONFIG_RIMAGE_SIGNING_SCHEMA in SOF.
        target = cache.get('RIMAGE_TARGET')

        if not target:
            msg = 'rimage target not defined in board.cmake'
            if args.if_tool_available:
                command.inf(msg)
                sys.exit(0)
            else:
                command.die(msg)

        kernel_name = build_conf.get('CONFIG_KERNEL_BIN_NAME', 'zephyr')

        # TODO: make this a new sign.py --bootloader option.
        if target in ('imx8', 'imx8m', 'imx8ulp', 'imx95', 'rmb'):
            bootloader = None
            kernel = str(b / 'zephyr' / f'{kernel_name}.elf')
            out_bin = str(b / 'zephyr' / f'{kernel_name}.ri')
            out_xman = str(b / 'zephyr' / f'{kernel_name}.ri.xman')
            out_tmp = str(b / 'zephyr' / f'{kernel_name}.rix')
        else:
            bootloader = str(b / 'zephyr' / 'boot.mod')
            kernel = str(b / 'zephyr' / 'main.mod')
            out_bin = str(b / 'zephyr' / f'{kernel_name}.ri')
            out_xman = str(b / 'zephyr' / f'{kernel_name}.ri.xman')
            out_tmp = str(b / 'zephyr' / f'{kernel_name}.rix')

        # Clean any stale output. This is especially important when using --if-tool-available
        # (but not just)
        for o in [ out_bin, out_xman, out_tmp ]:
            pathlib.Path(o).unlink(missing_ok=True)

        tool_path = (
            args.tool_path if args.tool_path else
            command.config_get('rimage.path', None)
        )
        err_prefix = '--tool-path' if args.tool_path else 'west config'

        if tool_path:
            command.check_force(shutil.which(tool_path),
                                f'{err_prefix} {tool_path}: not an executable')
        else:
            tool_path = shutil.which('rimage')
            if not tool_path:
                err_msg = 'rimage not found; either install it or provide --tool-path'
                if args.if_tool_available:
                    command.wrn(err_msg)
                    command.wrn('zephyr binary _not_ signed!')
                    return
                else:
                    command.die(err_msg)

        #### -c sof/rimage/config/signing_schema.toml  ####

        if not args.quiet:
            command.inf('Signing with tool {}'.format(tool_path))

        try:
            sof_proj = command.manifest.get_projects(['sof'], allow_paths=False)
            sof_src_dir = pathlib.Path(sof_proj[0].abspath)
        except ValueError: # sof is the manifest
            sof_src_dir = pathlib.Path(manifest.manifest_path()).parent

        self.sof_src_dir = sof_src_dir


        command.inf('Signing for SOC target ' + target)

        # FIXME: deprecate --no-manifest and replace it with a much
        # simpler and more direct `-- -e` which the user can _already_
        # pass today! With unclear consequences right now...
        if '--no-manifest' in args.tool_args:
            no_manifest = True
            args.tool_args.remove('--no-manifest')
        else:
            no_manifest = False

        # Non-SOF build does not have extended manifest data for
        # rimage to process, which might result in rimage error.
        # So skip it when not doing SOF builds.
        is_sof_build = build_conf.getboolean('CONFIG_SOF')
        if not is_sof_build:
            no_manifest = True

        if no_manifest:
            extra_ri_args = [ ]
        else:
            extra_ri_args = ['-e']

        sign_base = [tool_path]

        # Align rimage verbosity.
        # Sub-command arg 'west sign -q' takes precedence over west '-v'
        if not args.quiet and args.verbose:
            sign_base += ['-v'] * args.verbose

        components = [ ] if bootloader is None else [ bootloader ]
        components += [ kernel ]

        sign_config_extra_args = command.config_get_words('rimage.extra-args', [])

        if '-k' not in sign_config_extra_args + args.tool_args:
            # rimage requires a key argument even when it does not sign
            cmake_default_key = cache.get('RIMAGE_SIGN_KEY', 'key placeholder from sign.py')
            extra_ri_args += [ '-k', str(sof_src_dir / 'keys' / cmake_default_key) ]

        if args.tool_data and '-c' in args.tool_args:
            command.wrn('--tool-data ' + args.tool_data + ' ignored! Overridden by: -- -c ... ')

        if '-c' not in sign_config_extra_args + args.tool_args:
            conf_dir = self.rimage_config_dir()
            toml_basename = target + '.toml'
            if ((conf_dir / toml_basename).exists() and
               (conf_dir / (toml_basename + '.h')).exists()):
                command.die(f"Cannot have both {toml_basename + '.h'} and {toml_basename} in {conf_dir}")

            if (conf_dir / (toml_basename + '.h')).exists():
                generated_subdir = pathlib.Path('zephyr') / 'misc' / 'generated'
                self.preprocess_toml(conf_dir, toml_basename, generated_subdir)
                extra_ri_args += ['-c', str(b / generated_subdir / 'rimage_config.toml')]
            else:
                toml_dir = conf_dir
                extra_ri_args += ['-c', str(toml_dir / toml_basename)]

        # Warning: while not officially supported (yet?), the rimage --option that is last
        # on the command line currently wins in case of duplicate options. So pay
        # attention to the _args order below.
        sign_base += (['-o', out_bin] + sign_config_extra_args +
                      extra_ri_args + args.tool_args + components)

        command.inf(quote_sh_list(sign_base))
        subprocess.check_call(sign_base)

        if no_manifest:
            filenames = [out_bin]
        else:
            filenames = [out_xman, out_bin]
            if not args.quiet:
                command.inf('Prefixing ' + out_bin + ' with manifest ' + out_xman)
        with open(out_tmp, 'wb') as outfile:
            for fname in filenames:
                with open(fname, 'rb') as infile:
                    outfile.write(infile.read())

        os.remove(out_bin)
        os.rename(out_tmp, out_bin)
