| #!/usr/bin/env python3 |
| # ===----------------------------------------------------------------------===## |
| # |
| # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| # See https://llvm.org/LICENSE.txt for license information. |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| # |
| # ===----------------------------------------------------------------------===## |
| |
| """qemu_baremetal.py is a utility for running a program with QEMU's system mode. |
| |
| It is able to pass command line arguments to the program and forward input and |
| output (if the underlying baremetal enviroment supports QEMU semihosting). |
| """ |
| |
| import argparse |
| import os |
| import sys |
| import shutil |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--qemu", type=str, required=True) |
| parser.add_argument("--cpu", type=str, required=False) |
| parser.add_argument("--machine", type=str, default="virt") |
| parser.add_argument( |
| "--qemu-arg", dest="qemu_args", type=str, action="append", default=[] |
| ) |
| parser.add_argument("--semihosting", action="store_true", default=True) |
| parser.add_argument("--no-semihosting", dest="semihosting", action="store_false") |
| parser.add_argument("--execdir", type=str, required=True) |
| parser.add_argument("test_binary") |
| parser.add_argument("test_args", nargs=argparse.ZERO_OR_MORE, default=[]) |
| args = parser.parse_args() |
| |
| if not shutil.which(args.qemu): |
| sys.exit(f"Failed to find QEMU binary from --qemu value: '{args.qemu}'") |
| |
| if not os.path.exists(args.test_binary): |
| sys.exit(f"Expected argument to be a test executable: '{args.test_binary}'") |
| |
| qemu_commandline = [ |
| args.qemu, |
| "-chardev", |
| "stdio,mux=on,id=stdio0", |
| "-monitor", |
| "none", |
| "-serial", |
| "none", |
| "-machine", |
| f"{args.machine},accel=tcg", |
| "-device", |
| f"loader,file={args.test_binary},cpu-num=0", |
| "-nographic", |
| *args.qemu_args, |
| ] |
| if args.cpu: |
| qemu_commandline += ["-cpu", args.cpu] |
| |
| if args.semihosting: |
| # Use QEMU's semihosting support to pass argv (supported by picolibc) |
| semihosting_config = f"enable=on,chardev=stdio0,arg={args.test_binary}" |
| for arg in args.test_args: |
| semihosting_config += f",arg={arg}" |
| qemu_commandline += ["-semihosting-config", semihosting_config] |
| elif args.test_args: |
| sys.exit( |
| "Got non-empty test arguments but do no know how to pass them to " |
| "QEMU without semihosting support" |
| ) |
| os.execvp(qemu_commandline[0], qemu_commandline) |
| |
| |
| if __name__ == "__main__": |
| exit(main()) |