123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- #! /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()
- 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, fvpconf, extra_args):
- fvp = runner.FVPRunner(logger)
- try:
- 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'))
- finally:
- return 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)
- 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
|