blob: b9b5aef82920aa03378ac293f6bc837d6112d06c [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>] [-c <text>] [-N [-I <ifname>]] [-u <path>] [-g <port> [-r <fps>] [-t <cmd>]] [-x <port> [-X <directory>]] [-e <directory>] [-w <size>] [-s <cpus>] [--audio] [--headless] [--software-gpu] [--debugger]
## -a <mode> acceleration mode (auto, off, kvm, hvf, hax), default is auto
## -c <text> add item to kernel command line
## -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 prebuilt/third_party/aemu/PLATFORM
## -g <port> enable gRPC service on port to control the emulator, default is 5556 when WebRTC service is enabled
## -r <fps> webrtc frame rate when using gRPC service, default is 30
## -t <cmd> execute the given command to obtain turn configuration
## -x <port> enable WebRTC HTTP service on port
## -X <directory> location of grpcwebproxy, defaults to looking in prebuilt/third_party/grpcwebproxy
## -w <size> window size, default is 1280x800
## -s <cpus> number of cpus, 1 for uniprocessor, default is 4
## --audio run with audio hardware added to the virtual machine
## --headless run in headless mode
## --software-gpu run without host GPU acceleration
## --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 $?
ACCEL="auto"
NET=0
DEBUGGER=0
IFNAME=""
AUDIO=0
AEMU="emulator"
AEMU_DIR=""
UPSCRIPT=no
WINDOW_SIZE="1280x800"
GRPC=
RTCFPS="30"
TURNCFG=""
GPU="host"
VULKAN=1
HTTP=0
GRPCWEBPROXY_DIR=""
CMDLINE=""
SMP=4
# 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
while [[ $# -ge 1 ]]; do
case "$1" in
-h|--help)
fx-command-help
exit 0
;;
-a)
shift
ACCEL="$1"
;;
-c)
shift
CMDLINE+="$1 "
;;
-N)
NET=1
;;
-I)
shift
IFNAME="$1"
;;
-u)
shift
UPSCRIPT="$1"
;;
-e)
shift
AEMU_DIR="$1"
;;
-x)
shift
HTTP="$1"
;;
-X)
shift
GRPCWEBPROXY_DIR="$1"
;;
-g)
shift
GRPC="$1"
;;
-r)
shift
RTCFPS="$1"
;;
-t)
shift
TURNCFG="$1"
;;
-w)
shift
WINDOW_SIZE="$1"
;;
-s)
shift
SMP="$1"
;;
--audio)
AUDIO=1
;;
--headless)
AEMU="emulator-headless"
;;
--debugger)
DEBUGGER=1
;;
--software-gpu)
GPU="swiftshader_indirect"
# disable vulkan when using swiftshader.
# TODO: remove this when swiftshader supports external memory and
# can be used by fuchsia guests.
VULKAN=0
;;
*)
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 "$PREBUILT_AEMU_DIR" ]]; then
AEMU_DIR="$PREBUILT_AEMU_DIR"
fi
if [[ -z "$GRPCWEBPROXY_DIR" && -d "$PREBUILT_GRPCWEBPROXY_DIR" ]]; then
GRPCWEBPROXY_DIR="$PREBUILT_GRPCWEBPROXY_DIR"
fi
# construct the args for aemu
ARGS=()
ARGS+=("-m" "2048")
ARGS+=("-serial" "stdio")
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 [[ $SMP != 1 ]]; then
ARGS+=("-smp" "${SMP},threads=2")
fi
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,GLDirectMem"
elif [[ "$ACCEL" == "hvf" ]]; then
ARGS+=("-enable-hvf" "-cpu" "Haswell")
FEATURES+=",HVF,GLDirectMem"
elif [[ "$ACCEL" == "hax" ]]; then
ARGS+=("-enable-hax" "-cpu" "Haswell")
FEATURES+=",HAXM,GLDirectMem"
elif [[ "$ACCEL" == "off" ]]; then
ARGS+=("-cpu" "Haswell,+smap,-check,-fsgsbase")
FEATURES+=",-GLDirectMem"
# disable vulkan as not useful without kvm,hvf,hax and support
# for coherent host visible memory.
VULKAN=0
else
fx-error Unsupported acceleration mode
exit 1
fi
if (( $VULKAN )); then
FEATURES+=",Vulkan"
else
FEATURES+=",-Vulkan"
fi
OPTIONS=()
OPTIONS+=("-feature" "$FEATURES")
OPTIONS+=("-window-size" "$WINDOW_SIZE")
OPTIONS+=("-gpu" "$GPU")
if (( $DEBUGGER )); then
OPTIONS+=("-wait-for-debugger")
fi
# use port 5556 by default
if (( $HTTP )); then
GRPC="${GRPC:-5556}"
fi
if (( $GRPC )); then
OPTIONS+=("-grpc" "$GRPC")
OPTIONS+=("-rtcfps" "$RTCFPS")
if [[ -n "$TURNCFG" ]]; then
OPTIONS+=("-turncfg" "$TURNCFG")
fi
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}" ; [[ "${GRPCWEBPROXY_PID}" ]] && kill "${GRPCWEBPROXY_PID}"' EXIT
KERNEL_ZBI="${img_dir}/fuchsia-ssh.zbi"
fx-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
# Start gRPC web proxy if HTTP port is set
if (( $HTTP )); then
"${GRPCWEBPROXY_DIR}/grpcwebproxy" \
--backend_addr localhost:"$GRPC" --server_http_debug_port "$HTTP" \
--backend_tls=false --run_tls_server=false --allow_all_origins &
GRPCWEBPROXY_PID=$!
fi
# construct the kernel cmd line for aemu
CMDLINE+="kernel.serial=legacy "
# 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
"${AEMU_DIR}/${AEMU}" "${OPTIONS[@]}" -fuchsia \
-kernel "${FUCHSIA_BUILD_DIR}/${IMAGE_QEMU_KERNEL_RAW}" \
-initrd "$KERNEL_ZBI" "${ARGS[@]}" -append "$CMDLINE" "$@"