1#!/bin/sh 2########################################################################## 3# Copyright (c) 2009-2015 ETH Zurich. 4# All rights reserved. 5# 6# This file is distributed under the terms in the attached LICENSE file. 7# If you do not find this file, copies can be found by writing to: 8# ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich, 9# Attn: Systems Group. 10# 11# Shell script for running Qemu with a Barrelfish image 12# 13########################################################################## 14 15HDFILE=hd.img 16EFI_FLASH0=flash0.img 17EFI_FLASH1=flash1.img 18HAGFISH_LOCATION="/home/netos/tftpboot/Hagfish.efi" 19MENUFILE="" 20ARCH="" 21DEBUG_SCRIPT="" 22# Grab SMP from env, if unset default to 1 23SMP=${SMP:-1} 24# Grab NIC_MODEL from env, if unset default to e1000 25NIC_MODEL="${NIC_MODEL:-e1000e}" 26 27 28usage () { 29 echo "Usage: $0 --menu <file> --arch <arch> [options]" 30 echo " where:" 31 echo " 'arch' is one of: x86_64, a15ve, armv8, zynq7" 32 echo " 'file' is a menu.lst format file to read module list from" 33 echo " and options can be:" 34 echo " --debug <script> (run under the specified GDB script)" 35 echo " --hdfile <file> (hard disk image to be build for AHCI, defaults to $HDFILE" 36 echo " --kernel <file> (kernel binary, if no menu.lst given)" 37 echo " --initrd <file> (initial RAM disk, if no menu.lst given)" 38 echo " --image <file> (prebaked boot image, instead of kernel/initrd)" 39 echo " --args <args> (kernel command-line args, if no menu.lst given)" 40 echo " --smp <cores> (number of cores to use, defaults to $SMP)" 41 echo " --nic-model <name> (nic model to use, defaults to $NIC_MODEL)" 42 echo " --hagfish <file> (Hagfish boot loader, defaults to $HAGFISH_LOCATION)" 43 echo " " 44 echo " The following environment variables are considered:" 45 echo " QEMU_PATH (Path for qemu-system-* binary)" 46 echo " NIC_MODEL (Same as --nic-model)" 47 echo " SMP (Same as --smp)" 48 exit 1 49} 50 51# Result in $? 52qemu_supports_device() { 53 ${QEMU_PATH}qemu-system-x86_64 -device help 2>&1 | grep \"$1\" > /dev/null 54} 55 56 57if test $# = 0; then usage ; fi 58while test $# != 0; do 59 case $1 in 60 "--help"|"-h") 61 usage 62 exit 0 63 ;; 64 "--menu") 65 shift; MENUFILE="$1" 66 ;; 67 "--arch") 68 shift; ARCH="$1" 69 ;; 70 "--hdfile") 71 shift; HDFILE="$1" 72 ;; 73 "--debug") 74 shift; DEBUG_SCRIPT="$1" 75 ;; 76 "--initrd") 77 shift; INITRD="$1" 78 ;; 79 "--kernel") 80 shift; KERNEL="$1" 81 ;; 82 "--image") 83 shift; IMAGE="$1" 84 ;; 85 "--args") 86 shift; KERNEL_CMDS="$1" 87 ;; 88 "--smp") 89 shift; SMP="$1" 90 ;; 91 "--hagfish") 92 shift; HAGFISH_LOCATION="$1" 93 ;; 94 "--nic-model") 95 shift; NIC_MODEL="$1" 96 ;; 97 *) 98 echo "Unknown option $1 (try: --help)" >&2 99 exit 1 100 ;; 101 esac 102 shift 103done 104 105if test -z "$IMAGE"; then 106 if test -z "$MENUFILE"; then 107 echo "No menu.lst file specified." 108 if test -z "$KERNEL"; then 109 echo "ERROR: No initial kernel given and no menu.lst file." >&2; exit 1 110 fi 111 if test -z "$INITRD"; then 112 echo "ERROR: No initial RAM disk given and no menu.lst file." >&2; exit 1 113 fi 114 else 115 echo "Using menu file $MENUFILE" 116 ROOT=`sed -rne 's,^root[ \t]*([^ ]*).*,\1,p' "$MENUFILE"` 117 if test "$ROOT" != "(nd)"; then 118 echo "Root: $ROOT" 119 fi 120 KERNEL=`sed -rne 's,^kernel[ \t]*/([^ ]*).*,\1,p' "$MENUFILE"` 121 if test "$ROOT" != "(nd)"; then 122 KERNEL="$ROOT/$KERNEL" 123 fi 124 if test -z "$KERNEL"; then 125 echo "ERROR: No initial kernel specified in menu.lst file." >&2; exit 1 126 fi 127 KERNEL_CMDS=`sed -rne 's,^kernel[ \t]*[^ ]*[ \t]*(.*),\1,p' "$MENUFILE"` 128 if test "$ROOT" != "(nd)"; then 129 AWKSCRIPT='{ if (NR == 1) printf(root "/" $$0); else printf("," root "/" $$0) }' 130 AWKARGS="-v root=$ROOT" 131 else 132 AWKSCRIPT='{ if (NR == 1) printf($$0); else printf("," $$0) }' 133 fi 134 INITRD=`sed -rne 's,^module(nounzip)?[ \t]*/(.*),\2,p' "$MENUFILE" | awk $AWKARGS "$AWKSCRIPT"` 135 if test -z "$INITRD"; then 136 echo "ERROR: No initial ram disk modules specified in menu.lst file." >&2; exit 1 137 fi 138 fi 139 echo "Initial kernel file: $KERNEL" 140 echo "Initial RAM disk contents: $INITRD" 141else 142 echo "Booting image: $IMAGE" 143fi 144 145echo "Kernel command line arguments: $KERNEL_CMDS" 146echo "Requested architecture is $ARCH." 147 148case "$ARCH" in 149 "x86_64") 150 qemu_supports_device $NIC_MODEL 151 if [ $? = 1 ] ; then 152 echo "$NIC_MODEL not supported. Fall back to e1000" 153 NIC_MODEL=e1000 ; 154 fi 155 156 # Two NIC qemu conf 157 #QEMU_CMD="${QEMU_PATH}qemu-system-x86_64 \ 158 # -machine type=q35 \ 159 # -smp $SMP \ 160 # -enable-kvm \ 161 # -m 1024 \ 162 # -netdev user,id=network0 \ 163 # -netdev user,id=network1 \ 164 # -device $NIC_MODEL,netdev=network0 165 # -device $NIC_MODEL,netdev=network1 166 # -device ahci,id=ahci \ 167 # -device ide-drive,drive=disk,bus=ahci.0 \ 168 # -drive id=disk,file="$HDFILE",if=none" 169 170 QEMU_CMD="${QEMU_PATH}qemu-system-x86_64 \ 171 -machine type=q35 \ 172 -smp $SMP \ 173 -m 1024 \ 174 -netdev user,id=network0 \ 175 -device $NIC_MODEL,netdev=network0 \ 176 -device ahci,id=ahci \ 177 -device ide-drive,drive=disk,bus=ahci.0 \ 178 -drive id=disk,file="$HDFILE",if=none" 179 QEMU_NONDEBUG=-nographic 180 GDB=gdb-multiarch 181 echo "Creating hard disk image $HDFILE" 182 qemu-img create "$HDFILE" 10M 183 ;; 184 "a15ve") 185 QEMU_CMD="${QEMU_PATH}qemu-system-arm \ 186 -m 1024 \ 187 -smp $SMP \ 188 -machine vexpress-a15" 189 GDB=gdb 190 QEMU_NONDEBUG=-nographic 191 ;; 192 "armv8") 193 QEMU_CMD="${QEMU_PATH}qemu-system-aarch64 \ 194 -m 1024 \ 195 -cpu cortex-a57 \ 196 -M virt -d guest_errors \ 197 -M gic_version=3 \ 198 -smp $SMP \ 199 -bios /usr/share/qemu-efi/QEMU_EFI.fd \ 200 -device virtio-blk-device,drive=image \ 201 -drive if=none,id=image,file=$IMAGE,format=raw" 202 GDB=gdb-multiarch 203 QEMU_NONDEBUG=-nographic 204 EFI=1 205 ;; 206 "zynq7") 207 QEMU_CMD="${QEMU_PATH}qemu-system-arm \ 208 -machine xilinx-zynq-a9 \ 209 -m 1024 \ 210 -serial /dev/null \ 211 -serial mon:stdio" 212 GDB=gdb 213 QEMU_NONDEBUG=-nographic 214 ;; 215 *) 216 echo "No QEmu environment defined for architecture=$ARCH." >&2 217 exit 1 218 ;; 219esac 220 221export QEMU_AUDIO_DRV=none 222 223if test "$DEBUG_SCRIPT" = ""; then 224 echo "OK: about to run the follow qemu command:" 225 if test -z "$EFI"; then 226 if test -z "$IMAGE"; then 227 echo "$QEMU_CMD $QEMU_NONDEBUG -kernel $KERNEL -append '$KERNEL_CMDS' -initrd $INITRD" 228 exec $QEMU_CMD $QEMU_NONDEBUG -kernel $KERNEL -append '$KERNEL_CMDS' -initrd "$INITRD" 229 else 230 echo "$QEMU_CMD $QEMU_NONDEBUG -kernel $IMAGE" 231 exec $QEMU_CMD $QEMU_NONDEBUG -kernel "$IMAGE" 232 fi 233 else 234 echo $QEMU_CMD $QEMU_NONDEBUG 235 exec $QEMU_CMD $QEMU_NONDEBUG 236 fi 237fi 238 239 240# Now we run the debugger instead 241GDB_ARGS="-x $DEBUG_SCRIPT" 242SERIAL_OUTPUT=file:/dev/stdout 243PORT=$((10000 + UID)) 244 245if test "${SERIAL_OUTPUT}" = ""; then 246 # Assuming session is interactive. Use terminal for serial output because 247 # stdout does not work for daemonized qemu and output is lost. This likely 248 # only matters on ARM where there is no video driver at time of writing. 249 SERIAL_OUTPUT=`tty` 250fi 251 252PIDFILE=/tmp/qemu_debugsim_${USER}_${PORT}.pid 253if test -f $PIDFILE; then 254 if ps `cat $PIDFILE` >/dev/null; then 255 echo "Another QEMU already running (PID: `cat $PIDFILE` PIDFILE: $PIDFILE)" 256 exit 1 257 else 258 echo "Deleting stale lockfile $PIDFILE" 259 rm -f $PIDFILE 260 fi 261fi 262 263echo args = $GDB_ARGS 264 265cat > barrelfish_debug.gdb <<EOF 266# Connect to QEMU instance 267target remote localhost:$PORT 268EOF 269 270if test -z "$EFI"; then 271 if test -z "$IMAGE"; then 272 QEMU_INVOCATION="${QEMU_CMD} \ 273 -kernel \"$KERNEL\" \ 274 -append \"$KERNEL_CMDS\" \ 275 -initrd \"$INITRD\" \ 276 -serial $SERIAL_OUTPUT \ 277 -gdb tcp::$PORT \ 278 -S \ 279 -display none \ 280 -daemonize \ 281 -pidfile $PIDFILE" 282 else 283 QEMU_INVOCATION="${QEMU_CMD} \ 284 -kernel \"$IMAGE\" \ 285 -append \"$KERNEL_CMDS\" \ 286 -serial $SERIAL_OUTPUT \ 287 -gdb tcp::$PORT \ 288 -S \ 289 -display none \ 290 -daemonize \ 291 -pidfile $PIDFILE" 292 fi 293else 294 QEMU_INVOCATION="${QEMU_CMD} \ 295 -serial $SERIAL_OUTPUT \ 296 -gdb tcp::$PORT \ 297 -S \ 298 -display none \ 299 -daemonize \ 300 -pidfile $PIDFILE" 301fi 302 303echo $QEMU_INVOCATION 304set -x 305 306eval $QEMU_INVOCATION 307 308if test $? -eq 0; then 309 stty sane 310 trap '' INT 311 ${GDB} -x barrelfish_debug.gdb ${GDB_ARGS} 312 PID=`cat ${PIDFILE}` 313 kill ${PID} > /dev/null || true 314 rm -f $PIDFILE 315else 316 echo Failed to launch qemu with: 317 echo " ${QEMU_INVOCATION}" 318fi 319