Alexander Richardson | d002ce5 | 2023-11-09 21:09:06 | [diff] [blame^] | 1 | #!/usr/bin/env python3 |
| 2 | # ===----------------------------------------------------------------------===## |
| 3 | # |
| 4 | # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 5 | # See https://llvm.org/LICENSE.txt for license information. |
| 6 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 7 | # |
| 8 | # ===----------------------------------------------------------------------===## |
| 9 | |
| 10 | """qemu_baremetal.py is a utility for running a program with QEMU's system mode. |
| 11 | |
| 12 | It is able to pass command line arguments to the program and forward input and |
| 13 | output (if the underlying baremetal enviroment supports QEMU semihosting). |
| 14 | """ |
| 15 | |
| 16 | import argparse |
| 17 | import os |
| 18 | import platform |
| 19 | import subprocess |
| 20 | import sys |
| 21 | |
| 22 | |
| 23 | def main(): |
| 24 | parser = argparse.ArgumentParser() |
| 25 | parser.add_argument("--qemu", type=str, required=True) |
| 26 | parser.add_argument("--cpu", type=str, required=False) |
| 27 | parser.add_argument("--machine", type=str, default="virt") |
| 28 | parser.add_argument( |
| 29 | "--qemu-arg", dest="qemu_args", type=str, action="append", default=[] |
| 30 | ) |
| 31 | parser.add_argument("--semihosting", action="store_true", default=True) |
| 32 | parser.add_argument("--no-semihosting", dest="semihosting", action="store_false") |
| 33 | parser.add_argument("--execdir", type=str, required=True) |
| 34 | parser.add_argument("test_binary") |
| 35 | parser.add_argument("test_args", nargs=argparse.ZERO_OR_MORE, default=[]) |
| 36 | args = parser.parse_args() |
| 37 | if not os.path.exists(args.test_binary): |
| 38 | sys.exit(f"Expected argument to be a test executable: '{args.test_binary}'") |
| 39 | qemu_commandline = [ |
| 40 | args.qemu, |
| 41 | "-chardev", |
| 42 | "stdio,mux=on,id=stdio0", |
| 43 | "-monitor", |
| 44 | "none", |
| 45 | "-serial", |
| 46 | "none", |
| 47 | "-machine", |
| 48 | f"{args.machine},accel=tcg", |
| 49 | "-device", |
| 50 | f"loader,file={args.test_binary},cpu-num=0", |
| 51 | "-nographic", |
| 52 | *args.qemu_args, |
| 53 | ] |
| 54 | if args.cpu: |
| 55 | qemu_commandline += ["-cpu", args.cpu] |
| 56 | |
| 57 | if args.semihosting: |
| 58 | # Use QEMU's semihosting support to pass argv (supported by picolibc) |
| 59 | semihosting_config = f"enable=on,chardev=stdio0,arg={args.test_binary}" |
| 60 | for arg in args.test_args: |
| 61 | semihosting_config += f",arg={arg}" |
| 62 | qemu_commandline += ["-semihosting-config", semihosting_config] |
| 63 | elif args.test_args: |
| 64 | sys.exit( |
| 65 | "Got non-empty test arguments but do no know how to pass them to " |
| 66 | "QEMU without semihosting support" |
| 67 | ) |
| 68 | os.execvp(qemu_commandline[0], qemu_commandline) |
| 69 | |
| 70 | |
| 71 | if __name__ == "__main__": |
| 72 | exit(main()) |