#!/usr/bin/env python3

import argparse
import subprocess

parser = argparse.ArgumentParser(description="QEMU runner")

parser.add_argument("elf_executable", help="Location of compiled ELF executable to run")
# QEMU options
parser.add_argument("--init", default="/bin/sh", help="Location of the init process (in the rootfs)")
parser.add_argument("--rootfs", default="moss.img", help="Location of the root filesystem image to use")
parser.add_argument("--cpu", default="cortex-a72")
parser.add_argument("--smp", default=4, help="Number of CPU cores to use")
parser.add_argument("--memory", default="2G")
parser.add_argument("--debug", action="store_true", help="Enable QEMU debugging")
parser.add_argument("--display", action="store_true", help="Add a display device to the VM")



args = parser.parse_args()


elf_executable = args.elf_executable
bin_executable_location = elf_executable.replace(".elf", "") + ".bin"
# Convert the ELF executable to a binary format
subprocess.run(["aarch64-none-elf-objcopy", "-O", "binary", elf_executable, bin_executable_location], check=True)

append_args = ""

if args.init.split("/")[-1] in ["bash", "sh"]:
    append_args = f"--init={args.init} --init-arg=-i"
else:
    append_args = f"--init={args.init}"

default_args = {
    "-M": "virt,gic-version=3",
    "-initrd": args.rootfs,
    "-cpu": args.cpu,
    "-m": args.memory,
    "-smp": str(args.smp),
    "-rtc": "base=utc,clock=host",
    "-nographic": None,
    "-s": None,
    "-kernel": bin_executable_location,
    "-append": f"{append_args} --rootfs=ext4fs --automount=/dev,devfs --automount=/tmp,tmpfs --automount=/proc,procfs --automount=/sys,sysfs",
}

# Arguments that can appear multiple times (e.g. -device)
extra_args = ["-device", "virtio-rng-device"]

if args.debug:
    default_args["-S"] = None

if args.display:
    del default_args["-nographic"]
    default_args["-global"] = "virtio-mmio.force-legacy=false"
    default_args["-nic"] = "none"
    # Add uart
    default_args["-serial"] = "stdio"
    extra_args += ["-device", "virtio-gpu-device"]

qemu_command = ["qemu-system-aarch64"]

for key, value in default_args.items():
    qemu_command.append(key)
    if value is not None:
        qemu_command.append(value)

qemu_command += extra_args

subprocess.run(qemu_command, check=True)
