grub-shell.in 13.6 KB
Newer Older
1 2
#! /bin/sh
set -e
BVK Chaitanya's avatar
BVK Chaitanya committed
3 4

# Run GRUB script in a Qemu instance
5
# Copyright (C) 2009,2010  Free Software Foundation, Inc.
BVK Chaitanya's avatar
BVK Chaitanya committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#
# GRUB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GRUB is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.

# Initialize some variables.
21 22 23 24
prefix="@prefix@"
exec_prefix="@exec_prefix@"
datarootdir="@datarootdir@"
builddir="@builddir@"
25
srcdir="@srcdir@"
BVK Chaitanya's avatar
BVK Chaitanya committed
26 27 28 29 30
PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@

# Force build directory components
31
PATH="${builddir}:$PATH"
BVK Chaitanya's avatar
BVK Chaitanya committed
32 33
export PATH

34 35
trim=0

BVK Chaitanya's avatar
BVK Chaitanya committed
36 37 38 39 40 41 42 43 44
# Usage: usage
# Print the usage.
usage () {
    cat <<EOF
Usage: $0 [OPTION] [SOURCE]
Run GRUB script in a Qemu instance.

  -h, --help              print this message and exit
  -v, --version           print the version information and exit
45
  --boot=[fd|hd|cd|net]   boot method for Qemu instance
BVK Chaitanya's avatar
BVK Chaitanya committed
46
  --modules=MODULES       pre-load specified modules MODULES
47
  --qemu=FILE             Name of qemu binary
48
  --disk=FILE             Attach FILE as a disk
BVK Chaitanya's avatar
BVK Chaitanya committed
49
  --qemu-opts=OPTIONS     extra options to pass to Qemu instance
50
  --files=FILES           add files to the image
51 52
  --mkrescue-arg=ARGS     additional arguments to grub-mkrescue
  --timeout=SECONDS       set timeout
53
  --trim                  trim firmware output
BVK Chaitanya's avatar
BVK Chaitanya committed
54 55 56 57 58 59 60 61

$0 runs input GRUB script or SOURCE file in a Qemu instance and prints
its output.

Report bugs to <bug-grub@gnu.org>.
EOF
}

62
. "${builddir}/grub-core/modinfo.sh"
63
qemuopts="${GRUB_QEMU_OPTS}"
64 65
serial_port=com0
serial_null=
66
halt_cmd=halt
67
pseries=n
68
disk="hda "
69
case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in
70 71 72 73 74 75 76
    *-emu)
	device_map=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
	boot=emu
	console=console
	disk=0
	# To skip "Welcome to GRUB" and color setttings
	trim=1
77
	serial_port=
78
	;;
79
    powerpc-ieee1275)
80
	boot=hd
81 82
	qemu=qemu-system-ppc
	console=console
83
	serial_port=escc-ch-b
84
	serial_null="-serial null"
85
	netbootext=elf
86
	trim=1
87 88
	;;

89 90 91 92 93 94 95 96 97 98
    sparc64-ieee1275)
	boot=cd
	qemu=qemu-system-sparc64
	console=
	serial_port=ieee1275/ttya
	trim=1
	qemuopts="$qemuopts -no-reboot"
	halt_cmd=reboot
	;;

99 100 101
    mips-qemu_mips)
	boot=mips_qemu
	qemu=qemu-system-mips
102
	qemuopts="-M mips $qemuopts"
103 104
	console=vga_text
	;;
105 106 107
    mips-arc)
	boot=cd
	qemu=qemu-system-mips64
108
	qemuopts="-M indy $qemuopts"
109 110
	serial_port=arc/serial0/line0
	console=
111 112
	trim=1
	;;
113 114 115
    mipsel-arc)
	boot=cd
	qemu=qemu-system-mips64el
116
	qemuopts="-M magnum $qemuopts -no-reboot"
117 118 119 120 121
	serial_port=arc/multi0/serial0
	console=console
	halt_cmd=reboot
	trim=1
	;;
122 123 124
    mipsel-qemu_mips)
	boot=mipsel_qemu
	qemu=qemu-system-mipsel
125
	qemuopts="-M mips $qemuopts"
126 127
	console=vga_text
	;;
128 129 130
    mipsel-loongson)
	boot=mipsel_fulong2e
	qemu=qemu-system-mips64el
131
	qemuopts="-M fulong2e $qemuopts"
132 133 134
	console=
	trim=1
	;;
135 136 137 138 139 140 141 142 143 144 145
    i386-coreboot)
	boot=coreboot
	qemu=qemu-system-i386
	console=vga_text
	;;
    i386-multiboot)
	boot=cd
	qemu=qemu-system-i386
	console=vga_text;;

    i386-ieee1275)
146
	boot=hd
147
	qemu=qemu-system-i386
148 149
	console=console
	trim=1
150
	disk="hdb "
151
	;;
152 153 154 155 156 157 158 159
    i386-qemu)
	boot=qemu
	qemu=qemu-system-i386
	console=vga_text;;

    i386-pc)
	boot=cd
	qemu=qemu-system-i386
160 161 162
	console=console
	netbootext=0
	;;
163 164 165 166

    i386-efi)
	qemu=qemu-system-i386
	boot=cd
167 168
	console=console
	trim=1
169
	qemuopts="-bios OVMF-ia32.fd $qemuopts"
170
	;;
171 172 173
    x86_64-efi)
	qemu=qemu-system-x86_64
	boot=cd
174 175
	console=console
	trim=1
176
	qemuopts="-bios OVMF.fd $qemuopts"
177
	;;
178 179 180 181 182 183 184
    arm64-efi)
	qemu=qemu-system-aarch64
	boot=hd
	console=console
	trim=1
	qemuopts="-machine virt -cpu cortex-a57 -bios /usr/share/qemu-efi/QEMU_EFI.fd $qemuopts"
	disk="device virtio-blk-device,drive=hd1 -drive if=none,id=hd1,file="
185
	serial_port=
186
	;;
187 188 189 190 191 192 193 194 195
     arm-efi)
	qemu=qemu-system-arm
	boot=hd
	console=console
	trim=1
	qemuopts="-machine virt -bios /usr/share/ovmf-arm/QEMU_EFI.fd $qemuopts"
	disk="device virtio-blk-device,drive=hd1 -drive if=none,id=hd1,file="
	serial_port=efi0
	;;
196 197 198 199 200
    *)
	boot=hd
	qemu=qemu-system-i386
	console=console;;
esac
201

202
timeout=60
203
mkimage_extra_arg=
204

BVK Chaitanya's avatar
BVK Chaitanya committed
205 206 207 208 209 210 211 212 213
# Check the arguments.
for option in "$@"; do
    case "$option" in
    -h | --help)
	usage
	exit 0 ;;
    -v | --version)
	echo "$0 (GNU GRUB ${PACKAGE_VERSION})"
	exit 0 ;;
214 215 216
    --trim)
	trim=1
	;;
217 218
    --debug)
        debug=1 ;;
BVK Chaitanya's avatar
BVK Chaitanya committed
219 220 221
    --modules=*)
	ms=`echo "$option" | sed -e 's/--modules=//' -e 's/,/ /g'`
	modules="$modules $ms" ;;
222 223 224
    --files=*)
	fls=`echo "$option" | sed -e 's/--files=//' -e 's/,/ /g'`
	files="$files $fls" ;;
225 226 227
    --mkrescue-arg=*)
	mkr=`echo "$option" | sed -e 's/--mkrescue-arg=//' -e 's/,/ /g'`
	mkrescue_args="$mkrescue_args $mkr" ;;
228 229
    --qemu=*)
	qemu=`echo "$option" | sed -e 's/--qemu=//' -e 's/,/ /g'`;;
230 231 232 233
    --pseries)
	qemu=qemu-system-ppc64
	serial_port=ieee1275/hvterm
	serial_null=
234
	qemuopts="$qemuopts -M pseries -no-reboot"
235
	trim=1
236
	pseries=y
237
	    ;;
BVK Chaitanya's avatar
BVK Chaitanya committed
238 239 240
    --qemu-opts=*)
        qs=`echo "$option" | sed -e 's/--qemu-opts=//'`
        qemuopts="$qemuopts $qs" ;;
241 242 243 244 245 246
    --disk=*)
        dsk=`echo "$option" | sed -e 's/--disk=//'`
	if [ ${grub_modinfo_platform} = emu ]; then
	    echo "(hd$disk)  $dsk" >> "$device_map"
	    disk="$((disk+1))"
	else
247
	    if [ "$disk" = error ]; then
248 249 250
		echo "Too many disks" 1>&2
		exit 1;
	    fi
251 252 253 254
            qemuopts="$qemuopts -$disk$dsk"
	    if [ "$disk" = "hda " ]; then
		disk="hdb ";
	    elif [ "$disk" = "hdb " ]; then
255
		# CDROM is hdc
256 257
		disk="hdd "
	    elif [ "$disk" = "hdd " ]; then
258 259 260 261 262
		# CDROM is hdc
		disk=error
	    fi
	fi
	;;
263 264 265
    --timeout=*)
        timeout=`echo "$option" | sed -e 's/--timeout=//'`
	;;
266 267 268 269 270 271 272

    # Intentionally undocumented
    --grub-mkimage-extra)
	mkimage_extra_arg="$mkimage_extra_arg `argument $option "$@"`"; shift ;;
    --grub-mkimage-extra=*)
	mkimage_extra_arg="$mkimage_extra_arg `echo "$option" | sed 's/--grub-mkimage-extra=//'`" ;;

273 274
    --boot=*)
        dev=`echo "$option" | sed -e 's/--boot=//'`
275 276 277
	if   [ "$dev" = "fd" ] ; then boot=fd;
	elif [ "$dev" = "hd" ] ; then boot=hd;
	elif [ "$dev" = "cd" ] ; then boot=cd;
278
	elif [ "$dev" = "net" ] ; then boot=net;
279 280
	elif [ "$dev" = "qemu" ] ; then boot=qemu;
	elif [ "$dev" = "coreboot" ] ; then boot=coreboot;
281
	elif [ "$dev" = "mips_qemu" ] ; then boot=mips_qemu;
282 283
	elif [ "$dev" = "mipsel_qemu" ] ; then boot=mipsel_qemu;
	elif [ "$dev" = "mipsel_fulong2e" ] ; then boot=mipsel_fulong2e;
284 285 286 287 288
	else
	    echo "Unrecognized boot method \`$dev'" 1>&2
	    usage
	    exit 1
	fi ;;
BVK Chaitanya's avatar
BVK Chaitanya committed
289 290 291
    -*)
	echo "Unrecognized option \`$option'" 1>&2
	usage
292
	exit 1 ;;
BVK Chaitanya's avatar
BVK Chaitanya committed
293 294 295 296 297 298 299 300 301 302 303
    *)
	if [ "x${source}" != x ] ; then
	    echo "too many parameters at the end" 1>&2
	    usage
	    exit 1
	fi
	source="${option}" ;;
    esac
done

if [ "x${source}" = x ] ; then
304
    tmpfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
305
    while read REPLY; do
306
	echo "$REPLY" >> ${tmpfile}
307 308 309 310
    done
    source=${tmpfile}
fi

311
cfgfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
BVK Chaitanya's avatar
BVK Chaitanya committed
312 313
cat <<EOF >${cfgfile}
grubshell=yes
314 315
enable_progress_indicator=0
export enable_progress_indicator
316
EOF
317 318 319 320 321 322


if [ "${grub_modinfo_platform}" != emu ]; then
    echo insmod serial >>${cfgfile}
fi

323 324 325
if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = powerpc-ieee1275 ]; then
    echo insmod escc >>${cfgfile}
fi
326
if [ "${serial_port}" != "" ]; then
327 328 329 330 331 332
    echo "serial ${serial_port}" >>${cfgfile}
    term="serial_${serial_port}"
else
    term=console
fi

333
cat <<EOF >>${cfgfile}
334
terminfo -g 1024x1024 ${term} dumb
335 336
terminal_input ${term}
terminal_output ${term}
BVK Chaitanya's avatar
BVK Chaitanya committed
337 338
EOF

339 340 341 342 343 344
trim_head=664cbea8-132f-4770-8aa4-1696d59ac35c

if [ $trim = 1 ]; then
    echo "echo $trim_head" >>${cfgfile}
fi

345
rom_directory=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
346

BVK Chaitanya's avatar
BVK Chaitanya committed
347 348
for mod in ${modules}
do
349
    echo "insmod ${mod}" >> ${cfgfile}
BVK Chaitanya's avatar
BVK Chaitanya committed
350 351 352
done

cat <<EOF >>${cfgfile}
353
source "\$prefix/testcase.cfg"
354
# Stop serial output to suppress "ACPI shutdown failed" error.
BVK Chaitanya's avatar
BVK Chaitanya committed
355
EOF
356 357
# Attempt to switch to console on i386-ieee1275 causes "screen not found" message
if [ x$console != x ] && [ x"${grub_modinfo_target_cpu}-${grub_modinfo_platform}" != xi386-ieee1275 ]; then
358 359
    echo "terminal_output $console" >>${cfgfile}
fi
360
echo "${halt_cmd}" >>${cfgfile}
BVK Chaitanya's avatar
BVK Chaitanya committed
361

362 363 364 365
test -z "$debug" || echo "GRUB script: ${cfgfile}" >&2
test -z "$debug" || echo "GRUB testcase script: ${tmpfile}" >&2
test -z "$debug" || echo "Boot device: ${boot}" >&2

366
isofile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
367 368 369 370 371 372 373
test -z "$debug" || echo "GRUB ISO file: ${isofile}" >&2
test -z "$debug" || echo "GRUB ROM directory: ${rom_directory}" >&2

if test -z "$debug"; then
  qemuopts="${qemuopts} -nographic -monitor file:/dev/null"
fi

374
if [ x$boot != xnet ] && [ x$boot != xemu ]; then
375
    pkgdatadir="@builddir@" "@builddir@/grub-mkrescue" "--output=${isofile}" "--override-directory=${builddir}/grub-core" \
376
	--rom-directory="${rom_directory}" \
377
	--locale-directory="@srcdir@/po" \
378 379
	--themes-directory="@srcdir@/themes" \
	$mkimage_extra_arg ${mkrescue_args} \
380
	"/boot/grub/grub.cfg=${cfgfile}" "/boot/grub/testcase.cfg=${source}" \
381 382
	${files} >/dev/null 2>&1
fi
383
if [ x$boot = xhd ]; then
384
    if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = arm64-efi ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = arm-efi ]; then
385 386
	device="device virtio-blk-device,drive=hd0 -drive if=none,id=hd0,file="
    elif [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = mips-arc ]; then
387
	device="hdb "
388
    else
389
	device="hda "
390
    fi
391
    bootdev="-boot c"
392
fi
393
if [ x$boot = xcd ]; then
394
    if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = arm64-efi ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = arm-efi ]; then
395 396
	device="device virtio-blk-device,drive=cd0 -drive if=none,id=cd0,media=cdrom,file="
    elif [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = powerpc-ieee1275 ] && [ x$pseries != xy ] ; then
397 398 399 400
	device="-drive if=ide,media=cdrom,file="
    else
	device="cdrom "
    fi
401
    bootdev="-boot d"
402 403
fi
if [ x$boot = xfd ]; then
404
    device="fda "
405 406
    bootdev="-boot a"
fi
407

408 409
if [ x$boot = xqemu ]; then
    bootdev="-bios ${rom_directory}/qemu.img"
410
    device="cdrom "
411
fi
412

413 414
if [ x$boot = xmipsel_qemu ]; then
    bootdev="-kernel ${rom_directory}/mipsel-qemu_mips.elf"
415
    device="cdrom "
416 417
fi

418 419
if [ x$boot = xmipsel_fulong2e ]; then
    bootdev="-kernel ${rom_directory}/mipsel-loongson.elf -append machtype=lemote-fuloong-2e"
420
    device="cdrom "
421 422
fi

423 424
if [ x$boot = xmips_qemu ]; then
    bootdev="-kernel ${rom_directory}/mips-qemu_mips.elf"
425
    device="cdrom "
426 427
fi

428
if [ x$boot = xcoreboot ]; then
429
    imgfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
430
    cp "${GRUB_COREBOOT_ROM}" "${imgfile}"
431
    "${GRUB_CBFSTOOL}" "${imgfile}" add-payload -f "${rom_directory}/coreboot.elf" -n fallback/payload
432
    bootdev="-bios ${imgfile}"
433
    device="cdrom "
434
    test -z "$debug" || echo "Coreboot image: ${imgfile}" >&2
435
fi
BVK Chaitanya's avatar
BVK Chaitanya committed
436

437 438 439 440 441 442 443 444 445
if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = mipsel-arc ]; then
    case "$boot" in
	hd)
	    bootdev="-global ds1225y.filename=$GRUB_QEMU_MAGNUM_NVRAM_DIR/disk" ;;
	*)
	    bootdev="-global ds1225y.filename=$GRUB_QEMU_MAGNUM_NVRAM_DIR/cdrom";;
    esac
fi

446 447 448 449 450 451 452 453 454
do_trim ()
{
    if [ $trim = 1 ]; then
	awk '{ if (have_head == 1) print $0; } /664cbea8-132f-4770-8aa4-1696d59ac35c/ { have_head=1; }'
    else
	cat
    fi
}

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
copy_extra_files() {
    _destdir="$1"
    shift

    # FIXME support '=' in file names
    for _file in "$@"; do
	_target="${_file%=*}"
	_source="${_file#*=}"
	[ -n "$_source" ] || _source="$_target"
	_target="$_destdir/$_target"
	_targetdir="$(dirname "$_target")"
	[ -d "$_targetdir" ] || mkdir -p "$_targetdir"
	cp "$_source" "$_target"
    done
}

471
if [ x$boot = xnet ]; then
472
    netdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
473
    pkgdatadir="@builddir@" "@builddir@/grub-mknetdir" "--grub-mkimage=${builddir}/grub-mkimage" "--directory=${builddir}/grub-core" "--net-directory=$netdir" ${mkrescue_args} > /dev/null
474 475
    cp "${cfgfile}" "$netdir/boot/grub/grub.cfg"
    cp "${source}" "$netdir/boot/grub/testcase.cfg"
476
    [ -z "$files" ] || copy_extra_files "$netdir" $files
477
    timeout -s KILL $timeout "${qemu}" ${qemuopts} ${serial_null} -serial file:/dev/stdout -boot n -net "user,tftp=$netdir,bootfile=/boot/grub/${grub_modinfo_target_cpu}-${grub_modinfo_platform}/core.$netbootext"  -net nic  | cat | tr -d "\r" | do_trim
478
elif [ x$boot = xemu ]; then
479 480
    rootdir="$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")"
    grubdir="$rootdir/boot/grub"
481
    mkdir -p "$grubdir/fonts"
482
    mkdir -p "$grubdir/themes"
483
    mkdir -p "$grubdir/locale"
484
    cp "@builddir@/"unicode.pf2 "$grubdir/fonts/unicode.pf2"
485
    cp -R "@srcdir@/themes/starfield" "$grubdir/themes/starfield"
486 487 488 489 490
    for file in "@srcdir@/po/"*.gmo; do
	if [ -f "$file" ]; then
	    cp "$file" "$grubdir/locale/"
	fi
    done
491 492
    cp "${cfgfile}" "$grubdir/grub.cfg"
    cp "${source}" "$grubdir/testcase.cfg"
493 494 495 496 497 498
    [ -z "$files" ] || copy_extra_files "$rootdir" $files
    roottar="$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")"
    (cd "$rootdir"; tar cf "$roottar" .)
    @builddir@/grub-core/grub-emu -m "$device_map" --memdisk "$roottar" -r memdisk -d "/boot/grub" | tr -d "\r" | do_trim
    test -n "$debug" || rm -rf "$rootdir"
    test -n "$debug" || rm -f "$roottar"
499
else
500
    timeout -s KILL $timeout "${qemu}" ${qemuopts} ${serial_null} -serial file:/dev/stdout -${device}"${isofile}" ${bootdev} | cat | tr -d "\r" | do_trim
501
fi
502
if [ x$boot = xcoreboot ]; then
503
    test -n "$debug" || rm -f "${imgfile}"
504
fi
505 506 507
test -n "$debug" || rm -f "${isofile}"
test -n "$debug" || rm -rf "${rom_directory}"
test -n "$debug" || rm -f "${tmpfile}" "${cfgfile}"
BVK Chaitanya's avatar
BVK Chaitanya committed
508 509 510
exit 0