diff --git a/conf/common.rmk b/conf/common.rmk
index 31b62892b..905024a55 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -695,4 +695,9 @@ bin_UTILITIES += grub-mkpasswd-pbkdf2
grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/err.c
grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1
+# Randomly generated
+SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d
+
+bootcheck: $(BOOTCHECKS)
+
include $(srcdir)/conf/gcry.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index a89203dea..33575a87c 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -368,5 +368,15 @@ pkglib_DATA += efiemu32.o efiemu64.o
endif
+BOOTTARGET=bios-cd
+
+bootcheck-linux16-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/tests/boot/linux.cfg grub-shell
+ timeout -s KILL 30s ./grub-shell --boot=$(BOOTTARGET) --qemu=qemu-system-i386 --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
+
+bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/tests/boot/linux.cfg grub-shell
+ timeout -s KILL 30s ./grub-shell --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
+
+BOOTCHECKS+=bootcheck-linux16-i386 bootcheck-linux16-x86_64
+
include $(srcdir)/conf/i386.mk
include $(srcdir)/conf/common.mk
diff --git a/conf/i386.rmk b/conf/i386.rmk
index 7ef337c61..9305bf09c 100644
--- a/conf/i386.rmk
+++ b/conf/i386.rmk
@@ -41,3 +41,24 @@ multiboot2_mod_SOURCES = loader/i386/multiboot.c \
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)
+
+linuxinit.x86_64: $(srcdir)/tests/boot/linuxinit-x86_64.S
+ $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
+
+linuxinit.i386: $(srcdir)/tests/boot/linuxinit-i386.S
+ $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
+
+linux-initramfs.%: linuxinit.% Makefile
+ TDIR=`mktemp -d`; (cp $< $$TDIR/init; cd $$TDIR; echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@; rm -rf $$TDIR
+
+CLEANFILES += linuxinit.i386 linuxinit.x86_64 linux-initramfs.i386 linux-initramfs.x86_64
+
+bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/tests/boot/linux.cfg grub-shell
+ timeout -s KILL 30s ./grub-shell --boot=$(BOOTTARGET) --qemu=qemu-system-i386 --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
+
+bootcheck-linux-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/tests/boot/linux.cfg grub-shell
+ timeout -s KILL 30s ./grub-shell --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
+
+BOOTCHECKS+=bootcheck-linux-i386 bootcheck-linux-x86_64
+
+.PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64
diff --git a/tests/boot/linux.cfg b/tests/boot/linux.cfg
new file mode 100644
index 000000000..201de99fd
--- /dev/null
+++ b/tests/boot/linux.cfg
@@ -0,0 +1,3 @@
+linux /linux console=ttyS0 root=/dev/ram0
+initrd /initrd
+boot
diff --git a/tests/boot/linux16.cfg b/tests/boot/linux16.cfg
new file mode 100644
index 000000000..ed0a50872
--- /dev/null
+++ b/tests/boot/linux16.cfg
@@ -0,0 +1,3 @@
+linux16 /linux console=ttyS0 root=/dev/ram0
+initrd16 /initrd
+boot
diff --git a/tests/boot/linuxinit-i386.S b/tests/boot/linuxinit-i386.S
new file mode 100644
index 000000000..a79a5787e
--- /dev/null
+++ b/tests/boot/linuxinit-i386.S
@@ -0,0 +1,55 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * 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 .
+ */
+
+#define SYSCALL_WRITE 4
+#define SYSCALL_RESET 88
+#define SYSCALL_EXIT 1
+#define SYSCALL_INT 0x80
+
+#define STDOUT 1
+#define SHUTDOWN_MAGIC1 0xfee1dead
+#define SHUTDOWN_MAGIC2 0x28121969
+#define SHUTDOWN_MAGIC3 0x4321fedc
+
+ .text
+ .global start, _start
+_start:
+start:
+ /* write. */
+ movl $SYSCALL_WRITE, %eax
+ movl $STDOUT, %ebx
+ leal message, %ecx
+ movl $(messageend-message), %edx
+ int $SYSCALL_INT
+
+ /* shutdown. */
+ movl $SYSCALL_RESET, %eax
+ movl $SHUTDOWN_MAGIC1, %ebx
+ movl $SHUTDOWN_MAGIC2, %ecx
+ movl $SHUTDOWN_MAGIC3, %edx
+ int $SYSCALL_INT
+
+ /* exit (1). Shouldn't be reached. */
+ movl $SYSCALL_EXIT, %eax
+ movl $1, %ebx
+ int $SYSCALL_INT
+ .data
+message:
+ .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n"
+messageend:
+
\ No newline at end of file
diff --git a/tests/boot/linuxinit-x86_64.S b/tests/boot/linuxinit-x86_64.S
new file mode 100644
index 000000000..17ba8040c
--- /dev/null
+++ b/tests/boot/linuxinit-x86_64.S
@@ -0,0 +1,54 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * 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 .
+ */
+
+#define SYSCALL_WRITE 1
+#define SYSCALL_RESET 169
+#define SYSCALL_EXIT 60
+
+#define STDOUT 1
+#define SHUTDOWN_MAGIC1 0xfee1dead
+#define SHUTDOWN_MAGIC2 0x28121969
+#define SHUTDOWN_MAGIC3 0x4321fedc
+
+ .text
+ .global start, _start
+_start:
+start:
+ /* write. */
+ movq $SYSCALL_WRITE, %rax
+ movq $STDOUT, %rdi
+ leaq message, %rsi
+ movq $(messageend-message), %rdx
+ syscall
+
+ /* shutdown. */
+ movq $SYSCALL_RESET, %rax
+ movq $SHUTDOWN_MAGIC1, %rdi
+ movq $SHUTDOWN_MAGIC2, %rsi
+ movq $SHUTDOWN_MAGIC3, %rdx
+ syscall
+
+ /* exit(1). Shouldn't be reached. */
+ movq $SYSCALL_EXIT, %rax
+ movq $1, %rdi
+ syscall
+ .data
+message:
+ .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n"
+messageend:
+
\ No newline at end of file
diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in
index e6fef8313..ee0cded55 100644
--- a/tests/util/grub-shell.in
+++ b/tests/util/grub-shell.in
@@ -44,7 +44,9 @@ Run GRUB script in a Qemu instance.
-v, --version print the version information and exit
--boot=[fd|hd|cd] boot method for Qemu instance
--modules=MODULES pre-load specified modules MODULES
+ --qemu=FILE Name of qemu binary
--qemu-opts=OPTIONS extra options to pass to Qemu instance
+ --files=FILES add files to the image
$0 runs input GRUB script or SOURCE file in a Qemu instance and prints
its output.
@@ -53,6 +55,9 @@ Report bugs to .
EOF
}
+boot=bios-hd
+qemu=qemu-system-i386
+
# Check the arguments.
for option in "$@"; do
case "$option" in
@@ -65,14 +70,19 @@ for option in "$@"; do
--modules=*)
ms=`echo "$option" | sed -e 's/--modules=//' -e 's/,/ /g'`
modules="$modules $ms" ;;
+ --files=*)
+ fls=`echo "$option" | sed -e 's/--files=//' -e 's/,/ /g'`
+ files="$files $fls" ;;
+ --qemu=*)
+ qemu=`echo "$option" | sed -e 's/--qemu=//' -e 's/,/ /g'`;;
--qemu-opts=*)
qs=`echo "$option" | sed -e 's/--qemu-opts=//'`
qemuopts="$qemuopts $qs" ;;
--boot=*)
dev=`echo "$option" | sed -e 's/--boot=//'`
- if [ "$dev" = "fd" ] ; then bootdev=a;
- elif [ "$dev" = "hd" ] ; then bootdev=c;
- elif [ "$dev" = "cd" ] ; then bootdev=d;
+ if [ "$dev" = "bios-fd" ] ; then boot=bios-fd;
+ elif [ "$dev" = "bios-hd" ] ; then boot=bios-hd;
+ elif [ "$dev" = "bios-cd" ] ; then boot=bios-cd;
else
echo "Unrecognized boot method \`$dev'" 1>&2
usage
@@ -100,10 +110,6 @@ if [ "x${source}" = x ] ; then
source=${tmpfile}
fi
-if [ "x${bootdev}" = x ] ; then
- bootdev=c # default is boot as disk image
-fi
-
cfgfile=`mktemp`
cat <${cfgfile}
grubshell=yes
@@ -123,23 +129,28 @@ source /boot/grub/testcase.cfg
halt
EOF
-isofile=`mktemp`
-grub-mkrescue --output=${isofile} --override-directory=${builddir} \
- /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \
- >/dev/null 2>&1
+if [ x$boot = xbios-hd ] || [ x$boot = xbios-fd ] || [ x$boot = xbios-cd ]; then
+ isofile=`mktemp`
+ grub-mkrescue --output=${isofile} --override-directory=${builddir} \
+ /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \
+ ${files} >/dev/null 2>&1
+ if [ x$boot = xbios-hd ]; then
+ device=hda
+ bootdev=c
+ fi
+ if [ x$boot = xbios-cd ]; then
+ device=cdrom
+ bootdev=d
+ fi
+ if [ x$boot = xbios-fd ]; then
+ device=fda
+ bootdev=a
+ fi
+ ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} -boot ${bootdev} | tr -d "\r"
+ rm -f ${isofile}
+fi
-hdafile=`mktemp`
-cp ${isofile} ${hdafile}
-
-fdafile=`mktemp`
-cp ${isofile} ${fdafile}
-
-outfile=`mktemp`
-qemu-system-i386 ${qemuopts} -nographic -serial stdio -hda ${hdafile} -fda ${fdafile} -cdrom ${isofile} -boot ${bootdev} | tr -d "\r" >${outfile}
-
-cat $outfile
-
-rm -f ${tmpfile} ${outfile} ${cfgfile} ${isofile} ${hdafile} ${fdafile}
+rm -f ${tmpfile} ${cfgfile}
exit 0