1
0
mirror of https://git.yoctoproject.org/meta-arm synced 2026-07-15 15:37:15 +00:00
Files
Michael Safwat 6ab14ea640 runfvp: add --dry-run option
Add a --dry-run option to scripts/runfvp to print the constructed
FVP command line and exit without launching the model.

This is useful for checking parameters and reusing them with different
FVP binaries.

Signed-off-by: Michael Safwat <michael.safwat@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-28 05:00:03 -04:00

125 lines
4.4 KiB
Python
Executable File

#! /usr/bin/env python3
import itertools
import os
import pathlib
import signal
import sys
import threading
import logging
logger = logging.getLogger("RunFVP")
# Add meta-arm/lib/ to path
libdir = pathlib.Path(__file__).parents[1] / "meta-arm" / "lib"
sys.path.insert(0, str(libdir))
from fvp import conffile, terminal, runner
def parse_args(arguments):
import argparse
terminals = terminal.terminals
parser = argparse.ArgumentParser(description="Run images in a FVP")
parser.add_argument("config", nargs="?", help="Machine name or path to .fvpconf file")
group = parser.add_mutually_exclusive_group()
available_terminals=",".join(terminals.available_terminals())
group.add_argument("-t", "--terminals", choices=terminals.all_terminals(), default=terminals.preferred_terminal(), help=f"Automatically start terminals (default: %(default)s). Available terminals are ({available_terminals})")
group.add_argument("-c", "--console", action="store_true", help="Attach the first uart to stdin/stdout")
parser.add_argument("--verbose", action="store_true", help="Output verbose logging")
parser.add_argument("--dry-run", action="store_true", help="Print the FVP command and exit")
parser.usage = f"{parser.format_usage().strip()} -- [ arguments passed to FVP ]"
# TODO option for telnet vs netcat
# If the arguments contains -- then everything after it should be passed to the FVP binary directly.
if "--" in arguments:
i = arguments.index("--")
fvp_args = arguments[i+1:]
arguments = arguments[:i]
else:
fvp_args = []
args = parser.parse_args(args=arguments)
logging.basicConfig(level=args.verbose and logging.DEBUG or logging.WARNING,
format='\033[G%(levelname)s: %(message)s')
# If we're hooking up the console, don't start any terminals
if args.console:
args.terminals = "none"
logger.debug(f"Parsed arguments: {vars(args)}")
logger.debug(f"FVP arguments: {fvp_args}")
return args, fvp_args
def start_fvp(args, fvpconf, extra_args):
fvp = runner.FVPRunner(logger)
try:
if args.dry_run:
config = conffile.load(fvpconf)
cli = runner.cli_from_config(config, args.terminals) + extra_args
print(runner.shlex_join(cli))
return 0
if args.terminals:
if not terminal.terminals[args.terminals].is_ready():
return 1
fvp.start(fvpconf, extra_args, args.terminals)
if args.console:
config = fvp.getConfig()
expected_terminal = config["consoles"].get("default")
if expected_terminal is None:
logger.error("--console used but FVP_CONSOLE not set in machine configuration")
return 1
port_stdout, log_stdout = itertools.tee(fvp.stdout, 2)
parser = runner.ConsolePortParser(port_stdout)
port = parser.parse_port(expected_terminal)
def debug_log():
for line in log_stdout:
line = line.strip().decode(errors='ignore')
logger.debug(f'FVP output: {line}')
log_thread = threading.Thread(None, debug_log)
log_thread.start()
telnet = fvp.create_telnet(port)
telnet.wait()
logger.debug(f"Telnet quit, cancelling tasks")
else:
for line in fvp.stdout:
print(line.strip().decode(errors='ignore'))
except FileNotFoundError as e:
logger.error(f"FVP executable not found ({e})")
finally:
rv=fvp.stop()
return rv
def runfvp(cli_args):
args, extra_args = parse_args(cli_args)
if args.config and pathlib.Path(args.config).exists():
config_file = args.config
else:
config_file = conffile.find(args.config)
return start_fvp(args, config_file, extra_args)
if __name__ == "__main__":
try:
# Set the process group so that it's possible to kill runfvp and
# everything it spawns easily.
# Ignore permission errors happening when spawned from an other process
# for example run from except
try:
os.setpgid(0, 0)
except PermissionError:
pass
if sys.stdin.isatty():
signal.signal(signal.SIGTTOU, signal.SIG_IGN)
os.tcsetpgrp(sys.stdin.fileno(), os.getpgrp())
sys.exit(runfvp(sys.argv[1:]))
except KeyboardInterrupt:
pass