コード例 #1
0
    def sign(self, command, build_dir, bcfg, formats):
        if not formats:
            return

        args = command.args
        b = pathlib.Path(build_dir)
        cache = CMakeCache.from_build_dir(build_dir)

        tool_path = self.find_imgtool(command, args)
        # The vector table offset is set in Kconfig:
        vtoff = self.get_cfg(command, bcfg, 'CONFIG_TEXT_SECTION_OFFSET')
        # Flash device write alignment and the partition's slot size
        # come from devicetree:
        flash = self.edt_flash_node(b, cache)
        align, addr, size = self.edt_flash_params(flash)

        runner_config = cached_runner_config(build_dir, cache)
        if 'bin' in formats:
            in_bin = runner_config.bin_file
            if not in_bin:
                log.die("can't find unsigned .bin to sign")
        else:
            in_bin = None
        if 'hex' in formats:
            in_hex = runner_config.hex_file
            if not in_hex:
                log.die("can't find unsigned .hex to sign")
        else:
            in_hex = None

        log.banner('image configuration:')
        log.inf('partition offset: {0} (0x{0:x})'.format(addr))
        log.inf('partition size: {0} (0x{0:x})'.format(size))
        log.inf('text section offset: {0} (0x{0:x})'.format(vtoff))

        # Base sign command.
        #
        # We provide a default --version in case the user is just
        # messing around and doesn't want to set one. It will be
        # overridden if there is a --version in args.tool_args.
        sign_base = [tool_path, 'sign',
                     '--version', '0.0.0+0',
                     '--align', str(align),
                     '--header-size', str(vtoff),
                     '--slot-size', str(size)]
        sign_base.extend(args.tool_args)

        log.banner('signed binaries:')
        if in_bin:
            out_bin = args.sbin or str(b / 'zephyr' / 'zephyr.signed.bin')
            sign_bin = sign_base + [in_bin, out_bin]
            log.inf('bin: {}'.format(out_bin))
            log.dbg(quote_sh_list(sign_bin))
            subprocess.check_call(sign_bin)
        if in_hex:
            out_hex = args.shex or str(b / 'zephyr' / 'zephyr.signed.hex')
            sign_hex = sign_base + [in_hex, out_hex]
            log.inf('hex: {}'.format(out_hex))
            log.dbg(quote_sh_list(sign_hex))
            subprocess.check_call(sign_hex)
コード例 #2
0
def main(argv=None):
    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    # See if we're in an installation.
    try:
        topdir = west_topdir()
    except WestNotFound:
        topdir = None

    # Read the configuration files before looking for extensions.
    # We need this to find the manifest path in order to load extensions.
    config.read_config()

    # Load any extension command specs if we're in an installation.
    if topdir:
        try:
            extensions = get_extension_commands()
        except (MalformedConfig, FileNotFoundError):
            extensions = {}
    else:
        extensions = {}

    if argv is None:
        argv = sys.argv[1:]
    args, unknown = parse_args(argv, extensions, topdir)

    for_stack_trace = 'run as "west -v {}" for a stack trace'.format(
        quote_sh_list(argv))
    try:
        args.handler(args, unknown)
    except KeyboardInterrupt:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.args[0], quote_sh_list(cpe.args[1])))
        if args.verbose:
            traceback.print_exc()
        else:
            log.inf(for_stack_trace)
        sys.exit(cpe.returncode)
    except ExtensionCommandError as ece:
        log.err(
            'extension command', args.command,
            'was improperly defined and could not be run{}'.format(
                ': ' + ece.hint if ece.hint else ''))
        if args.verbose:
            traceback.print_exc()
        else:
            log.inf(for_stack_trace)
        sys.exit(ece.returncode)
    except CommandContextError as cce:
        log.err('command', args.command, 'cannot be run in this context:',
                *cce.args)
        sys.exit(cce.returncode)
    except CommandError as ce:
        sys.exit(ce.returncode)
コード例 #3
0
ファイル: main.py プロジェクト: rgundi/west
def main(argv=None):
    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    if argv is None:
        argv = sys.argv[1:]
    args, unknown = parse_args(argv)

    # Read the configuration files
    config.read_config()

    for_stack_trace = 'run as "west -v ... {} ..." for a stack trace'.format(
        args.command)
    try:
        args.handler(args, unknown)
    except WestUpdated:
        # West has been automatically updated. Restart ourselves to run the
        # latest version, with the same arguments that we were given.
        os.execv(sys.executable, [sys.executable] + sys.argv)
    except KeyboardInterrupt:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.args[0], quote_sh_list(cpe.args[1])))
        if args.verbose:
            raise
        else:
            log.inf(for_stack_trace)
    except CommandContextError as cce:
        log.die('command', args.command, 'cannot be run in this context:',
                *cce.args)
コード例 #4
0
def _ensure_min_version(cmake, dry_run):
    cmd = [cmake, '--version']
    if dry_run:
        log.inf('Dry run:', quote_sh_list(cmd))
        return

    try:
        version_out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
    except subprocess.CalledProcessError as cpe:
        log.die('cannot get cmake version:', str(cpe))
    decoded = version_out.decode('utf-8')
    lines = decoded.splitlines()
    if not lines:
        log.die('can\'t get cmake version: ' +
                'unexpected "cmake --version" output:\n{}\n'.format(decoded) +
                'Please install CMake ' + _MIN_CMAKE_VERSION_STR +
                ' or higher (https://cmake.org/download/).')
    version = lines[0].split()[2]
    if '-' in version:
        # Handle semver cases like "3.19.20210206-g1e50ab6"
        # which Kitware uses for prerelease versions.
        version = version.split('-', 1)[0]
    if packaging.version.parse(version) < _MIN_CMAKE_VERSION:
        log.die(
            'cmake version', version,
            'is less than minimum version {};'.format(_MIN_CMAKE_VERSION_STR),
            'please update your CMake (https://cmake.org/download/).')
    else:
        log.dbg('cmake version', version, 'is OK; minimum version is',
                _MIN_CMAKE_VERSION_STR)
コード例 #5
0
ファイル: project.py プロジェクト: tliqit/west
 def check_call(self, args, cwd=None):
     cmd_str = util.quote_sh_list(args)
     log.dbg("running '{}'".format(cmd_str),
             'in',
             cwd or os.getcwd(),
             level=log.VERBOSE_VERY)
     subprocess.check_call(args, cwd=cwd)
コード例 #6
0
def run_cmake(args, cwd=None, capture_output=False):
    '''Run cmake to (re)generate a build system.
    If capture_output is set to True, returns the output of the command instead
    of displaying it on stdout/stderr..'''
    cmake = shutil.which('cmake')
    if cmake is None:
        log.die('CMake is not installed or cannot be found; cannot build.')
    cmd = [cmake] + args
    kwargs = dict()
    if capture_output:
        kwargs['stdout'] = subprocess.PIPE
        # CMake sends the output of message() to stderr unless it's STATUS
        kwargs['stderr'] = subprocess.STDOUT
    if cwd:
        kwargs['cwd'] = cwd
    log.dbg('Running CMake:', quote_sh_list(cmd), level=log.VERBOSE_NORMAL)
    p = subprocess.Popen(cmd, **kwargs)
    out, err = p.communicate()
    if p.returncode == 0:
        if out:
            return out.decode(sys.getdefaultencoding()).splitlines()
        else:
            return None
    else:
        # A real error occurred, raise an exception
        raise subprocess.CalledProcessError(p.returncode, p.args)
コード例 #7
0
    def sign(self, command, build_dir, bcfg, formats):
        args = command.args

        if args.tool_path:
            command.check_force(
                shutil.which(args.tool_path),
                '--tool-path {}: not an executable'.format(args.tool_path))
            tool_path = args.tool_path
        else:
            tool_path = shutil.which('rimage')
            if not tool_path:
                log.die('rimage not found; either install it',
                        'or provide --tool-path')

        b = pathlib.Path(build_dir)
        cache = cmake.CMakeCache.from_build_dir(build_dir)

        board = cache['CACHED_BOARD']
        if board != 'up_squared_adsp':
            log.die('Supported only for up_squared_adsp board')

        log.inf('Signing with tool {}'.format(tool_path))

        bootloader = str(b / 'zephyr' / 'bootloader.elf.mod')
        kernel = str(b / 'zephyr' / 'zephyr.elf.mod')
        out_bin = str(b / 'zephyr' / 'zephyr.ri')

        sign_base = ([tool_path] + args.tool_args +
                     ['-o', out_bin, '-m', 'apl', '-i', '3'] +
                     [bootloader, kernel])

        log.inf(quote_sh_list(sign_base))
        subprocess.check_call(sign_base)
コード例 #8
0
    def check_output(args, cwd=None):
        '''Runs subprocess.check_output(args, cwd=cwd) after
        logging the call at VERBOSE_VERY level.'''

        cmd_str = quote_sh_list(args)
        log.dbg(f"running '{cmd_str}' in {cwd or os.getcwd()}",
                level=log.VERBOSE_VERY)
        return subprocess.check_output(args, cwd=cwd)
コード例 #9
0
ファイル: sign.py プロジェクト: TobleMiner/framework-zephyr
    def sign(self, command, build_dir, bcfg, formats):
        args = command.args

        if args.tool_path:
            command.check_force(
                shutil.which(args.tool_path),
                '--tool-path {}: not an executable'.format(args.tool_path))
            tool_path = args.tool_path
        else:
            tool_path = shutil.which('rimage')
            if not tool_path:
                log.die('rimage not found; either install it',
                        'or provide --tool-path')

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

        board = cache['CACHED_BOARD']
        log.inf('Signing for board ' + board)
        target = self.edt_get_rimage_target(board)
        conf = target + '.toml'
        log.inf('Signing for SOC target ' + target + ' using ' + conf)

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

        bootloader = str(b / 'zephyr' / 'bootloader.elf.mod')
        kernel = str(b / 'zephyr' / 'zephyr.elf.mod')
        out_bin = str(b / 'zephyr' / 'zephyr.ri')
        out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
        out_tmp = str(b / 'zephyr' / 'zephyr.rix')
        conf_path_cmd = []
        if cache.get('RIMAGE_CONFIG_PATH') and not args.tool_data:
            rimage_conf = pathlib.Path(cache['RIMAGE_CONFIG_PATH'])
            conf_path = str(rimage_conf / conf)
            conf_path_cmd = ['-c', conf_path]
        elif args.tool_data:
            conf_dir = pathlib.Path(args.tool_data)
            conf_path = str(conf_dir / conf)
            conf_path_cmd = ['-c', conf_path]
        else:
            log.die('Configuration not found')

        sign_base = ([tool_path] + args.tool_args + ['-o', out_bin] +
                     conf_path_cmd + ['-i', '3', '-e'] + [bootloader, kernel])

        if not args.quiet:
            log.inf(quote_sh_list(sign_base))
        subprocess.check_call(sign_base)

        filenames = [out_xman, out_bin]
        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)
コード例 #10
0
    def git(self, cmd, extra_args=(), capture_stdout=False,
            capture_stderr=False, check=True, cwd=None):
        '''Helper for running a git command using metadata from a Project
        instance.

        :param cmd: git command as a string (or list of strings); all strings
                    are formatted using self.format() before use.
        :param extra_args: sequence of additional arguments to pass to the git
                           command (useful mostly if cmd is a string).
        :param capture_stdout: True if stdout should be captured into the
                               returned object instead of being printed.
        :param capture_stderr: Like capture_stdout, but for stderr. Use with
                               caution as it prevents error messages from being
                               shown to the user.
        :param check: True if a subprocess.CalledProcessError should be raised
                      if the git command finishes with a non-zero return code.
        :param cwd: directory to run command in (default: self.abspath)

        Returns a CompletedProcess (which is back-ported for Python 3.4).'''
        _warn_once_if_no_git()

        if isinstance(cmd, str):
            cmd_list = shlex.split(cmd)
        else:
            cmd_list = list(cmd)

        extra_args = list(extra_args)

        if cwd is None:
            cwd = self.abspath

        args = ['git'] + [self.format(arg) for arg in cmd_list] + extra_args
        cmd_str = util.quote_sh_list(args)

        log.dbg("running '{}'".format(cmd_str), 'in', cwd,
                level=log.VERBOSE_VERY)
        popen = subprocess.Popen(
            args, cwd=cwd,
            stdout=subprocess.PIPE if capture_stdout else None,
            stderr=subprocess.PIPE if capture_stderr else None)

        stdout, stderr = popen.communicate()

        dbg_msg = "'{}' in {} finished with exit status {}".format(
            cmd_str, cwd, popen.returncode)
        if capture_stdout:
            dbg_msg += " and wrote {} to stdout".format(stdout)
        if capture_stderr:
            dbg_msg += " and wrote {} to stderr".format(stderr)
        log.dbg(dbg_msg, level=log.VERBOSE_VERY)

        if check and popen.returncode:
            raise subprocess.CalledProcessError(popen.returncode, cmd_list,
                                                output=stdout, stderr=stderr)
        else:
            return CompletedProcess(popen.args, popen.returncode,
                                    stdout, stderr)
コード例 #11
0
ファイル: sign.py プロジェクト: wingunder/zephyr
    def sign(self, args):
        cache = cmake.CMakeCache.from_build_dir(args.build_dir)
        runner_config = cached_runner_config(args.build_dir, cache)
        bcfg = BuildConfiguration(args.build_dir)

        # Build a signed .bin
        if args.gen_bin and runner_config.bin_file:
            sign_bin = self.sign_cmd(args, bcfg, runner_config.bin_file,
                                     args.sbin)
            log.dbg(quote_sh_list(sign_bin))
            subprocess.check_call(sign_bin)

        # Build a signed .hex
        if args.gen_hex and runner_config.hex_file:
            sign_hex = self.sign_cmd(args, bcfg, runner_config.hex_file,
                                     args.shex)
            log.dbg(quote_sh_list(sign_hex))
            subprocess.check_call(sign_hex)
コード例 #12
0
def run_cmake(args, cwd=None, capture_output=False, dry_run=False):
    '''Run cmake to (re)generate a build system, a script, etc.

    :param args: arguments to pass to CMake
    :param cwd: directory to run CMake in, cwd is default
    :param capture_output: if True, the output is returned instead of being
                           displayed (None is returned by default, or if
                           dry_run is also True)
    :param dry_run: don't actually execute the command, just print what
                    would have been run

    If capture_output is set to True, returns the output of the command instead
    of displaying it on stdout/stderr..'''
    cmake = shutil.which('cmake')
    if cmake is None and not dry_run:
        log.die('CMake is not installed or cannot be found; cannot build.')
    _ensure_min_version(cmake, dry_run)

    cmd = [cmake] + args

    kwargs = dict()
    if capture_output:
        kwargs['stdout'] = subprocess.PIPE
        # CMake sends the output of message() to stderr unless it's STATUS
        kwargs['stderr'] = subprocess.STDOUT
    if cwd:
        kwargs['cwd'] = cwd

    if dry_run:
        in_cwd = ' (in {})'.format(cwd) if cwd else ''
        log.inf('Dry run{}:'.format(in_cwd), quote_sh_list(cmd))
        return None

    log.dbg('Running CMake:', quote_sh_list(cmd), level=log.VERBOSE_NORMAL)
    p = subprocess.Popen(cmd, **kwargs)
    out, _ = p.communicate()
    if p.returncode == 0:
        if out:
            return out.decode(sys.getdefaultencoding()).splitlines()
        else:
            return None
    else:
        # A real error occurred, raise an exception
        raise subprocess.CalledProcessError(p.returncode, p.args)
コード例 #13
0
ファイル: main.py プロジェクト: XIZHAOJUN/west
def main(argv=None):
    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    # See if we're in an installation.
    try:
        topdir = west_topdir()
    except WestNotFound:
        topdir = None

    # Read the configuration files before looking for extensions.
    # We need this to find the manifest path in order to load extensions.
    config.read_config()

    # Load any extension command specs if we're in an installation.
    if topdir:
        try:
            extensions = get_extension_commands()
        except (MalformedConfig, FileNotFoundError):
            extensions = {}
    else:
        extensions = {}

    if argv is None:
        argv = sys.argv[1:]
    args, unknown = parse_args(argv, extensions, topdir)

    try:
        args.handler(args, unknown)
    except KeyboardInterrupt:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.returncode, quote_sh_list(cpe.cmd)))
        if args.verbose:
            traceback.print_exc()
        sys.exit(cpe.returncode)
    except ExtensionCommandError as ece:
        msg = 'extension command "{}" could not be run{}.'.format(
            args.command, ': ' + ece.hint if ece.hint else '')
        if args.verbose:
            log.err(msg)
            traceback.print_exc()
        else:
            log.err(msg, 'See {} for a traceback.'.format(dump_traceback()))
        sys.exit(ece.returncode)
    except CommandContextError as cce:
        log.err('command', args.command, 'cannot be run in this context:',
                *cce.args)
        log.err('see {} for a traceback.'.format(dump_traceback()))
        sys.exit(cce.returncode)
    except CommandError as ce:
        # No need to dump_traceback() here. The command is responsible
        # for logging its own errors.
        sys.exit(ce.returncode)
コード例 #14
0
def run_cmake(args, quiet=False):
    '''Run cmake to (re)generate a build system'''
    cmake = shutil.which('cmake')
    if cmake is None:
        log.die('CMake is not installed or cannot be found; cannot build.')
    cmd = [cmake] + args
    kwargs = dict()
    if quiet:
        kwargs['stdout'] = subprocess.DEVNULL
        kwargs['stderr'] = subprocess.STDOUT
    log.dbg('Running CMake:', cmd, level=log.VERBOSE_VERY)
    log.dbg('As command:', quote_sh_list(cmd), level=log.VERBOSE_VERY)
    subprocess.check_call(cmd, **kwargs)
コード例 #15
0
    def call(self, cmd):
        '''Subclass subprocess.call() wrapper.

        Subclasses should use this method to run command in a
        subprocess and get its return code, rather than
        using subprocess directly, to keep accurate debug logs.
        '''
        quoted = quote_sh_list(cmd)

        if JUST_PRINT:
            log.inf(quoted)
            return 0

        log.dbg(quoted)
        return subprocess.call(cmd)
コード例 #16
0
    def check_output(self, cmd):
        '''Subclass subprocess.check_output() wrapper.

        Subclasses should use this method to run command in a
        subprocess and check that it executed correctly, rather than
        using subprocess directly, to keep accurate debug logs.
        '''
        quoted = quote_sh_list(cmd)

        if JUST_PRINT:
            log.inf(quoted)
            return b''

        log.dbg(quoted)
        try:
            return subprocess.check_output(cmd)
        except subprocess.CalledProcessError:
            raise
コード例 #17
0
def main(argv=None):
    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    # Read the configuration files
    config.read_config()

    # Load any external command specs. If the config file isn't
    # fully set up yet, ignore the error. This allows west init to
    # work properly.
    try:
        externals = get_external_commands()
    except MalformedConfig:
        externals = {}

    if argv is None:
        argv = sys.argv[1:]
    args, unknown = parse_args(argv, externals)

    for_stack_trace = 'run as "west -v ... {} ..." for a stack trace'.format(
        args.command)
    try:
        args.handler(args, unknown)
    except WestUpdated:
        # West has been automatically updated. Restart ourselves to run the
        # latest version, with the same arguments that we were given.
        os.execv(sys.executable, [sys.executable] + argv)
    except KeyboardInterrupt:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.args[0], quote_sh_list(cpe.args[1])))
        if args.verbose:
            raise
        else:
            log.inf(for_stack_trace)
    except CommandContextError as cce:
        log.err('command', args.command, 'cannot be run in this context:',
                *cce.args)
        sys.exit(cce.returncode)
    except CommandError as ce:
        sys.exit(ce.returncode)
コード例 #18
0
    def popen_ignore_int(self, cmd):
        '''Spawn a child command, ensuring it ignores SIGINT.

        The returned subprocess.Popen object must be manually terminated.'''
        cflags = 0
        preexec = None
        system = platform.system()
        quoted = quote_sh_list(cmd)

        if system == 'Windows':
            cflags |= subprocess.CREATE_NEW_PROCESS_GROUP
        elif system in {'Linux', 'Darwin'}:
            preexec = os.setsid

        if JUST_PRINT:
            log.inf(quoted)
            return _DebugDummyPopen()

        log.dbg(quoted)
        return subprocess.Popen(cmd, creationflags=cflags, preexec_fn=preexec)
コード例 #19
0
    def sign(self, command, build_dir, bcfg, formats):
        args = command.args

        if args.tool_path:
            command.check_force(
                shutil.which(args.tool_path),
                '--tool-path {}: not an executable'.format(args.tool_path))
            tool_path = args.tool_path
        else:
            tool_path = shutil.which('rimage')
            if not tool_path:
                log.die('rimage not found; either install it',
                        'or provide --tool-path')

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

        board = cache['CACHED_BOARD']
        log.inf('Signing for board ' + board)
        target = self.edt_get_rimage_target(board)
        log.inf('Signing for SOC target ' + target)

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

        bootloader = str(b / 'zephyr' / 'bootloader.elf.mod')
        kernel = str(b / 'zephyr' / 'zephyr.elf.mod')
        out_bin = str(b / 'zephyr' / 'zephyr.ri')

        sign_base = ([tool_path] + args.tool_args +
                     ['-o', out_bin, '-m', target, '-i', '3'] +
                     [bootloader, kernel])

        if not args.quiet:
            log.inf(quote_sh_list(sign_base))
        subprocess.check_call(sign_base)
コード例 #20
0
ファイル: sign.py プロジェクト: moshe-borochov/zephyr
    def sign(self, command, build_dir, build_conf, formats):
        if not formats:
            return

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

        imgtool = self.find_imgtool(command, args)
        # The vector table offset is set in Kconfig:
        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(b, args.quiet)
        align, addr, size = self.edt_flash_params(flash)

        if build_conf.getboolean('CONFIG_BOOTLOADER_MCUBOOT'):
            log.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():
                log.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():
                log.die(f"no unsigned .hex found at {in_hex}")
            in_hex = os.fspath(in_hex)
        else:
            in_hex = None

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

        # Base sign command.
        #
        # We provide a default --version in case the user is just
        # messing around and doesn't want to set one. It will be
        # overridden if there is a --version in args.tool_args.
        sign_base = imgtool + [
            'sign', '--version', '0.0.0+0', '--align',
            str(align), '--header-size',
            str(vtoff), '--slot-size',
            str(size)
        ]
        sign_base.extend(args.tool_args)

        if not args.quiet:
            log.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:
                log.inf(f'unsigned bin: {in_bin}')
                log.inf(f'signed bin:   {out_bin}')
                log.dbg(quote_sh_list(sign_bin))
            subprocess.check_call(sign_bin)
        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:
                log.inf(f'unsigned hex: {in_hex}')
                log.inf(f'signed hex:   {out_hex}')
                log.dbg(quote_sh_list(sign_hex))
            subprocess.check_call(sign_hex)
コード例 #21
0
ファイル: manifest.py プロジェクト: tliqit/west
    def git(self,
            cmd,
            extra_args=(),
            capture_stdout=False,
            capture_stderr=False,
            check=True,
            cwd=None):
        '''Run a git command in the project repository.

        Returns a ``subprocess.CompletedProcess`` (an equivalent
        object is back-ported for Python 3.4).

        :param cmd: git command as a string (or list of strings); all
            strings are formatted using `format` before use.
        :param extra_args: sequence of additional arguments to pass to
            the git command (useful mostly if *cmd* is a string).
        :param capture_stdout: if True, git's standard output is
            captured in the ``CompletedProcess`` instead of being
            printed.
        :param capture_stderr: Like *capture_stdout*, but for standard
            error. Use with caution: this may prevent error messages
            from being shown to the user.
        :param check: if given, ``subprocess.CalledProcessError`` is
            raised if git finishes with a non-zero return code
        :param cwd: directory to run git in (default: ``self.abspath``)
        '''
        _warn_once_if_no_git()

        if isinstance(cmd, str):
            cmd_list = shlex.split(cmd)
        else:
            cmd_list = list(cmd)

        extra_args = list(extra_args)

        if cwd is None:
            if self.abspath is not None:
                cwd = self.abspath
            else:
                raise ValueError('no abspath; cwd must be given')

        args = ['git'] + [self.format(arg) for arg in cmd_list] + extra_args
        cmd_str = util.quote_sh_list(args)

        log.dbg("running '{}'".format(cmd_str),
                'in',
                cwd,
                level=log.VERBOSE_VERY)
        popen = subprocess.Popen(
            args,
            cwd=cwd,
            stdout=subprocess.PIPE if capture_stdout else None,
            stderr=subprocess.PIPE if capture_stderr else None)

        stdout, stderr = popen.communicate()

        dbg_msg = "'{}' in {} finished with exit status {}".format(
            cmd_str, cwd, popen.returncode)
        if capture_stdout:
            dbg_msg += " and wrote {} to stdout".format(stdout)
        if capture_stderr:
            dbg_msg += " and wrote {} to stderr".format(stderr)
        log.dbg(dbg_msg, level=log.VERBOSE_VERY)

        if check and popen.returncode:
            raise subprocess.CalledProcessError(popen.returncode,
                                                cmd_list,
                                                output=stdout,
                                                stderr=stderr)
        else:
            return CompletedProcess(popen.args, popen.returncode, stdout,
                                    stderr)
コード例 #22
0
def main(argv=None):
    # Silence validation errors from pykwalify, which are logged at
    # logging.ERROR level. We want to handle those ourselves as
    # needed.
    logging.getLogger('pykwalify').setLevel(logging.CRITICAL)

    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    # See if we're in an installation.
    try:
        topdir = west_topdir()
    except WestNotFound:
        topdir = None

    # Read the configuration files before looking for extensions.
    # We need this to find the manifest path in order to load extensions.
    config.read_config(topdir=topdir)

    # Parse the manifest and create extension command thunks. We'll
    # pass the saved manifest around so it doesn't have to be
    # re-parsed.
    mve = None
    if topdir:
        try:
            manifest = Manifest.from_file(topdir=topdir)
            extensions = get_extension_commands(manifest)
        except (MalformedManifest, MalformedConfig, FileNotFoundError,
                ManifestVersionError) as e:
            manifest = None
            extensions = None
            if isinstance(e, ManifestVersionError):
                mve = e
    else:
        manifest = None
        extensions = {}

    # Create the initial set of parsers. We'll need to re-create these
    # if we're running an extension command. Register extensions with
    # the parser.
    if argv is None:
        argv = sys.argv[1:]
    west_parser, subparser_gen = _make_parsers()
    west_parser.west_extensions = extensions
    west_parser.mve = mve

    # Cache the parser in the global Help instance. Dirty, but it
    # needs this data as its parser attribute is not the parent
    # parser, but the return value of a subparser_gen.
    BUILTIN_COMMANDS['help'].west_parser = west_parser

    # Add sub-parsers for the built-in commands.
    for command in BUILTIN_COMMANDS.values():
        command.add_parser(subparser_gen)

    # Add stub parsers for extensions.
    #
    # These just reserve the names of each extension. The real parser
    # for each extension can't be added until we import the
    # extension's code, which we won't do unless parse_known_args()
    # says to run that extension.
    extensions_by_name = {}
    if extensions:
        for path, specs in extensions.items():
            for spec in specs:
                subparser_gen.add_parser(spec.name, add_help=False)
                extensions_by_name[spec.name] = spec

    # Parse arguments for the first time. We'll need to do this again
    # if we're running an extension.
    args, unknown = west_parser.parse_known_args(args=argv)

    # Set up logging verbosity before running the command, so
    # e.g. verbose messages related to argument handling errors work
    # properly. This works even for extension commands that haven't
    # been instantiated yet, because --verbose is an option to the top
    # level parser, and the command run() method doesn't get called
    # until later.
    log.set_verbosity(args.verbose)

    log.dbg('args namespace:', args, level=log.VERBOSE_EXTREME)

    # Try to set ZEPHYR_BASE. It would be nice to get rid of this
    # someday and just have extensions that need it set this variable.
    if args.command and args.command not in ['init', 'help'] and not args.help:
        set_zephyr_base(args)

    # If we were run as 'west -h ...' or 'west --help ...',
    # monkeypatch the args namespace so we end up running Help.  The
    # user might have also provided a command. If so, print help about
    # that command.
    if args.help or args.command is None:
        args.command_name = args.command
        args.command = 'help'

    # Finally, run the command.
    try:
        if args.command in extensions_by_name:
            # Check a program invariant. We should never get here
            # unless we were able to parse the manifest. That's where
            # information about extensions is gained.
            assert mve is None, \
                'internal error: running extension "{}" ' \
                'but got ManifestVersionError'.format(args.command)

            # This does not return. get_extension_commands() ensures
            # that extensions do not shadow built-in command names, so
            # checking this first is safe.
            run_extension(extensions_by_name[args.command], topdir, argv,
                          manifest)
        else:
            if mve:
                if args.command == 'help':
                    log.wrn(
                        _mve_msg(mve, suggest_ugprade=False) +
                        '\n  Cannot get extension command help, ' +
                        "and most commands won't run." +
                        '\n  To silence this warning, upgrade west.')
                elif args.command in ['config', 'topdir']:
                    # config and topdir are safe to run, but let's
                    # warn the user that most other commands won't be.
                    log.wrn(
                        _mve_msg(mve, suggest_ugprade=False) +
                        "\n  This should work, but most commands won't." +
                        '\n  To silence this warning, upgrade west.')
                elif args.command != 'init':
                    log.die(_mve_msg(mve))

            cmd = BUILTIN_COMMANDS.get(args.command, BUILTIN_COMMANDS['help'])
            cmd.run(args, unknown, topdir, manifest=manifest)
    except KeyboardInterrupt:
        sys.exit(0)
    except BrokenPipeError:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.returncode, quote_sh_list(cpe.cmd)))
        if args.verbose:
            traceback.print_exc()
        sys.exit(cpe.returncode)
    except ExtensionCommandError as ece:
        msg = 'extension command "{}" could not be run{}.'.format(
            args.command, ': ' + ece.hint if ece.hint else '')
        if args.verbose:
            log.err(msg)
            traceback.print_exc()
        else:
            log.err(msg, 'See {} for a traceback.'.format(dump_traceback()))
        sys.exit(ece.returncode)
    except CommandContextError as cce:
        log.err('command', args.command, 'cannot be run in this context:',
                *cce.args)
        log.err('see {} for a traceback.'.format(dump_traceback()))
        sys.exit(cce.returncode)
    except CommandError as ce:
        # No need to dump_traceback() here. The command is responsible
        # for logging its own errors.
        sys.exit(ce.returncode)
    except (MalformedManifest, MalformedConfig) as malformed:
        log.die('\n  '.join(["can't load west manifest"] +
                            list(malformed.args)))
コード例 #23
0
def main(argv=None):
    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    # Read the configuration files
    config.read_config()

    # Load any extension command specs. If the config file isn't
    # fully set up yet or the west.yml cannot be found, ignore the error.
    # This allows west init to work properly.
    try:
        extensions = get_extension_commands()
    except (MalformedConfig, FileNotFoundError):
        extensions = {}

    if argv is None:
        argv = sys.argv[1:]
    args, unknown = parse_args(argv, extensions)

    for_stack_trace = 'run as "west -v {}" for a stack trace'.format(
        quote_sh_list(argv))
    try:
        args.handler(args, unknown)
    except WestUpdated:
        # West has been automatically updated. Restart ourselves to run the
        # latest version, with the same arguments that we were given.
        # Treat the Python script as an executable. This works because on
        # Unix the script created by pip has a shebang and on Windows it is
        # actually a binary executable
        log.dbg("sys.argv[0]:\"{}\" argv:\"{}\"".format(sys.argv[0], argv))
        # Use Popen + exit instead of execv due to the asynchronous nature of
        # execv on Windows, where it creates a new process with a different
        # pid that executes in parallel to the original one instead of
        # replacing it as it does on UNIX
        # https://bugs.python.org/issue9148
        # https://bugs.python.org/issue19124
        try:
            proc = Popen([sys.argv[0]] + argv)
            proc.communicate()
        except KeyboardInterrupt:
            sys.exit(0)
        log.dbg('proc.returncode: {}'.format(proc.returncode))
        sys.exit(errno.EIO if proc.returncode is None else proc.returncode)
    except KeyboardInterrupt:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.args[0], quote_sh_list(cpe.args[1])))
        if args.verbose:
            traceback.print_exc()
        else:
            log.inf(for_stack_trace)
        sys.exit(cpe.returncode)
    except ExtensionCommandError as ece:
        log.err(
            'extension command', args.command,
            'was improperly defined and could not be run{}'.format(
                ': ' + ece.hint if ece.hint else ''))
        if args.verbose:
            traceback.print_exc()
        else:
            log.inf(for_stack_trace)
        sys.exit(ece.returncode)
    except CommandContextError as cce:
        log.err('command', args.command, 'cannot be run in this context:',
                *cce.args)
        sys.exit(cce.returncode)
    except CommandError as ce:
        sys.exit(ce.returncode)
コード例 #24
0
ファイル: main.py プロジェクト: machinelinux-root/west
def main(argv=None):
    # Silence validation errors from pykwalify, which are logged at
    # logging.ERROR level. We want to handle those ourselves as
    # needed.
    logging.getLogger('pykwalify').setLevel(logging.CRITICAL)

    # Makes ANSI color escapes work on Windows, and strips them when
    # stdout/stderr isn't a terminal
    colorama.init()

    # See if we're in an installation.
    try:
        topdir = west_topdir()
    except WestNotFound:
        topdir = None

    # Read the configuration files before looking for extensions.
    # We need this to find the manifest path in order to load extensions.
    config.read_config()

    # Parse the manifest and create extension command thunks. We'll
    # pass the saved manifest around so it doesn't have to be
    # re-parsed.
    if topdir:
        try:
            manifest = Manifest.from_file()
            extensions = get_extension_commands(manifest)
        except (MalformedManifest, MalformedConfig, FileNotFoundError):
            manifest = None
            extensions = None
    else:
        manifest = None
        extensions = {}

    if argv is None:
        argv = sys.argv[1:]
    args, unknown = parse_args(argv, extensions, topdir, manifest)

    try:
        args.handler(args, unknown)
    except KeyboardInterrupt:
        sys.exit(0)
    except CalledProcessError as cpe:
        log.err('command exited with status {}: {}'.format(
            cpe.returncode, quote_sh_list(cpe.cmd)))
        if args.verbose:
            traceback.print_exc()
        sys.exit(cpe.returncode)
    except ExtensionCommandError as ece:
        msg = 'extension command "{}" could not be run{}.'.format(
            args.command, ': ' + ece.hint if ece.hint else '')
        if args.verbose:
            log.err(msg)
            traceback.print_exc()
        else:
            log.err(msg, 'See {} for a traceback.'.format(dump_traceback()))
        sys.exit(ece.returncode)
    except CommandContextError as cce:
        log.err('command', args.command, 'cannot be run in this context:',
                *cce.args)
        log.err('see {} for a traceback.'.format(dump_traceback()))
        sys.exit(cce.returncode)
    except CommandError as ce:
        # No need to dump_traceback() here. The command is responsible
        # for logging its own errors.
        sys.exit(ce.returncode)
    except (MalformedManifest, MalformedConfig) as malformed:
        log.die("can't load west manifest:", malformed)
コード例 #25
0
ファイル: project.py プロジェクト: ioannisg/west
def _git_helper(project, cmd, extra_args, cwd, capture_stdout, check):
    # Runs a git command.
    #
    # project:
    #   The Project instance for the project, derived from the manifest file.
    #
    # cmd:
    #   String with git arguments. Supports some "(foo)" shorthands. See below.
    #
    # extra_args:
    #   List of additional arguments to pass to the git command (e.g. from the
    #   user).
    #
    # cwd:
    #   Directory to switch to first (None = current directory)
    #
    # capture_stdout:
    #   True if stdout should be captured into the returned
    #   subprocess.CompletedProcess instance instead of being printed.
    #
    #   We never capture stderr, to prevent error messages from being eaten.
    #
    # check:
    #   True if an error should be raised if the git command finishes with a
    #   non-zero return code.
    #
    # Returns a subprocess.CompletedProcess instance.

    # TODO: Run once somewhere?
    if shutil.which('git') is None:
        log.die('Git is not installed or cannot be found')

    args = (('git', ) +
            tuple(_expand_shorthands(project, arg)
                  for arg in cmd.split()) + tuple(extra_args))
    cmd_str = util.quote_sh_list(args)

    log.dbg("running '{}'".format(cmd_str), 'in', cwd, level=log.VERBOSE_VERY)
    popen = subprocess.Popen(
        args, stdout=subprocess.PIPE if capture_stdout else None, cwd=cwd)

    stdout, _ = popen.communicate()

    dbg_msg = "'{}' in {} finished with exit status {}" \
              .format(cmd_str, cwd, popen.returncode)
    if capture_stdout:
        dbg_msg += " and wrote {} to stdout".format(stdout)
    log.dbg(dbg_msg, level=log.VERBOSE_VERY)

    if check and popen.returncode:
        msg = "Command '{}' failed for {{name_and_path}}".format(cmd_str)
        if _error_context_msg:
            msg += _error_context_msg.replace('\n', ' ')
        _die(project, msg)

    if capture_stdout:
        # Manual UTF-8 decoding and universal newlines. Before Python 3.6,
        # Popen doesn't seem to allow using universal newlines mode (which
        # enables decoding) with a specific encoding (because the encoding=
        # parameter is missing).
        #
        # Also strip all trailing newlines as convenience. The splitlines()
        # already means we lose a final '\n' anyway.
        stdout = "\n".join(stdout.decode('utf-8').splitlines()).rstrip("\n")

    return CompletedProcess(popen.args, popen.returncode, stdout)
コード例 #26
0
ファイル: sign.py プロジェクト: vulporuza/zephyr
    def sign(self, command, build_dir, build_conf, formats):
        args = command.args

        if args.tool_path:
            command.check_force(shutil.which(args.tool_path),
                                '--tool-path {}: not an executable'.
                                format(args.tool_path))
            tool_path = args.tool_path
        else:
            tool_path = shutil.which('rimage')
            if not tool_path:
                log.die('rimage not found; either install it',
                        'or provide --tool-path')

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

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

        # warning: RIMAGE_TARGET is a duplicate of CONFIG_RIMAGE_SIGNING_SCHEMA
        target = cache.get('RIMAGE_TARGET')
        if not target:
            log.die('rimage target not defined')

        cmake_toml = target + '.toml'

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

        if target in ('imx8', 'imx8m'):
            kernel = str(b / 'zephyr' / 'zephyr.elf')
            out_bin = str(b / 'zephyr' / 'zephyr.ri')
            out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
            out_tmp = str(b / 'zephyr' / 'zephyr.rix')
        else:
            bootloader = str(b / 'zephyr' / 'boot.mod')
            kernel = str(b / 'zephyr' / 'main.mod')
            out_bin = str(b / 'zephyr' / 'zephyr.ri')
            out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
            out_tmp = str(b / 'zephyr' / 'zephyr.rix')

        conf_path_cmd = []

        if '-c' in args.tool_args:
            # Precedence to the -- rimage command line
            conf_path_cmd = []
            if args.tool_data:
                log.wrn('--tool-data ' + args.tool_data + ' ignored, overridden by -c')
            # For logging only
            conf_path = args.tool_args[args.tool_args.index('-c') + 1]
        elif args.tool_data:
            conf_dir = pathlib.Path(args.tool_data)
            conf_path = str(conf_dir / cmake_toml)
            conf_path_cmd = ['-c', conf_path]
        elif cache.get('RIMAGE_CONFIG_PATH'):
            rimage_conf = pathlib.Path(cache['RIMAGE_CONFIG_PATH'])
            conf_path = str(rimage_conf / cmake_toml)
            conf_path_cmd = ['-c', conf_path]
        else:
            log.die('-c configuration not found')

        log.inf('Signing for SOC target ' + target + ' using ' + conf_path)

        if '--no-manifest' in args.tool_args:
            no_manifest = True
            args.tool_args.remove('--no-manifest')
        else:
            no_manifest = False

        if no_manifest:
            extra_ri_args = ['-i', '3']
        else:
            extra_ri_args = ['-i', '3', '-e']

        sign_base = [tool_path]

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

        components = [ ] if (target in ('imx8', 'imx8m')) else [ bootloader ]
        components += [ kernel ]
        sign_base += (args.tool_args +
                     ['-o', out_bin] + conf_path_cmd + extra_ri_args +
                     components)

        if not args.quiet:
            log.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:
            log.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)
コード例 #27
0
    def sign(self, command, build_dir, bcfg, formats):
        args = command.args

        if args.tool_path:
            command.check_force(
                shutil.which(args.tool_path),
                '--tool-path {}: not an executable'.format(args.tool_path))
            tool_path = args.tool_path
        else:
            tool_path = shutil.which('imgtool')
            if not tool_path:
                log.die(
                    'imgtool not found; either install it',
                    '(e.g. "pip3 install imgtool") or provide --tool-path')

        align, vtoff, slot_size = [
            self.get_cfg(command, bcfg, x)
            for x in ('DT_FLASH_WRITE_BLOCK_SIZE',
                      'CONFIG_TEXT_SECTION_OFFSET',
                      'DT_FLASH_AREA_IMAGE_0_SIZE')
        ]

        log.dbg('build config: --align={}, --header-size={}, --slot-size={}'.
                format(align, vtoff, slot_size))

        # Base sign command.
        #
        # We provide a default --version in case the user is just
        # messing around and doesn't want to set one. It will be
        # overridden if there is a --version in args.tool_args.
        sign_base = [tool_path, 'sign', '--version', '0.0.0+0']
        if align:
            sign_base.extend(['--align', str(align)])
        else:
            log.wrn('expected nonzero flash alignment, but '
                    'DT_FLASH_WRITE_BLOCK_SIZE={} '
                    "in build directory's ({}) device tree".format(
                        align, build_dir))

        if vtoff:
            sign_base.extend(['--header-size', str(vtoff)])
        else:
            log.wrn('expected nonzero header size, but '
                    'CONFIG_TEXT_SECTION_OFFSET={} '
                    "in build directory's ({}) .config".format(
                        vtoff, build_dir))

        if slot_size:
            sign_base.extend(['--slot-size', str(slot_size)])
        else:
            log.wrn('expected nonzero slot size, but '
                    'DT_FLASH_AREA_IMAGE_0_SIZE={} '
                    "in build directory's ({}) device tree".format(
                        slot_size, build_dir))

        b = pathlib.Path(build_dir)
        cache = cmake.CMakeCache.from_build_dir(build_dir)
        runner_config = cached_runner_config(build_dir, cache)

        # Build a signed .bin
        if 'bin' in formats and runner_config.bin_file:
            out_bin = args.sbin or str(b / 'zephyr' / 'zephyr.signed.bin')
            log.inf('Generating:', out_bin)
            sign_bin = (sign_base + args.tool_args +
                        [runner_config.bin_file, out_bin])
            log.dbg(quote_sh_list(sign_bin))
            subprocess.check_call(sign_bin)

        # Build a signed .hex
        if 'hex' in formats and runner_config.hex_file:
            out_hex = args.shex or str(b / 'zephyr' / 'zephyr.signed.hex')
            log.inf('Generating:', out_hex)
            sign_hex = (sign_base + args.tool_args +
                        [runner_config.hex_file, out_hex])
            log.dbg(quote_sh_list(sign_hex))
            subprocess.check_call(sign_hex)
コード例 #28
0
 def check_call(self, args, cwd=None):
     cmd_str = util.quote_sh_list(args)
     log.dbg(f"running '{cmd_str}' in {cwd or os.getcwd()}",
             level=log.VERBOSE_VERY)
     subprocess.check_call(args, cwd=cwd)
コード例 #29
0
ファイル: sign.py プロジェクト: westonrobot/zephyr
    def sign(self, command, build_dir, build_conf, formats):
        args = command.args

        if args.tool_path:
            command.check_force(
                shutil.which(args.tool_path),
                '--tool-path {}: not an executable'.format(args.tool_path))
            tool_path = args.tool_path
        else:
            tool_path = shutil.which('rimage')
            if not tool_path:
                log.die('rimage not found; either install it',
                        'or provide --tool-path')

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

        target = cache.get('RIMAGE_TARGET')
        if not target:
            log.die('rimage target not defined')

        conf = target + '.toml'
        log.inf('Signing for SOC target ' + target + ' using ' + conf)

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

        if target in ('imx8', 'imx8m'):
            kernel = str(b / 'zephyr' / 'zephyr.elf')
            out_bin = str(b / 'zephyr' / 'zephyr.ri')
            out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
            out_tmp = str(b / 'zephyr' / 'zephyr.rix')
        else:
            bootloader = str(b / 'zephyr' / 'boot.mod')
            kernel = str(b / 'zephyr' / 'main.mod')
            out_bin = str(b / 'zephyr' / 'zephyr.ri')
            out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
            out_tmp = str(b / 'zephyr' / 'zephyr.rix')
        conf_path_cmd = []
        if cache.get('RIMAGE_CONFIG_PATH') and not args.tool_data:
            rimage_conf = pathlib.Path(cache['RIMAGE_CONFIG_PATH'])
            conf_path = str(rimage_conf / conf)
            conf_path_cmd = ['-c', conf_path]
        elif args.tool_data:
            conf_dir = pathlib.Path(args.tool_data)
            conf_path = str(conf_dir / conf)
            conf_path_cmd = ['-c', conf_path]
        else:
            log.die('Configuration not found')
        if '--no-manifest' in args.tool_args:
            no_manifest = True
            args.tool_args.remove('--no-manifest')
        else:
            no_manifest = False

        if no_manifest:
            extra_ri_args = ['-i', '3']
        else:
            extra_ri_args = ['-i', '3', '-e']

        components = [] if (target in ('imx8', 'imx8m')) else [bootloader]
        components += [kernel]
        sign_base = ([tool_path] + args.tool_args + ['-o', out_bin] +
                     conf_path_cmd + extra_ri_args + components)

        if not args.quiet:
            log.inf(quote_sh_list(sign_base))
        subprocess.check_call(sign_base)

        if no_manifest:
            filenames = [out_bin]
        else:
            filenames = [out_xman, out_bin]
        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)