mirror of
https://git.yoctoproject.org/meta-arm
synced 2026-01-12 03:10:15 +00:00
Start a new thread to simultaneously log the output of FVP and the telnet output if the --verbose flag is passed to runfvp. So that ConsolePortParser can read the same stream, use itertools.tee to temporarily duplicate the stream. Use a custom log format string with an escape character to ensure that log output always starts at the beginning of a line when interleaved with console output. Issue-Id: SCM-5314 Signed-off-by: Peter Hoyes <Peter.Hoyes@arm.com> Change-Id: I3e815d9d899425e0d2af619524f09f2eda87562c Signed-off-by: Jon Mason <jon.mason@arm.com>
111 lines
3.8 KiB
Python
Executable File
111 lines
3.8 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 terminal, runner, conffile
|
|
|
|
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()
|
|
group.add_argument("-t", "--terminals", choices=terminals.all_terminals(), default=terminals.preferred_terminal(), help="Automatically start terminals (default: %(default)s)")
|
|
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.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, config, extra_args):
|
|
fvp = runner.FVPRunner(logger)
|
|
try:
|
|
fvp.start(config, extra_args, args.terminals)
|
|
|
|
if args.console:
|
|
expected_terminal = config["consoles"]["default"]
|
|
if not expected_terminal:
|
|
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'))
|
|
|
|
finally:
|
|
fvp.stop()
|
|
|
|
|
|
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)
|
|
logger.debug(f"Loading {config_file}")
|
|
config = conffile.load(config_file)
|
|
start_fvp(args, config, 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
|