blob: f44773a37ea2d4b3cf2fe66b0c96eb777fc0b699 [file] [edit]
#!/usr/bin/env bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
. "$DIR/qemu-shared.sh"
function HELP {
local ec=${1:-0}
echo "help:"
echo "-6 : x86-64"
echo "-l : legacy mode build (386 emulated machine)"
echo "-m <memory in MB> : memory size (default: 512 MB, 4 MB for legacy)"
echo "-s <number of cpus> : number of CPUs (default: 1)"
echo "-X : print QEMU command and exit (dry run)"
echo
echo "-A <cmd line> : append command line (may be used multiple times)"
echo "-d <disk image> : add an IDE disk device (may be used multiple times)"
echo "-g : with graphics (VGA display, keyboard, mouse)"
echo "-n : enable user mode networking (default driver: e1000e)"
echo "-N <network driver> : specify network driver (requires -n or -t, e.g., virtio-net-pci, e1000e)"
echo "-t : use tap interface qemu0 for networking"
echo "-f <shared dir> : add a virtio 9p device with a host shared directory"
echo "-V : use virtio versions of devices where possible"
echo "-k : use KVM acceleration"
echo
echo "-h : show this help"
echo "all arguments after -- are passed to qemu directly"
exit $ec
}
DO_64BIT=0
DO_LEGACY=0
DO_GRAPHICS=0
DO_KVM=0
DISK_IMAGES=()
CMDLINE=""
DO_NET=0
DO_NET_TAP=0
DO_VIRTIO=0
DO_V9P=0
DO_V9P_DIR=""
NETDEV=e1000e
DO_NETDEV_OVERRIDE=0
MEMSIZE=0
SMP=1
SUDO=""
DO_DRYRUN=0
while getopts A:6d:gf:klm:nN:s:thVX FLAG; do
case $FLAG in
A) CMDLINE+="${CMDLINE:+ }$(quote_cmdline_arg "$OPTARG")";;
6) DO_64BIT=1;;
d)
DISK_IMAGES+=("$OPTARG")
;;
g) DO_GRAPHICS=1;;
f) DO_V9P=1; DO_V9P_DIR=$OPTARG;;
k) DO_KVM=1;;
l) DO_LEGACY=1;;
m) MEMSIZE=$OPTARG;;
n) DO_NET=1;;
t) DO_NET_TAP=1;;
N) NETDEV=$OPTARG; DO_NETDEV_OVERRIDE=1;;
s) SMP=$OPTARG;;
V) DO_VIRTIO=1;;
X) DO_DRYRUN=1;;
h) HELP 0;;
\?)
echo unrecognized option $OPTARG
HELP 1
esac
done
shift $((OPTIND-1))
if (( DO_NET && DO_NET_TAP )); then
echo "Error: Cannot use both -n (user network) and -t (tap network) together"
exit 1
fi
if (( DO_NETDEV_OVERRIDE && ! ( DO_NET || DO_NET_TAP ) )); then
echo "Error: -N requires either -n (user network) or -t (tap network)"
exit 1
fi
# pick the appropriate qemu and project
if (( DO_64BIT )); then
QEMU="qemu-system-x86_64"
PROJECT="pc-x86-64-test"
CPU=max
MACHINE=q35
elif (( DO_LEGACY )); then
QEMU="qemu-system-i386"
PROJECT="pc-x86-legacy-test"
CPU=486
MACHINE=isapc
else
QEMU="qemu-system-i386"
PROJECT="pc-x86-test"
CPU=max
MACHINE=q35
fi
if (( DO_LEGACY )); then
if (( ! MEMSIZE )); then
MEMSIZE=4
fi
else
if (( ! MEMSIZE )); then
MEMSIZE=512
fi
fi
VIRTIO_BLOCK_DEVICE="virtio-blk-pci"
VIRTIO_NET_DEVICE="virtio-net-pci"
VIRTIO_GPU_DEVICE="virtio-gpu-pci"
VIRTIO_KEYBOARD_DEVICE="virtio-keyboard-pci"
VIRTIO_MOUSE_DEVICE="virtio-mouse-pci"
VIRTIO_9P_DEVICE="virtio-9p-pci"
VIRTIO_RNG_DEVICE="virtio-rng-pci"
if (( DO_VIRTIO )); then
NETDEV=$VIRTIO_NET_DEVICE
fi
ARGS=()
if (( DO_KVM )); then
ARGS+=("-accel" "kvm" "-cpu" "host")
else
ARGS+=("-cpu" "$CPU")
fi
ARGS+=("-m" "$MEMSIZE")
ARGS+=("-smp" "$SMP")
ARGS+=("-machine" "$MACHINE")
ARGS+=("-kernel" "build-${PROJECT}/lk.elf")
if [[ -n "$CMDLINE" ]]; then
ARGS+=("-append" "$CMDLINE")
fi
ARGS+=("-device" "isa-debug-exit,iobase=0xf4,iosize=0x04")
ARGS+=("-fw_cfg" "name=etc/sercon-port,string=0")
if (( DO_GRAPHICS )); then
ARGS+=("-serial" "stdio")
# TODO: get -vga virtio working
ARGS+=("-vga" "std")
if (( DO_VIRTIO )); then
# this will create an additional virtio GPU device for graphics output in addition
# to the primary VGA device
ARGS+=("-device" "${VIRTIO_GPU_DEVICE}")
ARGS+=("-device" "${VIRTIO_KEYBOARD_DEVICE}")
ARGS+=("-device" "${VIRTIO_MOUSE_DEVICE}")
fi
else
ARGS+=("-nographic")
fi
function append_disk_image {
local disk_image=$1
local disk_number=$2
ARGS+=("-drive" "if=none,file=${disk_image},id=disk${disk_number},discard=on")
if (( DO_VIRTIO )); then
ARGS+=("-device" "${VIRTIO_BLOCK_DEVICE},drive=disk${disk_number}")
else
# for q35 machines this will add to an ahci controller
# for legacy machines will end up appending to the ISA ide controller
ARGS+=("-device" "ide-hd,drive=disk${disk_number},bus=ide.${disk_number}")
fi
}
DISK_COUNT=0
for img in "${DISK_IMAGES[@]}"; do
append_disk_image "$img" "$DISK_COUNT"
((DISK_COUNT++))
done
if (( DO_NET || DO_NET_TAP )); then
if (( ! DO_LEGACY )); then
if (( DO_NET )); then
ARGS+=("-netdev" "user,id=vmnic,hostname=qemu")
elif (( DO_NET_TAP )); then
# quick note to enable tap interface
# IFNAME=qemu0
# BRIDGE=bridge0
# sudo ip tuntap add name "${IFNAME}" mode tap user $(whoami)
# sudo ip link set "${IFNAME}" master "${BRIDGE}"
# sudo ip link set "${IFNAME}" up
ARGS+=("-netdev" "tap,id=vmnic,ifname=qemu0,script=no,downscript=no")
#SUDO="sudo"
fi
ARGS+=("-device" "$NETDEV,netdev=vmnic")
else
echo "implement legacy + network config"
exit 1
fi
else
ARGS+=("-net" "none")
fi
if (( DO_V9P )); then
ARGS+=("-fsdev" "local,path=$DO_V9P_DIR,security_model=mapped,id=v9p0")
ARGS+=("-device" "${VIRTIO_9P_DEVICE},fsdev=v9p0,mount_tag=V9P0")
fi
if (( ! DO_LEGACY )); then
ARGS+=("-device" "${VIRTIO_RNG_DEVICE}")
fi
CMD=()
if [[ -n "$SUDO" ]]; then
CMD+=("sudo")
fi
CMD+=("$QEMU")
CMD+=("${ARGS[@]}")
CMD+=("$@")
if (( DO_DRYRUN )); then
echo "${CMD[@]}"
exit 0
fi
"$DIR"/make-parallel $PROJECT &&
echo "${CMD[@]}" &&
exec "${CMD[@]}"