blob: 5c1f129170e4ff2fbc2d68e11aa5daf0d19f1273 [file] [log] [blame]
#!/bin/bash
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
### start fuchsia in aemu
## usage: fx aemu [-a <mode>] [-N [-I <ifname>]] [-u <path>] [-g <port>] [-e <directory>] [-w <size>] [--audio] [--headless] [--debugger]
## -a <mode> acceleration mode (auto, off, kvm, hvf, hax), default is auto
## -N run with emulated nic via tun/tap
## -I <ifname> uses the tun/tap interface named ifname
## -u <path> execute aemu if-up script, default is no script
## -e <directory> location of emulator, defaults to looking in zircon/prebuilt/downloads/aemu
## -g <port> enable gRPC service on port to control the emulator
## -w <size> window size, default is 1280x800
## --audio run with audio hardware added to the virtual machine
## --headless run in headless mode
## --debugger pause on launch and wait for a debugger process to attach before resuming
set -e
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/image_build_vars.sh || exit $?
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/fvm.sh || exit $?
source "${FUCHSIA_DIR}/buildtools/vars.sh"
ACCEL="auto"
NET=0
DEBUGGER=0
IFNAME=""
AUDIO=0
AEMU="emulator"
AEMU_DIR=""
UPSCRIPT=no
WINDOW_SIZE="1280x800"
GRPC=0
while [[ $# -ge 1 ]]; do
case "$1" in
-h|--help)
fx-command-help
exit 0
;;
-a)
shift
ACCEL="$1"
;;
-N)
NET=1
;;
-I)
shift
IFNAME="$1"
;;
-u)
shift
UPSCRIPT="$1"
;;
-e)
shift
AEMU_DIR="$1"
;;
-g)
shift
GRPC="$1"
;;
-w)
shift
WINDOW_SIZE="$1"
;;
--audio)
AUDIO=1
;;
--headless)
AEMU="emulator-headless"
;;
--debugger)
DEBUGGER=1
;;
*)
break
esac
shift
done
# aemu is limited to x64 for now
if [[ "$FUCHSIA_ARCH" != "x64" ]]; then
fx-error Unsupported arch
exit 1
fi
if [[ -z "$AEMU_DIR" && -d "${FUCHSIA_DIR}/zircon/prebuilt/downloads/aemu" ]]; then
AEMU_DIR="${FUCHSIA_DIR}/zircon/prebuilt/downloads/aemu/"
fi
# construct the args for aemu
ARGS=()
ARGS+=("-m" "2048")
ARGS+=("-serial" "stdio")
ARGS+=("-smp" "4,threads=2")
ARGS+=("-vga" "none")
ARGS+=("-machine" "q35")
ARGS+=("-device" "isa-debug-exit,iobase=0xf4,iosize=0x04")
ARGS+=("-device" "virtio-keyboard-pci")
ARGS+=("-device" "virtio_input_multi_touch_pci_1")
if (( $AUDIO )); then
ARGS+=("-soundhw" "hda")
fi
FEATURES="VirtioInput,RefCountPipe"
if [[ "$ACCEL" == "auto" ]]; then
if [[ "$(uname -s)" == "Darwin" ]]; then
ACCEL="hvf"
else
ACCEL="kvm"
fi
fi
if [[ "$ACCEL" == "kvm" ]]; then
ARGS+=("-enable-kvm" "-cpu" "host,migratable=no,+invtsc")
FEATURES+=",KVM,Vulkan,GLDirectMem"
elif [[ "$ACCEL" == "hvf" ]]; then
ARGS+=("-enable-hvf" "-cpu" "Haswell")
FEATURES+=",HVF,Vulkan,GLDirectMem"
elif [[ "$ACCEL" == "hax" ]]; then
ARGS+=("-enable-hax" "-cpu" "Haswell")
FEATURES+=",HAXM,Vulkan,GLDirectMem"
elif [[ "$ACCEL" == "off" ]]; then
ARGS+=("-cpu" "Haswell,+smap,-check,-fsgsbase")
# disable vulkan as not useful without kvm,hvf,hax and support
# for coherent host visible memory.
FEATURES+=",-Vulkan,-GLDirectMem"
else
fx-error Unsupported acceleration mode
exit 1
fi
OPTIONS=()
OPTIONS+=("-feature" "$FEATURES")
OPTIONS+=("-window-size" "$WINDOW_SIZE")
if (( $DEBUGGER )); then
OPTIONS+=("-wait-for-debugger")
fi
if (( $GRPC )); then
OPTIONS+=("-grpc" "$GRPC")
fi
if (( $NET )); then
if [[ "$(uname -s)" == "Darwin" ]]; then
if [ -z "$IFNAME" ]; then
IFNAME="tap0"
fi
if [[ ! -c "/dev/$IFNAME" ]]; then
echo "To use aemu with networking on macOS, install the tun/tap driver:"
echo "http://tuntaposx.sourceforge.net/download.xhtml"
exit 1
fi
if [[ ! -w "/dev/$IFNAME" ]]; then
echo "For networking /dev/$IFNAME must be owned by $USER. Please run:"
echo " sudo chown $USER /dev/$IFNAME"
exit 1
fi
else
if [ -z "$IFNAME" ]; then
IFNAME="qemu"
fi
TAP_IFS=$(ip tuntap show 2>/dev/null)
if [[ ! "$TAP_IFS" =~ "${IFNAME}:" ]]; then
echo "To use aemu with networking on Linux, configure tun/tap:"
echo
echo "sudo ip tuntap add dev $IFNAME mode tap user $USER && \\"
echo "sudo ip link set $IFNAME up"
exit 1
fi
fi
ARGS+=("-netdev" "type=tap,ifname=$IFNAME,script=$UPSCRIPT,downscript=no,id=net0")
HASH=$(echo $IFNAME | shasum)
SUFFIX=$(for i in {0..2}; do echo -n :${HASH:$(( 2 * $i )):2}; done)
MAC=",mac=52:54:00$SUFFIX"
ARGS+=("-device" "e1000,netdev=net0${MAC}")
else
ARGS+=("-net" "none")
fi
# Construction of a qcow image prevents aemu from writing back to the
# build-produced image file, which could cause timestamp issues with that file.
# Construction of the new ZBI adds //.ssh/authorized_keys for SSH access.
img_dir="$(mktemp -d)"
if [[ ! -d "${img_dir}" ]]; then
fx-error "Failed to create temporary directory"
exit 1
fi
trap 'rm -rf "$img_dir"' EXIT
KERNEL_ZBI="${img_dir}/fuchsia-ssh.zbi"
"${ZIRCON_TOOLS_DIR}/zbi" -o "${KERNEL_ZBI}" "${FUCHSIA_BUILD_DIR}/${IMAGE_ZIRCONA_ZBI}" \
--entry "data/ssh/authorized_keys=${FUCHSIA_DIR}/.ssh/authorized_keys"
if [ -n "$IMAGE_FVM_RAW" ]; then
fvmimg="${img_dir}/fvm.blk"
fx-fvm-extend-image "${FUCHSIA_BUILD_DIR}/${IMAGE_FVM_RAW}" $fvmimg
ARGS+=("-drive" "file=${fvmimg},format=raw,if=none,id=mydisk")
ARGS+=("-device" "ich9-ahci,id=ahci" "-device" "ide-drive,drive=mydisk,bus=ahci.0")
fi
# construct the kernel cmd line for aemu
CMDLINE="kernel.serial=legacy "
# Propagate our TERM environment variable as a kernel command line
# argument. This is first so that an explicit -c TERM=foo argument
# goes into CMDLINE later and overrides this.
if [[ -n $TERM ]]; then
CMDLINE+="TERM=$TERM "
fi
# Add entropy to the kernel
CMDLINE+="kernel.entropy-mixin=$(head -c 32 /dev/urandom | shasum -a 256 | awk '{ print $1 }') "
# Don't 'reboot' the emulator if the kernel crashes
CMDLINE+="kernel.halt-on-panic=true "
# run aemu
set -x
exec "${AEMU_DIR}${AEMU}" "${OPTIONS[@]}" -fuchsia \
-kernel "${FUCHSIA_BUILD_DIR}/${IMAGE_QEMU_KERNEL_RAW}" \
-initrd "$KERNEL_ZBI" "${ARGS[@]}" -append "$CMDLINE" "$@"