2 ##########################################################################
3 # Copyright (c) 2009-2015 ETH Zurich.
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,
11 # Shell script for running Qemu with a Barrelfish image
13 ##########################################################################
18 HAGFISH_LOCATION="/home/netos/tftpboot/Hagfish.efi"
22 # Grab SMP from env, if unset default to 2
24 # Grab NIC_MODEL from env, if unset default to e1000
25 NIC_MODEL="${NIC_MODEL:-e1000}"
29 echo "Usage: $0 --menu <file> --arch <arch> [options]"
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)"
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)"
52 if test $# = 0; then usage ; fi
53 while test $# != 0; do
69 shift; DEBUG_SCRIPT="$1"
81 shift; KERNEL_CMDS="$1"
87 shift; HAGFISH_LOCATION="$1"
93 echo "Unknown option $1 (try: --help)" >&2
100 if test -z "$IMAGE"; then
101 if test -z "$MENUFILE"; then
102 echo "No menu.lst file specified."
103 if test -z "$KERNEL"; then
104 echo "ERROR: No initial kernel given and no menu.lst file." >&2; exit 1
106 if test -z "$INITRD"; then
107 echo "ERROR: No initial RAM disk given and no menu.lst file." >&2; exit 1
110 echo "Using menu file $MENUFILE"
111 ROOT=`sed -rne 's,^root[ \t]*([^ ]*).*,\1,p' "$MENUFILE"`
112 if test "$ROOT" != "(nd)"; then
115 KERNEL=`sed -rne 's,^kernel[ \t]*/([^ ]*).*,\1,p' "$MENUFILE"`
116 if test "$ROOT" != "(nd)"; then
117 KERNEL="$ROOT/$KERNEL"
119 if test -z "$KERNEL"; then
120 echo "ERROR: No initial kernel specified in menu.lst file." >&2; exit 1
122 KERNEL_CMDS=`sed -rne 's,^kernel[ \t]*[^ ]*[ \t]*(.*),\1,p' "$MENUFILE"`
123 if test "$ROOT" != "(nd)"; then
124 AWKSCRIPT='{ if (NR == 1) printf(root "/" $$0); else printf("," root "/" $$0) }'
125 AWKARGS="-v root=$ROOT"
127 AWKSCRIPT='{ if (NR == 1) printf($$0); else printf("," $$0) }'
129 INITRD=`sed -rne 's,^module(nounzip)?[ \t]*/(.*),\2,p' "$MENUFILE" | awk $AWKARGS "$AWKSCRIPT"`
130 if test -z "$INITRD"; then
131 echo "ERROR: No initial ram disk modules specified in menu.lst file." >&2; exit 1
134 echo "Initial kernel file: $KERNEL"
135 echo "Initial RAM disk contents: $INITRD"
137 echo "Booting image: $IMAGE"
140 echo "Kernel command line arguments: $KERNEL_CMDS"
141 echo "Requested architecture is $ARCH."
145 QEMU_CMD="${QEMU_PATH}qemu-system-x86_64 \
149 -net nic,model=$NIC_MODEL \
151 -device ahci,id=ahci \
152 -device ide-drive,drive=disk,bus=ahci.0 \
153 -drive id=disk,file="$HDFILE",if=none"
154 QEMU_NONDEBUG=-nographic
156 echo "Creating hard disk image $HDFILE"
157 qemu-img create "$HDFILE" 10M
160 QEMU_CMD="${QEMU_PATH}qemu-system-arm \
163 -machine vexpress-a15"
165 QEMU_NONDEBUG=-nographic
169 # The next steps create the EFI directory for QEMU.
171 # - Hagfish.efi the UEFI bootloader
172 # - Hagfish.cfg 'menu.lst' specifying what Hagfish should boot
173 # - startup.nsh script executed by the EFI shell
174 # - ... remaining files in the disk
176 # NOTE: Qemu is only able to support FAT16, hence the directory specified
177 # by -drive must be smaller than 500M.
178 # We currently copy the created binary into this directory
180 mkdir -p qemu-efi/armv8/sbin
181 # create the startup script
182 echo "\\Hagfish.efi Hagfish.cfg" > qemu-efi/startup.nsh
183 chmod +x qemu-efi/startup.nsh
184 # setup hagfish location
185 cp $HAGFISH_LOCATION qemu-efi/Hagfish.efi
186 cp platforms/arm/menu.lst.armv8_a57v qemu-efi/Hagfish.cfg
189 cp -r armv8/sbin/* qemu-efi/armv8/sbin/
190 QEMU_CMD="${QEMU_PATH}qemu-system-aarch64 \
195 -pflash $EFI_FLASH0 \
196 -pflash $EFI_FLASH1 \
197 -drive if=none,file=fat:rw:qemu-efi,id=drv \
198 -device virtio-blk-device,drive=drv"
200 QEMU_NONDEBUG=-nographic
201 # Now you'll need to create pflash volumes for UEFI. Two volumes are required,
202 # one static one for the UEFI firmware, and another dynamic one to store variables.
203 # Both need to be exactly 64M in size. //https://wiki.ubuntu.com/ARM64/QEMU
204 if ! [ -e $EFI_FLASH0 ] ; then
205 dd if=/dev/zero of="$EFI_FLASH0" bs=1M count=64
206 dd if=/usr/share/qemu-efi/QEMU_EFI.fd of="$EFI_FLASH0" conv=notrunc
208 [ -e $EFI_FLASH1 ] || dd if=/dev/zero of="$EFI_FLASH1" bs=1M count=64
212 QEMU_CMD="${QEMU_PATH}qemu-system-arm \
213 -machine xilinx-zynq-a9 \
218 QEMU_NONDEBUG=-nographic
221 echo "No QEmu environment defined for architecture=$ARCH." >&2
226 export QEMU_AUDIO_DRV=none
228 if test "$DEBUG_SCRIPT" = ""; then
229 echo "OK: about to run the follow qemu command:"
230 if test -z "$EFI"; then
231 if test -z "$IMAGE"; then
232 echo "$QEMU_CMD $QEMU_NONDEBUG -kernel $KERNEL -append '$KERNEL_CMDS' -initrd $INITRD"
233 exec $QEMU_CMD $QEMU_NONDEBUG -kernel $KERNEL -append '$KERNEL_CMDS' -initrd "$INITRD"
235 echo "$QEMU_CMD $QEMU_NONDEBUG -kernel $IMAGE"
236 exec $QEMU_CMD $QEMU_NONDEBUG -kernel "$IMAGE"
239 echo $QEMU_CMD $QEMU_NONDEBUG
240 exec $QEMU_CMD $QEMU_NONDEBUG
245 # Now we run the debugger instead
246 GDB_ARGS="-x $DEBUG_SCRIPT"
247 SERIAL_OUTPUT=file:/dev/stdout
248 PORT=$((10000 + UID))
250 if test "${SERIAL_OUTPUT}" = ""; then
251 # Assuming session is interactive. Use terminal for serial output because
252 # stdout does not work for daemonized qemu and output is lost. This likely
253 # only matters on ARM where there is no video driver at time of writing.
257 PIDFILE=/tmp/qemu_debugsim_${USER}_${PORT}.pid
258 if test -f $PIDFILE; then
259 if ps `cat $PIDFILE` >/dev/null; then
260 echo "Another QEMU already running (PID: `cat $PIDFILE` PIDFILE: $PIDFILE)"
263 echo "Deleting stale lockfile $PIDFILE"
268 echo args = $GDB_ARGS
270 cat > barrelfish_debug.gdb <<EOF
271 # Connect to QEMU instance
272 target remote localhost:$PORT
275 if test -z "$EFI"; then
276 if test -z "$IMAGE"; then
277 QEMU_INVOCATION="${QEMU_CMD} \
278 -kernel \"$KERNEL\" \
279 -append \"$KERNEL_CMDS\" \
280 -initrd \"$INITRD\" \
281 -serial $SERIAL_OUTPUT \
288 QEMU_INVOCATION="${QEMU_CMD} \
290 -append \"$KERNEL_CMDS\" \
291 -serial $SERIAL_OUTPUT \
299 QEMU_INVOCATION="${QEMU_CMD} \
300 -serial $SERIAL_OUTPUT \
308 echo $QEMU_INVOCATION
311 eval $QEMU_INVOCATION
313 if test $? -eq 0; then
316 ${GDB} -x barrelfish_debug.gdb ${GDB_ARGS}
318 kill ${PID} > /dev/null || true
321 echo Failed to launch qemu with:
322 echo " ${QEMU_INVOCATION}"