summaryrefslogtreecommitdiff
path: root/debvm-run
blob: 87fe0d6e3bb21f249cd777739af25533b7a1f4c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/bin/sh
# Copyright 2022 Helmut Grohne <helmut@subdivi.de>
# SPDX-License-Identifier: MIT

set -u

IMAGE=rootfs.ext2
SSHPORT=
GRAPHICAL=

die() {
	echo "$*" 1>&2
	exit 1
}

usage() {
	die "usage: $0 [-g] [-i image] [-s sshport] [-- qemu options]"
}

while test "$#" -gt 0; do
	case "$1" in
		-g)
			GRAPHICAL=1
			shift
		;;
		-i)
			test "$#" -eq 1 && usage
			IMAGE=$2
			shift 2
		;;
		-s)
			test "$#" -eq 1 && usage
			SSHPORT=$2
			shift 2
		;;
		--)
			shift
			break
		;;
		*)
			usage
		;;
	esac
done

test -f "$IMAGE" || die "image '$IMAGE' not found"

KERNELNAME=$(/sbin/debugfs "$IMAGE" -R "stat vmlinuz" | sed 's/Fast link dest: "\(.*\)"/\1/;t;d')
INITRDNAME=$(/sbin/debugfs "$IMAGE" -R "stat initrd.img" | sed 's/Fast link dest: "\(.*\)"/\1/;t;d')

cleanup() {
	set +x
	test -n "$KERNELTMP" && rm -f "$KERNELTMP"
	test -n "$INITRDTMP" && rm -f "$INITRDTMP"
}

trap cleanup EXIT INT TERM QUIT

KERNELTMP=$(mktemp)
INITRDTMP=$(mktemp)

ARCHITECTURE=$(dpkg --print-architecture)
VMARCH=$ARCHITECTURE
if command -v elf-arch >/dev/null 2>&1; then
	/sbin/debugfs "$IMAGE" -R "cat /bin/true" > "$KERNELTMP"
	VMARCH=$(elf-arch "$KERNELTMP")
fi
case "$VMARCH" in
	arm64|s390x)
		DISKDEV=vda
	;;
	*)
		DISKDEV=sda
	;;
esac

KERNEL_CMDLINE=root=/dev/$DISKDEV
NETDEV="user,id=net0"

set -- \
	-m 1G \
	-smp "$(nproc)" \
	-kernel "$KERNELTMP" \
	-initrd "$INITRDTMP" \
	-drive "media=disk,format=raw,discard=unmap,file=$IMAGE" \
	-device "virtio-net-pci,netdev=net0" \
	"$@"

if test "$ARCHITECTURE" = "$VMARCH"; then
	QEMU=kvm
	# While kvm will fall back gracefully, the following options can only
	# be passed when kvm really is available.
	if test -w /dev/kvm; then
		set -- -enable-kvm -cpu host "$@"
	fi
else
	case "$VMARCH" in
		arm64)
			QEMU=qemu-system-aarch64
			set -- -machine virt -cpu max "$@"
		;;
		*)
			QEMU="qemu-system-$VMARCH"
		;;
	esac
fi
if test "$VMARCH" = arm64; then
	set -- -nographic "$@"
elif test "$VMARCH" = s390x; then
	set -- -M s390-ccw-virtio -nographic "$@"
elif test -z "$GRAPHICAL"; then
	KERNEL_CMDLINE="$KERNEL_CMDLINE console=ttyS0"
	set -- -nographic "$@"
fi
if test -n "$SSHPORT"; then
	NETDEV="$NETDEV,hostfwd=tcp:127.0.0.1:$SSHPORT-:22"
fi
set -- \
	-append "$KERNEL_CMDLINE" \
	-netdev "$NETDEV" \
	"$@"

set -ex

/sbin/debugfs "$IMAGE" -R "cat $KERNELNAME" > "$KERNELTMP"
/sbin/debugfs "$IMAGE" -R "cat $INITRDNAME" > "$INITRDTMP"

"$QEMU" "$@"