aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgignore3
-rw-r--r--extras/mini-os/arch/x86/mm.c2
-rw-r--r--extras/mini-os/blkfront.c8
-rw-r--r--extras/mini-os/fbfront.c24
-rw-r--r--extras/mini-os/include/x86/arch_mm.h2
-rw-r--r--extras/mini-os/main.c4
-rw-r--r--extras/mini-os/netfront.c13
-rw-r--r--stubdom/Makefile41
-rw-r--r--stubdom/README69
-rw-r--r--stubdom/grub.patches/10graphics.diff2299
-rw-r--r--stubdom/grub.patches/20print_func.diff80
-rw-r--r--stubdom/grub.patches/30savedefault.diff186
-rw-r--r--stubdom/grub.patches/40ext3_256byte_inode.diff114
-rw-r--r--stubdom/grub.patches/99minios1456
-rw-r--r--stubdom/grub/Makefile76
-rw-r--r--stubdom/grub/boot-x86_32.S112
-rw-r--r--stubdom/grub/boot-x86_64.S108
-rw-r--r--stubdom/grub/config.h11
-rw-r--r--stubdom/grub/kexec.c324
-rw-r--r--stubdom/grub/mini-os.c702
-rw-r--r--stubdom/grub/mini-os.h5
-rw-r--r--stubdom/grub/osdep.h30
-rw-r--r--tools/libxc/xc_dom.h3
-rw-r--r--tools/libxc/xc_dom_core.c6
24 files changed, 5654 insertions, 24 deletions
diff --git a/.hgignore b/.hgignore
index 183af2d72e..fa674adcaf 100644
--- a/.hgignore
+++ b/.hgignore
@@ -94,6 +94,9 @@
^stubdom/newlib-.*$
^stubdom/pciutils-.*$
^stubdom/zlib-.*$
+^stubdom/grub-cvs$
+^stubdom/grub/stage2$
+^stubdom/grub/netboot$
^tools/.*/TAGS$
^tools/.*/build/lib.*/.*\.py$
^tools/blktap/Makefile\.smh$
diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index 96c433b135..ea8158045b 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -372,7 +372,7 @@ static pgentry_t *get_pgt(unsigned long addr)
return &tab[offset];
}
-static pgentry_t *need_pgt(unsigned long addr)
+pgentry_t *need_pgt(unsigned long addr)
{
unsigned long mfn;
pgentry_t *tab;
diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c
index 9e5411bce6..48704bd1c4 100644
--- a/extras/mini-os/blkfront.c
+++ b/extras/mini-os/blkfront.c
@@ -242,9 +242,15 @@ void shutdown_blkfront(struct blkfront_dev *dev)
err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
xenbus_wait_for_value(path, "6", &dev->events);
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ xenbus_wait_for_value(path, "2", &dev->events);
+
xenbus_unwatch_path(XBT_NIL, path);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ snprintf(path, sizeof(path), "%s/ring-ref", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/event-channel", nodename);
+ xenbus_rm(XBT_NIL, path);
free_blkfront(dev);
}
diff --git a/extras/mini-os/fbfront.c b/extras/mini-os/fbfront.c
index 6517cdf4b5..245ef468ed 100644
--- a/extras/mini-os/fbfront.c
+++ b/extras/mini-os/fbfront.c
@@ -229,9 +229,18 @@ void shutdown_kbdfront(struct kbdfront_dev *dev)
err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
xenbus_wait_for_value(path, "6", &dev->events);
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ // does not work yet.
+ //xenbus_wait_for_value(path, "2", &dev->events);
+
xenbus_unwatch_path(XBT_NIL, path);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ snprintf(path, sizeof(path), "%s/page-ref", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/event-channel", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/request-abs-pointer", nodename);
+ xenbus_rm(XBT_NIL, path);
free_kbdfront(dev);
}
@@ -561,9 +570,20 @@ void shutdown_fbfront(struct fbfront_dev *dev)
err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
xenbus_wait_for_value(path, "6", &dev->events);
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ // does not work yet
+ //xenbus_wait_for_value(path, "2", &dev->events);
+
xenbus_unwatch_path(XBT_NIL, path);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ snprintf(path, sizeof(path), "%s/page-ref", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/event-channel", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/protocol", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/feature-update", nodename);
+ xenbus_rm(XBT_NIL, path);
unbind_evtchn(dev->evtchn);
diff --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h
index a7e013bc06..4a04812891 100644
--- a/extras/mini-os/include/x86/arch_mm.h
+++ b/extras/mini-os/include/x86/arch_mm.h
@@ -221,4 +221,6 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
#define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, 0, L1_PROT_RO)
#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, 0, L1_PROT_RO)
+pgentry_t *need_pgt(unsigned long addr);
+
#endif /* _ARCH_MM_H_ */
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index 6c26e96057..dac185a528 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -59,11 +59,13 @@ static void call_main(void *p)
* crashing. */
//sleep(1);
+#ifndef CONFIG_GRUB
sparse((unsigned long) &__app_bss_start, &__app_bss_end - &__app_bss_start);
#ifdef HAVE_LWIP
start_networking();
#endif
init_fs_frontend();
+#endif
#ifdef CONFIG_QEMU
if (!fs_import) {
@@ -154,7 +156,7 @@ void _exit(int ret)
#ifdef HAVE_LWIP
stop_networking();
#endif
- unbind_all_ports();
+ stop_kernel();
if (!ret) {
/* No problem, just shutdown. */
struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
index 00f159c332..d01ce6927b 100644
--- a/extras/mini-os/netfront.c
+++ b/extras/mini-os/netfront.c
@@ -497,15 +497,26 @@ void shutdown_netfront(struct netfront_dev *dev)
printk("close network: backend at %s\n",dev->backend);
snprintf(path, sizeof(path), "%s/state", dev->backend);
+
err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
xenbus_wait_for_value(path, "5", &dev->events);
err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
xenbus_wait_for_value(path, "6", &dev->events);
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ xenbus_wait_for_value(path, "2", &dev->events);
+
xenbus_unwatch_path(XBT_NIL, path);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ snprintf(path, sizeof(path), "%s/tx-ring-ref", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/rx-ring-ref", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/event-channel", nodename);
+ xenbus_rm(XBT_NIL, path);
+ snprintf(path, sizeof(path), "%s/request-rx-copy", nodename);
+ xenbus_rm(XBT_NIL, path);
free_netfront(dev);
}
diff --git a/stubdom/Makefile b/stubdom/Makefile
index 77d7e4d299..5197ecb87f 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -14,6 +14,7 @@ ZLIB_VERSION=1.2.3
LIBPCI_VERSION=2.2.9
NEWLIB_DATE=2008-01-01
LWIP_DATE=2008-06-01
+GRUB_DATE=2008-06-01
WGET=wget -c
@@ -39,10 +40,10 @@ CROSS_PREFIX=$(CURDIR)/$(CROSS_ROOT)
export CROSS_COMPILE=$(GNU_TARGET_ARCH)-xen-elf-
export PATH:=$(CROSS_PREFIX)/bin:$(PATH)
-TARGETS=ioemu c caml
+TARGETS=ioemu c caml grub
.PHONY: all
-all: ioemu-stubdom c-stubdom
+all: ioemu-stubdom c-stubdom pv-grub
################
# Cross-binutils
@@ -221,30 +222,53 @@ caml: cross-newlib mk-symlinks
c: cross-newlib mk-symlinks
$(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-cvs
+######
+# Grub
+######
+
+grub-cvs:
+ cvs -z 9 -d :pserver:anonymous@cvs.sv.gnu.org:/sources/grub co -D $(GRUB_DATE) -d $@ grub
+ for i in grub.patches/* ; do \
+ patch -d $@ -p1 < $$i ; \
+ done
+
+.PHONY: grub
+grub: grub-cvs cross-newlib mk-symlinks
+ $(MAKE) -C $@
+
########
# minios
########
.PHONY: ioemu-stubdom
ioemu-stubdom: mini-os-ioemu lwip-cvs libxc ioemu
- $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/ioemu/i386-dm-stubdom/qemu.a $(CURDIR)/ioemu/i386-dm-stubdom/libqemu.a" CFLAGS=-DCONFIG_QEMU
+ DEF_CFLAGS=-DCONFIG_QEMU $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/ioemu/i386-dm-stubdom/qemu.a $(CURDIR)/ioemu/i386-dm-stubdom/libqemu.a"
CAMLLIB = $(shell ocamlc -where)
.PHONY: caml-stubdom
caml-stubdom: mini-os-caml lwip-cvs libxc caml
- $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o $(CAMLLIB)/libasmrun.a" CFLAGS=-DCONFIG_CAML
+ DEF_CFLAGS=-DCONFIG_CAML $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o $(CAMLLIB)/libasmrun.a"
.PHONY: c-stubdom
c-stubdom: mini-os-c lwip-cvs libxc c
- $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS=$(CURDIR)/c/main.a CFLAGS=-DCONFIG_C
+ DEF_CFLAGS=-DCONFIG_C $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS=$(CURDIR)/c/main.a
+
+.PHONY: pv-grub
+pv-grub: mini-os-grub libxc grub
+ DEF_CFLAGS=-DCONFIG_GRUB $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< APP_OBJS=$(CURDIR)/grub/main.a
#########
# install
#########
-install: mini-os-ioemu/mini-os.gz
+install: install-ioemu install-grub
+
+install-ioemu: mini-os-ioemu/mini-os.gz
$(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin"
- $(INSTALL_PROG) $< "$(DESTDIR)/usr/lib/xen/boot/stubdom.gz"
+ $(INSTALL_PROG) $< "$(DESTDIR)/usr/lib/xen/boot/ioemu-stubdom.gz"
+
+install-grub: mini-os-grub/mini-os.gz
+ $(INSTALL_PROG) $< "$(DESTDIR)/usr/lib/xen/boot/pv-grub.gz"
#######
# clean
@@ -256,8 +280,10 @@ clean:
rm -fr mini-os-ioemu
rm -fr mini-os-c
rm -fr mini-os-caml
+ rm -fr mini-os-grub
$(MAKE) -C caml clean
$(MAKE) -C c clean
+ $(MAKE) -C grub clean
rm -fr libxc ioemu mini-os include
# clean the cross-compilation result
@@ -274,6 +300,7 @@ patchclean: crossclean
rm -fr gcc-$(GCC_VERSION)
rm -fr newlib-cvs
rm -fr lwip-cvs
+ rm -fr grub-cvs
# clean downloads
.PHONY: downloadclean
diff --git a/stubdom/README b/stubdom/README
index af0efd2927..a57cf7521e 100644
--- a/stubdom/README
+++ b/stubdom/README
@@ -6,12 +6,19 @@ Then make install to install the result.
Also, run make and make install in $XEN_ROOT/tools/fs-back
+
+
+ IOEMU stubdom
+ =============
+
+ This boosts HVM performance by putting ioemu in its own lightweight domain.
+
General Configuration
=====================
In your HVM config "hvmconfig",
-- use /usr/lib/xen/bin/stubdom-dm as dm script
+- use /usr/lib/xen/bin/stubdom-dm as dm script:
device_model = '/usr/lib/xen/bin/stubdom-dm'
@@ -25,7 +32,7 @@ device_model = '/usr/lib/xen/bin/stubdom-dm'
Create /etc/xen/stubdom-hvmconfig (where "hvmconfig" is the name of your HVM
guest) with
-kernel = "/usr/lib/xen/boot/stubdom.gz"
+kernel = "/usr/lib/xen/boot/ioemu-stubdom.gz"
vif = [ '', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
@@ -42,34 +49,36 @@ There are three posibilities
* Using SDL
-In hvmconfig, disable vnc:
+ - In hvmconfig, disable vnc and sdl:
vnc = 0
+sdl = 0
-In stubdom-hvmconfig, set a vfb:
+ - In stubdom-hvmconfig, set an sdl vfb:
vfb = [ 'type=sdl' ]
* Using a VNC server in the stub domain
-In hvmconfig, set vnclisten to "172.30.206.1" for instance. Do not use a host
-name as Mini-OS does not have a name resolver. Do not use 127.0.0.1 since then
-you will not be able to connect to it.
+ - In hvmconfig, set vnclisten to "172.30.206.1" for instance. Do not use a
+host name as Mini-OS does not have a name resolver. Do not use 127.0.0.1 since
+then you will not be able to connect to it.
vnc = 1
vnclisten = "172.30.206.1"
-In stubdom-hvmconfig, fill the reserved vif with the same IP, for instance:
+ - In stubdom-hvmconfig, fill the reserved vif with the same IP, for instance:
vif = [ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
* Using a VNC server in dom0
-In hvmconfig, disable vnc:
+ - In hvmconfig, disable vnc and sdl:
vnc = 0
+sdl = 0
-In stubdom-hvmconfig, set a vfb:
+ - In stubdom-hvmconfig, set a vnc vfb:
vfb = [ 'type=vnc' ]
@@ -85,3 +94,43 @@ ln -s /var/lib/xen /exports/var/lib
/usr/sbin/fs-backend &
xm create hvmconfig
+
+
+
+ PV-GRUB
+ =======
+
+ This replaces pygrub to boot domU images safely: it runs the regular grub
+inside the created domain itself and uses regular domU facilities to read the
+disk / fetch files from network etc. ; it eventually loads the PV kernel and
+chain-boots it.
+
+Configuration
+=============
+
+In your PV config,
+
+- use /usr/lib/xen/boot/pv-grub.gz as kernel:
+
+kernel = "/usr/lib/xen/boot/pv-grub.gz"
+
+- set the path to menu.lst, as seen from the domU, in extra:
+
+extra = "(hd0,0)/boot/grub/menu.lst"
+
+you can also use a tftp path (dhcp will be automatically performed):
+
+extra = "(nd)/somepath/menu.lst"
+
+or you can set it in option 150 of your dhcp server and leave extra empty
+
+Limitations
+===========
+
+- You can not boot a 64bit kernel with a 32bit-compiled PV-GRUB and vice-versa.
+To cross-compile a 32bit PV-GRUB,
+
+export XEN_TARGET_ARCH=x86_32
+
+- bootsplash is supported, but the ioemu backend does not yet support restart
+for use by the booted kernel.
diff --git a/stubdom/grub.patches/10graphics.diff b/stubdom/grub.patches/10graphics.diff
new file mode 100644
index 0000000000..d891c51353
--- /dev/null
+++ b/stubdom/grub.patches/10graphics.diff
@@ -0,0 +1,2299 @@
+diff -Naur grub-0.97.orig/configure.ac grub-0.97/configure.ac
+--- grub-0.97.orig/configure.ac 2005-05-07 23:36:03.000000000 -0300
++++ grub-0.97/configure.ac 2005-06-12 20:56:49.000000000 -0300
+@@ -595,6 +595,11 @@
+ [ --enable-diskless enable diskless support])
+ AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
+
++dnl Graphical splashscreen support
++AC_ARG_ENABLE(graphics,
++ [ --disable-graphics disable graphics terminal support])
++AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
++
+ dnl Hercules terminal
+ AC_ARG_ENABLE(hercules,
+ [ --disable-hercules disable hercules terminal support])
+diff -Naur grub-0.97.orig/stage2/asm.S grub-0.97/stage2/asm.S
+--- grub-0.97.orig/stage2/asm.S 2004-06-19 13:55:22.000000000 -0300
++++ grub-0.97/stage2/asm.S 2005-06-13 14:05:31.000000000 -0300
+@@ -2216,7 +2216,304 @@
+ pop %ebx
+ pop %ebp
+ ret
+-
++
++
++/* graphics mode functions */
++#ifdef SUPPORT_GRAPHICS
++VARIABLE(cursorX)
++.word 0
++VARIABLE(cursorY)
++.word 0
++VARIABLE(cursorCount)
++.word 0
++VARIABLE(cursorBuf)
++.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++
++
++/*
++ * set_int1c_handler(void)
++ */
++ENTRY(set_int1c_handler)
++ pushl %edi
++
++ /* save the original int1c handler */
++ movl $0x70, %edi
++ movw (%edi), %ax
++ movw %ax, ABS(int1c_offset)
++ movw 2(%edi), %ax
++ movw %ax, ABS(int1c_segment)
++
++ /* save the new int1c handler */
++ movw $ABS(int1c_handler), %ax
++ movw %ax, (%edi)
++ xorw %ax, %ax
++ movw %ax, 2(%edi)
++
++ popl %edi
++ ret
++
++
++/*
++ * unset_int1c_handler(void)
++ */
++ENTRY(unset_int1c_handler)
++ pushl %edi
++
++ /* check if int1c_handler is set */
++ movl $0x70, %edi
++ movw $ABS(int1c_handler), %ax
++ cmpw %ax, (%edi)
++ jne int1c_1
++ xorw %ax, %ax
++ cmpw %ax, 2(%edi)
++ jne int1c_1
++
++ /* restore the original */
++ movw ABS(int1c_offset), %ax
++ movw %ax, (%edi)
++ movw ABS(int1c_segment), %ax
++ movw %ax, 2(%edi)
++
++int1c_1:
++ popl %edi
++ ret
++
++
++/*
++ * blinks graphics cursor
++ */
++ .code16
++write_data:
++ movw $0, %ax
++ movw %ax, %ds
++
++ mov $0xA000, %ax /* video in es:di */
++ mov %ax, %es
++ mov $80, %ax
++ movw $ABS(cursorY), %si
++ mov %ds:(%si), %bx
++ mul %bx
++ movw $ABS(cursorX), %si
++ mov %ds:(%si), %bx
++ shr $3, %bx /* %bx /= 8 */
++ add %bx, %ax
++ mov %ax, %di
++
++ movw $ABS(cursorBuf), %si /* fontBuf in ds:si */
++
++ /* prepare for data moving */
++ mov $16, %dx /* altura da fonte */
++ mov $80, %bx /* bytes por linha */
++
++write_loop:
++ movb %ds:(%si), %al
++ xorb $0xff, %al
++ movb %al, %ds:(%si) /* invert cursorBuf */
++ movb %al, %es:(%di) /* write to video */
++ add %bx, %di
++ inc %si
++ dec %dx
++ jg write_loop
++ ret
++
++int1c_handler:
++ pusha
++ mov $0, %ax
++ mov %ax, %ds
++ mov $ABS(cursorCount), %si
++ mov %ds:(%si), %ax
++ inc %ax
++ mov %ax, %ds:(%si)
++ cmp $9, %ax
++ jne int1c_done
++
++ mov $0, %ax
++ mov %ax, %ds:(%si)
++ call write_data
++
++int1c_done:
++ popa
++ iret
++ /* call previous int1c handler */
++ /* ljmp */
++ .byte 0xea
++int1c_offset: .word 0
++int1c_segment: .word 0
++ .code32
++
++
++/*
++ * unsigned char set_videomode(unsigned char mode)
++ * BIOS call "INT 10H Function 0h" to set video mode
++ * Call with %ah = 0x0
++ * %al = video mode
++ * Returns old videomode.
++ */
++ENTRY(set_videomode)
++ pushl %ebp
++ movl %esp,%ebp
++ pushl %ebx
++ pushl %ecx
++
++ movb 8(%ebp), %cl
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ xorb %al, %al
++ movb $0xf, %ah
++ int $0x10 /* Get Current Video mode */
++ movb %al, %ch
++ xorb %ah, %ah
++ movb %cl, %al
++ int $0x10 /* Set Video mode */
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movb %ch, %al
++
++ popl %ecx
++ popl %ebx
++ popl %ebp
++ ret
++
++
++/*
++ * int get_videomode()
++ * BIOS call "INT 10H Function 0Fh" to get current video mode
++ * Call with %al = 0x0
++ * %ah = 0xF
++ * Returns current videomode.
++ */
++ENTRY(get_videomode)
++ pushl %ebp
++ movl %esp,%ebp
++ pushl %ebx
++ pushl %ecx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ xorb %al, %al
++ movb $0xF, %ah
++ int $0x10 /* Get Current Video mode */
++ movb %al, %cl /* For now we only want display mode */
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movb %cl, %al
++
++ popl %ecx
++ popl %ebx
++ popl %ebp
++ ret
++
++
++/*
++ * unsigned char * graphics_get_font()
++ * BIOS call "INT 10H Function 11h" to set font
++ * Call with %ah = 0x11
++ */
++ENTRY(graphics_get_font)
++ push %ebp
++ push %ebx
++ push %ecx
++ push %edx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ movw $0x1130, %ax
++ movb $6, %bh /* font 8x16 */
++ int $0x10
++ movw %bp, %dx
++ movw %es, %cx
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movw %cx, %ax
++ shll $4, %eax
++ movw %dx, %ax
++
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %ebp
++ ret
++
++
++/*
++ * graphics_set_palette(index, red, green, blue)
++ * BIOS call "INT 10H Function 10h" to set individual dac register
++ * Call with %ah = 0x10
++ * %bx = register number
++ * %ch = new value for green (0-63)
++ * %cl = new value for blue (0-63)
++ * %dh = new value for red (0-63)
++ */
++
++ENTRY(graphics_set_palette)
++ push %ebp
++ push %eax
++ push %ebx
++ push %ecx
++ push %edx
++
++ movw $0x3c8, %bx /* address write mode register */
++
++ /* wait vertical retrace */
++ movw $0x3da, %dx
++l1b:
++ inb %dx, %al /* wait vertical active display */
++ test $8, %al
++ jnz l1b
++
++l2b:
++ inb %dx, %al /* wait vertical retrace */
++ test $8, %al
++ jnz l2b
++
++ mov %bx, %dx
++ movb 0x18(%esp), %al /* index */
++ outb %al, %dx
++ inc %dx
++
++ movb 0x1c(%esp), %al /* red */
++ outb %al, %dx
++
++ movb 0x20(%esp), %al /* green */
++ outb %al, %dx
++
++ movb 0x24(%esp), %al /* blue */
++ outb %al, %dx
++
++ movw 0x18(%esp), %bx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ movb %bl, %bh
++ movw $0x1000, %ax
++ int $0x10
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %eax
++ pop %ebp
++ ret
++#endif /* SUPPORT_GRAPHICS */
++
++
+ /*
+ * getrtsecs()
+ * if a seconds value can be read, read it and return it (BCD),
+diff -Naur grub-0.97.orig/stage2/builtins.c grub-0.97/stage2/builtins.c
+--- grub-0.97.orig/stage2/builtins.c 2005-02-15 19:58:23.000000000 -0200
++++ grub-0.97/stage2/builtins.c 2005-06-13 18:44:03.000000000 -0300
+@@ -28,6 +28,10 @@
+ #include <filesys.h>
+ #include <term.h>
+
++#ifdef SUPPORT_GRAPHICS
++# include <graphics.h>
++#endif
++
+ #ifdef SUPPORT_NETBOOT
+ # define GRUB 1
+ # include <etherboot.h>
+@@ -237,12 +241,22 @@
+ static int
+ boot_func (char *arg, int flags)
+ {
++ struct term_entry *prev_term = current_term;
+ /* Clear the int15 handler if we can boot the kernel successfully.
+ This assumes that the boot code never fails only if KERNEL_TYPE is
+ not KERNEL_TYPE_NONE. Is this assumption is bad? */
+ if (kernel_type != KERNEL_TYPE_NONE)
+ unset_int15_handler ();
+
++ /* if our terminal needed initialization, we should shut it down
++ * before booting the kernel, but we want to save what it was so
++ * we can come back if needed */
++ if (current_term->shutdown)
++ {
++ current_term->shutdown();
++ current_term = term_table; /* assumption: console is first */
++ }
++
+ #ifdef SUPPORT_NETBOOT
+ /* Shut down the networking. */
+ cleanup_net ();
+@@ -306,6 +320,13 @@
+ return 1;
+ }
+
++ /* if we get back here, we should go back to what our term was before */
++ current_term = prev_term;
++ if (current_term->startup)
++ /* if our terminal fails to initialize, fall back to console since
++ * it should always work */
++ if (current_term->startup() == 0)
++ current_term = term_table; /* we know that console is first */
+ return 0;
+ }
+
+@@ -852,6 +873,251 @@
+ };
+ #endif /* SUPPORT_NETBOOT */
+
++#ifdef SUPPORT_GRAPHICS
++
++static int splashimage_func(char *arg, int flags) {
++ int i;
++
++ /* filename can only be 256 characters due to our buffer size */
++ if (grub_strlen(arg) > 256) {
++ grub_printf("Splash image filename too large\n");
++ grub_printf("Press any key to continue...");
++ getkey();
++ return 1;
++ }
++
++ /* get rid of TERM_NEED_INIT from the graphics terminal. */
++ for (i = 0; term_table[i].name; i++) {
++ if (grub_strcmp (term_table[i].name, "graphics") == 0) {
++ term_table[i].flags &= ~TERM_NEED_INIT;
++ break;
++ }
++ }
++
++ graphics_set_splash(arg);
++
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ if (graphics_init() == 0) {
++ /* Fallback to default term */
++ current_term = term_table;
++ max_lines = current_term->max_lines;
++ if (current_term->cls)
++ current_term->cls();
++ grub_printf("Failed to set splash image and/or graphics mode\n");
++ return 1;
++ }
++ graphics_cls();
++ }
++
++ if (flags == BUILTIN_MENU)
++ current_term = term_table + i;
++
++ return 0;
++}
++
++static struct builtin builtin_splashimage =
++{
++ "splashimage",
++ splashimage_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "splashimage FILE",
++ "Load FILE as the background image when in graphics mode."
++};
++
++
++/* shade */
++static int
++shade_func(char *arg, int flags)
++{
++ int new_shade;
++
++ if (!arg || safe_parse_maxint(&arg, &new_shade) == 0)
++ return (1);
++
++ if (shade != new_shade) {
++ shade = new_shade;
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ graphics_init();
++ graphics_cls();
++ }
++ }
++
++ return 0;
++}
++
++static struct builtin builtin_shade =
++{
++ "shade",
++ shade_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "shade INTEGER",
++ "If set to 0, disables the use of shaded text, else enables it."
++};
++
++
++/* foreground */
++static int
++foreground_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ foreground = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(15, r, g, b);
++
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct builtin builtin_foreground =
++{
++ "foreground",
++ foreground_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "foreground RRGGBB",
++ "Sets the foreground color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* background */
++static int
++background_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ background = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(0, r, g, b);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct builtin builtin_background =
++{
++ "background",
++ background_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "background RRGGBB",
++ "Sets the background color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* border */
++static int
++border_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ window_border = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(0x11, r, g, b);
++
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct builtin builtin_border =
++{
++ "border",
++ border_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "border RRGGBB",
++ "Sets the border video color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* viewport */
++static int
++viewport_func (char *arg, int flags)
++{
++ int i;
++ int x0 = 0, y0 = 0, x1 = 80, y1 = 30;
++ int *pos[4] = { &x0, &y0, &x1, &y1 };
++
++ if (!arg)
++ return (1);
++ for (i = 0; i < 4; i++) {
++ if (!*arg)
++ return (1);
++ while (*arg && (*arg == ' ' || *arg == '\t'))
++ ++arg;
++ if (!safe_parse_maxint(&arg, pos[i]))
++ return (1);
++ while (*arg && (*arg != ' ' && *arg != '\t'))
++ ++arg;
++ }
++
++ /* minimum size is 65 colums and 16 rows */
++ if (x0 > x1 - 66 || y0 > y1 - 16 || x0 < 0 || y0 < 0 || x1 > 80 || y1 > 30)
++ return 1;
++
++ view_x0 = x0;
++ view_y0 = y0;
++ view_x1 = x1;
++ view_y1 = y1;
++
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ graphics_init();
++ graphics_cls();
++ }
++
++ return 0;
++}
++
++static struct builtin builtin_viewport =
++{
++ "viewport",
++ viewport_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "viewport x0 y0 x1 y1",
++ "Changes grub internals to output text in the window defined by"
++ " four parameters. The x and y parameters are 0 based. This option"
++ " only works with the graphics interface."
++};
++
++#endif /* SUPPORT_GRAPHICS */
++
++
++/* clear */
++static int
++clear_func()
++{
++ if (current_term->cls)
++ current_term->cls();
++
++ return 0;
++}
++
++static struct builtin builtin_clear =
++{
++ "clear",
++ clear_func,
++ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++ "clear",
++ "Clear the screen"
++};
++
+
+ /* displayapm */
+ static int
+@@ -1454,14 +1720,20 @@
+
+
+ /* help */
+-#define MAX_SHORT_DOC_LEN 39
+-#define MAX_LONG_DOC_LEN 66
+-
+ static int
+ help_func (char *arg, int flags)
+ {
+- int all = 0;
+-
++ int all = 0, max_short_doc_len, max_long_doc_len;
++ max_short_doc_len = 39;
++ max_long_doc_len = 66;
++#ifdef SUPPORT_GRAPHICS
++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
++ {
++ max_short_doc_len = (view_x1 - view_x0 + 1) / 2 - 1;
++ max_long_doc_len = (view_x1 - view_x0) - 14;
++ }
++#endif
++
+ if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
+ {
+ all = 1;
+@@ -1491,13 +1763,13 @@
+
+ len = grub_strlen ((*builtin)->short_doc);
+ /* If the length of SHORT_DOC is too long, truncate it. */
+- if (len > MAX_SHORT_DOC_LEN - 1)
+- len = MAX_SHORT_DOC_LEN - 1;
++ if (len > max_short_doc_len - 1)
++ len = max_short_doc_len - 1;
+
+ for (i = 0; i < len; i++)
+ grub_putchar ((*builtin)->short_doc[i]);
+
+- for (; i < MAX_SHORT_DOC_LEN; i++)
++ for (; i < max_short_doc_len; i++)
+ grub_putchar (' ');
+
+ if (! left)
+@@ -1546,10 +1818,10 @@
+ int i;
+
+ /* If LEN is too long, fold DOC. */
+- if (len > MAX_LONG_DOC_LEN)
++ if (len > max_long_doc_len)
+ {
+ /* Fold this line at the position of a space. */
+- for (len = MAX_LONG_DOC_LEN; len > 0; len--)
++ for (len = max_long_doc_len; len > 0; len--)
+ if (doc[len - 1] == ' ')
+ break;
+ }
+@@ -4085,7 +4357,7 @@
+ };
+
+
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+ /* terminal */
+ static int
+ terminal_func (char *arg, int flags)
+@@ -4244,17 +4516,29 @@
+ end:
+ current_term = term_table + default_term;
+ current_term->flags = term_flags;
+-
++
+ if (lines)
+ max_lines = lines;
+ else
+- /* 24 would be a good default value. */
+- max_lines = 24;
+-
++ max_lines = current_term->max_lines;
++
+ /* If the interface is currently the command-line,
+ restart it to repaint the screen. */
+- if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
++ if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
++ if (prev_term->shutdown)
++ prev_term->shutdown();
++ if (current_term->startup) {
++ /* If startup fails, return to previous term */
++ if (current_term->startup() == 0) {
++ current_term = prev_term;
++ max_lines = current_term->max_lines;
++ if (current_term->cls) {
++ current_term->cls();
++ }
++ }
++ }
+ grub_longjmp (restart_cmdline_env, 0);
++ }
+
+ return 0;
+ }
+@@ -4264,7 +4548,7 @@
+ "terminal",
+ terminal_func,
+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+- "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
++ "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]",
+ "Select a terminal. When multiple terminals are specified, wait until"
+ " you push any key to continue. If both console and serial are specified,"
+ " the terminal to which you input a key first will be selected. If no"
+@@ -4276,7 +4560,7 @@
+ " seconds. The option --lines specifies the maximum number of lines."
+ " The option --silent is used to suppress messages."
+ };
+-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
+
+
+ #ifdef SUPPORT_SERIAL
+@@ -4795,13 +5079,20 @@
+ /* The table of builtin commands. Sorted in dictionary order. */
+ struct builtin *builtin_table[] =
+ {
++#ifdef SUPPORT_GRAPHICS
++ &builtin_background,
++#endif
+ &builtin_blocklist,
+ &builtin_boot,
+ #ifdef SUPPORT_NETBOOT
+ &builtin_bootp,
+ #endif /* SUPPORT_NETBOOT */
++#ifdef SUPPORT_GRAPHICS
++ &builtin_border,
++#endif
+ &builtin_cat,
+ &builtin_chainloader,
++ &builtin_clear,
+ &builtin_cmp,
+ &builtin_color,
+ &builtin_configfile,
+@@ -4821,6 +5112,9 @@
+ &builtin_embed,
+ &builtin_fallback,
+ &builtin_find,
++#ifdef SUPPORT_GRAPHICS
++ &builtin_foreground,
++#endif
+ &builtin_fstest,
+ &builtin_geometry,
+ &builtin_halt,
+@@ -4864,9 +5158,13 @@
+ #endif /* SUPPORT_SERIAL */
+ &builtin_setkey,
+ &builtin_setup,
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++#ifdef SUPPORT_GRAPHICS
++ &builtin_shade,
++ &builtin_splashimage,
++#endif /* SUPPORT_GRAPHICS */
++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+ &builtin_terminal,
+-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
+ #ifdef SUPPORT_SERIAL
+ &builtin_terminfo,
+ #endif /* SUPPORT_SERIAL */
+@@ -4880,5 +5178,8 @@
+ &builtin_unhide,
+ &builtin_uppermem,
+ &builtin_vbeprobe,
++#ifdef SUPPORT_GRAPHICS
++ &builtin_viewport,
++#endif
+ 0
+ };
+diff -Naur grub-0.97.orig/stage2/char_io.c grub-0.97/stage2/char_io.c
+--- grub-0.97.orig/stage2/char_io.c 2005-02-01 18:51:23.000000000 -0200
++++ grub-0.97/stage2/char_io.c 2005-06-12 20:56:49.000000000 -0300
+@@ -29,12 +29,17 @@
+ # include <serial.h>
+ #endif
+
++#ifdef SUPPORT_GRAPHICS
++# include <graphics.h>
++#endif
++
+ #ifndef STAGE1_5
+ struct term_entry term_table[] =
+ {
+ {
+ "console",
+ 0,
++ 24,
+ console_putchar,
+ console_checkkey,
+ console_getkey,
+@@ -43,13 +48,16 @@
+ console_cls,
+ console_setcolorstate,
+ console_setcolor,
+- console_setcursor
++ console_setcursor,
++ 0,
++ 0
+ },
+ #ifdef SUPPORT_SERIAL
+ {
+ "serial",
+ /* A serial device must be initialized. */
+ TERM_NEED_INIT,
++ 24,
+ serial_putchar,
+ serial_checkkey,
+ serial_getkey,
+@@ -58,6 +66,8 @@
+ serial_cls,
+ serial_setcolorstate,
+ 0,
++ 0,
++ 0,
+ 0
+ },
+ #endif /* SUPPORT_SERIAL */
+@@ -65,6 +75,7 @@
+ {
+ "hercules",
+ 0,
++ 24,
+ hercules_putchar,
+ console_checkkey,
+ console_getkey,
+@@ -73,11 +84,30 @@
+ hercules_cls,
+ hercules_setcolorstate,
+ hercules_setcolor,
+- hercules_setcursor
++ hercules_setcursor,
++ 0,
++ 0
+ },
+ #endif /* SUPPORT_HERCULES */
++#ifdef SUPPORT_GRAPHICS
++ { "graphics",
++ TERM_NEED_INIT, /* flags */
++ 30, /* number of lines */
++ graphics_putchar, /* putchar */
++ console_checkkey, /* checkkey */
++ console_getkey, /* getkey */
++ graphics_getxy, /* getxy */
++ graphics_gotoxy, /* gotoxy */
++ graphics_cls, /* cls */
++ graphics_setcolorstate, /* setcolorstate */
++ graphics_setcolor, /* setcolor */
++ graphics_setcursor, /* nocursor */
++ graphics_init, /* initialize */
++ graphics_end /* shutdown */
++ },
++#endif /* SUPPORT_GRAPHICS */
+ /* This must be the last entry. */
+- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ };
+
+ /* This must be console. */
+@@ -305,9 +335,10 @@
+
+ /* XXX: These should be defined in shared.h, but I leave these here,
+ until this code is freezed. */
+-#define CMDLINE_WIDTH 78
+ #define CMDLINE_MARGIN 10
+-
++
++ /* command-line limits */
++ int cmdline_width = 78, col_start = 0;
+ int xpos, lpos, c, section;
+ /* The length of PROMPT. */
+ int plen;
+@@ -338,7 +369,7 @@
+
+ /* If the cursor is in the first section, display the first section
+ instead of the second. */
+- if (section == 1 && plen + lpos < CMDLINE_WIDTH)
++ if (section == 1 && plen + lpos < cmdline_width)
+ cl_refresh (1, 0);
+ else if (xpos - count < 1)
+ cl_refresh (1, 0);
+@@ -354,7 +385,7 @@
+ grub_putchar ('\b');
+ }
+ else
+- gotoxy (xpos, getxy () & 0xFF);
++ gotoxy (xpos + col_start, getxy () & 0xFF);
+ }
+ }
+
+@@ -364,7 +395,7 @@
+ lpos += count;
+
+ /* If the cursor goes outside, scroll the screen to the right. */
+- if (xpos + count >= CMDLINE_WIDTH)
++ if (xpos + count >= cmdline_width)
+ cl_refresh (1, 0);
+ else
+ {
+@@ -383,7 +414,7 @@
+ }
+ }
+ else
+- gotoxy (xpos, getxy () & 0xFF);
++ gotoxy (xpos + col_start, getxy () & 0xFF);
+ }
+ }
+
+@@ -398,14 +429,14 @@
+ if (full)
+ {
+ /* Recompute the section number. */
+- if (lpos + plen < CMDLINE_WIDTH)
++ if (lpos + plen < cmdline_width)
+ section = 0;
+ else
+- section = ((lpos + plen - CMDLINE_WIDTH)
+- / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
++ section = ((lpos + plen - cmdline_width)
++ / (cmdline_width - 1 - CMDLINE_MARGIN) + 1);
+
+ /* From the start to the end. */
+- len = CMDLINE_WIDTH;
++ len = cmdline_width;
+ pos = 0;
+ grub_putchar ('\r');
+
+@@ -445,8 +476,8 @@
+ if (! full)
+ offset = xpos - 1;
+
+- start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
+- + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
++ start = ((section - 1) * (cmdline_width - 1 - CMDLINE_MARGIN)
++ + cmdline_width - plen - CMDLINE_MARGIN);
+ xpos = lpos + 1 - start;
+ start += offset;
+ }
+@@ -471,7 +502,7 @@
+
+ /* If the cursor is at the last position, put `>' or a space,
+ depending on if there are more characters in BUF. */
+- if (pos == CMDLINE_WIDTH)
++ if (pos == cmdline_width)
+ {
+ if (start + len < llen)
+ grub_putchar ('>');
+@@ -488,7 +519,7 @@
+ grub_putchar ('\b');
+ }
+ else
+- gotoxy (xpos, getxy () & 0xFF);
++ gotoxy (xpos + col_start, getxy () & 0xFF);
+ }
+
+ /* Initialize the command-line. */
+@@ -518,10 +549,10 @@
+
+ llen += l;
+ lpos += l;
+- if (xpos + l >= CMDLINE_WIDTH)
++ if (xpos + l >= cmdline_width)
+ cl_refresh (1, 0);
+- else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
+- cl_refresh (0, CMDLINE_WIDTH - xpos);
++ else if (xpos + l + llen - lpos > cmdline_width)
++ cl_refresh (0, cmdline_width - xpos);
+ else
+ cl_refresh (0, l + llen - lpos);
+ }
+@@ -533,12 +564,22 @@
+ grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
+ llen -= count;
+
+- if (xpos + llen + count - lpos > CMDLINE_WIDTH)
+- cl_refresh (0, CMDLINE_WIDTH - xpos);
++ if (xpos + llen + count - lpos > cmdline_width)
++ cl_refresh (0, cmdline_width - xpos);
+ else
+ cl_refresh (0, llen + count - lpos);
+ }
+
++ max_lines = current_term->max_lines;
++#ifdef SUPPORT_GRAPHICS
++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
++ {
++ cmdline_width = (view_x1 - view_x0) - 2;
++ col_start = view_x0;
++ max_lines = view_y1 - view_y0;
++ }
++#endif
++
+ plen = grub_strlen (prompt);
+ llen = grub_strlen (cmdline);
+
+@@ -1006,6 +1047,48 @@
+ }
+ #endif /* ! STAGE1_5 */
+
++#ifndef STAGE1_5
++/* Internal pager. */
++int
++do_more (void)
++{
++ if (count_lines >= 0)
++ {
++ count_lines++;
++ if (count_lines >= max_lines - 2)
++ {
++ int tmp;
++
++ /* It's important to disable the feature temporarily, because
++ the following grub_printf call will print newlines. */
++ count_lines = -1;
++
++ grub_printf("\n");
++ if (current_term->setcolorstate)
++ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
++
++ grub_printf ("[Hit return to continue]");
++
++ if (current_term->setcolorstate)
++ current_term->setcolorstate (COLOR_STATE_NORMAL);
++
++
++ do
++ {
++ tmp = ASCII_CHAR (getkey ());
++ }
++ while (tmp != '\n' && tmp != '\r');
++ grub_printf ("\r \r");
++
++ /* Restart to count lines. */
++ count_lines = 0;
++ return 1;
++ }
++ }
++ return 0;
++}
++#endif
++
+ /* Display an ASCII character. */
+ void
+ grub_putchar (int c)
+@@ -1034,38 +1117,11 @@
+
+ if (c == '\n')
+ {
++ int flag;
+ /* Internal `more'-like feature. */
+- if (count_lines >= 0)
+- {
+- count_lines++;
+- if (count_lines >= max_lines - 2)
+- {
+- int tmp;
+-
+- /* It's important to disable the feature temporarily, because
+- the following grub_printf call will print newlines. */
+- count_lines = -1;
+-
+- if (current_term->setcolorstate)
+- current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+-
+- grub_printf ("\n[Hit return to continue]");
+-
+- if (current_term->setcolorstate)
+- current_term->setcolorstate (COLOR_STATE_NORMAL);
+-
+- do
+- {
+- tmp = ASCII_CHAR (getkey ());
+- }
+- while (tmp != '\n' && tmp != '\r');
+- grub_printf ("\r \r");
+-
+- /* Restart to count lines. */
+- count_lines = 0;
+- return;
+- }
+- }
++ flag = do_more ();
++ if (flag)
++ return;
+ }
+
+ current_term->putchar (c);
+@@ -1090,7 +1146,7 @@
+ cls (void)
+ {
+ /* If the terminal is dumb, there is no way to clean the terminal. */
+- if (current_term->flags & TERM_DUMB)
++ if (current_term->flags & TERM_DUMB)
+ grub_putchar ('\n');
+ else
+ current_term->cls ();
+@@ -1217,6 +1273,16 @@
+ return ! errnum;
+ }
+
++void
++grub_memcpy(void *dest, const void *src, int len)
++{
++ int i;
++ register char *d = (char*)dest, *s = (char*)src;
++
++ for (i = 0; i < len; i++)
++ d[i] = s[i];
++}
++
+ void *
+ grub_memmove (void *to, const void *from, int len)
+ {
+diff -Naur grub-0.97.orig/stage2/cmdline.c grub-0.97/stage2/cmdline.c
+--- grub-0.97.orig/stage2/cmdline.c 2004-08-16 20:23:01.000000000 -0300
++++ grub-0.97/stage2/cmdline.c 2005-06-12 20:56:49.000000000 -0300
+@@ -50,10 +50,11 @@
+ void
+ print_cmdline_message (int forever)
+ {
+- printf (" [ Minimal BASH-like line editing is supported. For the first word, TAB\n"
+- " lists possible command completions. Anywhere else TAB lists the possible\n"
+- " completions of a device/filename.%s ]\n",
+- (forever ? "" : " ESC at any time exits."));
++ grub_printf(" [ Minimal BASH-like line editing is supported. For\n"
++ " the first word, TAB lists possible command\n"
++ " completions. Anywhere else TAB lists the possible\n"
++ " completions of a device/filename.%s ]\n",
++ (forever ? "" : " ESC at any time\n exits."));
+ }
+
+ /* Find the builtin whose command name is COMMAND and return the
+diff -Naur grub-0.97.orig/stage2/graphics.c grub-0.97/stage2/graphics.c
+--- grub-0.97.orig/stage2/graphics.c 1969-12-31 21:00:00.000000000 -0300
++++ grub-0.97/stage2/graphics.c 2005-06-13 19:13:31.000000000 -0300
+@@ -0,0 +1,585 @@
++/*
++ * graphics.c - graphics mode support for GRUB
++ * Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
++ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
++ * Options and enhancements made by Herton Ronaldo Krzesinski
++ * <herton@mandriva.com>
++ *
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2001,2002 Red Hat, Inc.
++ * Portions copyright (C) 2000 Conectiva, Inc.
++ *
++ * This program 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 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifdef SUPPORT_GRAPHICS
++
++#include <term.h>
++#include <shared.h>
++#include <graphics.h>
++
++int saved_videomode;
++unsigned char *font8x16;
++
++int graphics_inited = 0;
++static char splashimage[256];
++
++int shade = 1, no_cursor = 0;
++
++#define VSHADOW VSHADOW1
++unsigned char VSHADOW1[38400];
++unsigned char VSHADOW2[38400];
++unsigned char VSHADOW4[38400];
++unsigned char VSHADOW8[38400];
++
++/* define the default viewable area */
++int view_x0 = 0;
++int view_y0 = 0;
++int view_x1 = 80;
++int view_y1 = 30;
++
++/* text buffer has to be kept around so that we can write things as we
++ * scroll and the like */
++unsigned short text[80 * 30];
++
++/* graphics options */
++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, window_border = 0;
++
++/* current position */
++static int fontx = 0;
++static int fonty = 0;
++
++/* global state so that we don't try to recursively scroll or cursor */
++static int no_scroll = 0;
++
++/* color state */
++static int graphics_standard_color = A_NORMAL;
++static int graphics_normal_color = A_NORMAL;
++static int graphics_highlight_color = A_REVERSE;
++static int graphics_current_color = A_NORMAL;
++static color_state graphics_color_state = COLOR_STATE_STANDARD;
++
++static inline void outb(unsigned short port, unsigned char val)
++{
++ __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
++}
++
++static void MapMask(int value) {
++ outb(0x3c4, 2);
++ outb(0x3c5, value);
++}
++
++/* bit mask register */
++static void BitMask(int value) {
++ outb(0x3ce, 8);
++ outb(0x3cf, value);
++}
++
++/* move the graphics cursor location to col, row */
++static void graphics_setxy(int col, int row) {
++ if (col >= view_x0 && col < view_x1) {
++ fontx = col;
++ cursorX = col << 3;
++ }
++ if (row >= view_y0 && row < view_y1) {
++ fonty = row;
++ cursorY = row << 4;
++ }
++}
++
++/* scroll the screen */
++static void graphics_scroll() {
++ int i, j, k;
++
++ /* we don't want to scroll recursively... that would be bad */
++ if (no_scroll)
++ return;
++ no_scroll = 1;
++
++ /* disable pager temporarily */
++ k = count_lines;
++ count_lines = -1;
++
++ /* move everything up a line */
++ for (j = view_y0 + 1; j < view_y1; j++) {
++ graphics_gotoxy(view_x0, j - 1);
++ for (i = view_x0; i < view_x1; i++) {
++ graphics_putchar(text[j * 80 + i]);
++ }
++ }
++
++ /* last line should be blank */
++ graphics_gotoxy(view_x0, view_y1 - 1);
++ for (i = view_x0; i < view_x1; i++)
++ graphics_putchar(' ');
++ graphics_setxy(view_x0, view_y1 - 1);
++
++ count_lines = k;
++
++ no_scroll = 0;
++}
++
++/* Set the splash image */
++void graphics_set_splash(char *splashfile) {
++ grub_strcpy(splashimage, splashfile);
++}
++
++/* Get the current splash image */
++char *graphics_get_splash(void) {
++ return splashimage;
++}
++
++/*
++ * Initialize a vga16 graphics display with the palette based off of
++ * the image in splashimage. If the image doesn't exist, leave graphics
++ * mode. The mode initiated is 12h. From "Ralf Brown's Interrupt List":
++ * text/ text pixel pixel colors disply scrn system
++ * grph resol box resolution pages addr
++ * 12h G 80x30 8x16 640x480 16/256K . A000 VGA,ATI VIP
++ * G 80x30 8x16 640x480 16/64 . A000 ATI EGA Wonder
++ * G . . 640x480 16 . . UltraVision+256K EGA
++ */
++int graphics_init()
++{
++ if (!graphics_inited) {
++ saved_videomode = set_videomode(0x12);
++ if (get_videomode() != 0x12) {
++ set_videomode(saved_videomode);
++ return 0;
++ }
++ graphics_inited = 1;
++ }
++ else
++ return 1;
++
++ font8x16 = (unsigned char*)graphics_get_font();
++
++ /* make sure that the highlight color is set correctly */
++ graphics_highlight_color = ((graphics_normal_color >> 4) |
++ ((graphics_normal_color & 0xf) << 4));
++
++ graphics_cls();
++
++ if (!read_image(splashimage)) {
++ grub_printf("Failed to read splash image (%s)\n", splashimage);
++ grub_printf("Press any key to continue...");
++ getkey();
++ set_videomode(saved_videomode);
++ graphics_inited = 0;
++ return 0;
++ }
++
++ set_int1c_handler();
++
++ return 1;
++}
++
++/* Leave graphics mode */
++void graphics_end(void)
++{
++ if (graphics_inited) {
++ unset_int1c_handler();
++ set_videomode(saved_videomode);
++ graphics_inited = 0;
++ no_cursor = 0;
++ }
++}
++
++/* Print ch on the screen. Handle any needed scrolling or the like */
++void graphics_putchar(int ch) {
++ ch &= 0xff;
++
++ graphics_cursor(0);
++
++ if (ch == '\n') {
++ if (fonty + 1 < view_y1)
++ graphics_setxy(fontx, fonty + 1);
++ else
++ graphics_scroll();
++ graphics_cursor(1);
++ return;
++ } else if (ch == '\r') {
++ graphics_setxy(view_x0, fonty);
++ graphics_cursor(1);
++ return;
++ }
++
++ graphics_cursor(0);
++
++ text[fonty * 80 + fontx] = ch;
++ text[fonty * 80 + fontx] &= 0x00ff;
++ if (graphics_current_color & 0xf0)
++ text[fonty * 80 + fontx] |= 0x100;
++
++ graphics_cursor(0);
++
++ if ((fontx + 1) >= view_x1) {
++ graphics_setxy(view_x0, fonty);
++ if (fonty + 1 < view_y1)
++ graphics_setxy(view_x0, fonty + 1);
++ else
++ graphics_scroll();
++ graphics_cursor(1);
++ do_more ();
++ graphics_cursor(0);
++ } else {
++ graphics_setxy(fontx + 1, fonty);
++ }
++
++ graphics_cursor(1);
++}
++
++/* get the current location of the cursor */
++int graphics_getxy(void) {
++ return (fontx << 8) | fonty;
++}
++
++void graphics_gotoxy(int x, int y) {
++ graphics_cursor(0);
++
++ graphics_setxy(x, y);
++
++ graphics_cursor(1);
++}
++
++void graphics_cls(void) {
++ int i;
++ unsigned char *mem, *s1, *s2, *s4, *s8;
++
++ graphics_cursor(0);
++ graphics_gotoxy(view_x0, view_y0);
++
++ mem = (unsigned char*)VIDEOMEM;
++ s1 = (unsigned char*)VSHADOW1;
++ s2 = (unsigned char*)VSHADOW2;
++ s4 = (unsigned char*)VSHADOW4;
++ s8 = (unsigned char*)VSHADOW8;
++
++ for (i = 0; i < 80 * 30; i++)
++ text[i] = ' ';
++ graphics_cursor(1);
++
++ BitMask(0xff);
++
++ /* plane 1 */
++ MapMask(1);
++ grub_memcpy(mem, s1, 38400);
++
++ /* plane 2 */
++ MapMask(2);
++ grub_memcpy(mem, s2, 38400);
++
++ /* plane 3 */
++ MapMask(4);
++ grub_memcpy(mem, s4, 38400);
++
++ /* plane 4 */
++ MapMask(8);
++ grub_memcpy(mem, s8, 38400);
++
++ MapMask(15);
++
++ if (no_cursor) {
++ no_cursor = 0;
++ set_int1c_handler();
++ }
++}
++
++void graphics_setcolorstate (color_state state) {
++ switch (state) {
++ case COLOR_STATE_STANDARD:
++ graphics_current_color = graphics_standard_color;
++ break;
++ case COLOR_STATE_NORMAL:
++ graphics_current_color = graphics_normal_color;
++ break;
++ case COLOR_STATE_HIGHLIGHT:
++ graphics_current_color = graphics_highlight_color;
++ break;
++ default:
++ graphics_current_color = graphics_standard_color;
++ break;
++ }
++
++ graphics_color_state = state;
++}
++
++void graphics_setcolor (int normal_color, int highlight_color) {
++ graphics_normal_color = normal_color;
++ graphics_highlight_color = highlight_color;
++
++ graphics_setcolorstate (graphics_color_state);
++}
++
++int graphics_setcursor (int on) {
++ if (!no_cursor && !on) {
++ no_cursor = 1;
++ unset_int1c_handler();
++ graphics_cursor(0);
++ }
++ else if(no_cursor && on) {
++ no_cursor = 0;
++ set_int1c_handler();
++ graphics_cursor(1);
++ }
++ return 0;
++}
++
++/* Read in the splashscreen image and set the palette up appropriately.
++ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
++ * 640x480. */
++int read_image(char *s)
++{
++ char buf[32], pal[16], c;
++ unsigned char base, mask, *s1, *s2, *s4, *s8;
++ unsigned i, len, idx, colors, x, y, width, height;
++
++ if (!grub_open(s))
++ return 0;
++
++ /* read header */
++ if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
++ grub_close();
++ return 0;
++ }
++
++ /* parse info */
++ while (grub_read(&c, 1)) {
++ if (c == '"')
++ break;
++ }
++
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ i = 0;
++ width = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ width = width * 10 + c - '0';
++ else
++ break;
++ }
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ height = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ height = height * 10 + c - '0';
++ else
++ break;
++ }
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ colors = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ colors = colors * 10 + c - '0';
++ else
++ break;
++ }
++
++ base = 0;
++ while (grub_read(&c, 1) && c != '"')
++ ;
++
++ /* palette */
++ for (i = 0, idx = 1; i < colors; i++) {
++ len = 0;
++
++ while (grub_read(&c, 1) && c != '"')
++ ;
++ grub_read(&c, 1); /* char */
++ base = c;
++ grub_read(buf, 4); /* \t c # */
++
++ while (grub_read(&c, 1) && c != '"') {
++ if (len < sizeof(buf))
++ buf[len++] = c;
++ }
++
++ if (len == 6 && idx < 15) {
++ int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
++ int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
++ int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
++
++ pal[idx] = base;
++ graphics_set_palette(idx, r, g, b);
++ ++idx;
++ }
++ }
++
++ x = y = len = 0;
++
++ s1 = (unsigned char*)VSHADOW1;
++ s2 = (unsigned char*)VSHADOW2;
++ s4 = (unsigned char*)VSHADOW4;
++ s8 = (unsigned char*)VSHADOW8;
++
++ for (i = 0; i < 38400; i++)
++ s1[i] = s2[i] = s4[i] = s8[i] = 0;
++
++ /* parse xpm data */
++ while (y < height) {
++ while (1) {
++ if (!grub_read(&c, 1)) {
++ grub_close();
++ return 0;
++ }
++ if (c == '"')
++ break;
++ }
++
++ while (grub_read(&c, 1) && c != '"') {
++ for (i = 1; i < 15; i++)
++ if (pal[i] == c) {
++ c = i;
++ break;
++ }
++
++ mask = 0x80 >> (x & 7);
++ if (c & 1)
++ s1[len + (x >> 3)] |= mask;
++ if (c & 2)
++ s2[len + (x >> 3)] |= mask;
++ if (c & 4)
++ s4[len + (x >> 3)] |= mask;
++ if (c & 8)
++ s8[len + (x >> 3)] |= mask;
++
++ if (++x >= 640) {
++ x = 0;
++
++ if (y < 480)
++ len += 80;
++ ++y;
++ }
++ }
++ }
++
++ grub_close();
++
++ graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
++ background & 63);
++ graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
++ foreground & 63);
++ graphics_set_palette(0x11, (window_border >> 16), (window_border >> 8) & 63,
++ window_border & 63);
++
++ return 1;
++}
++
++/* Convert a character which is a hex digit to the appropriate integer */
++int hex(int v)
++{
++ if (v >= 'A' && v <= 'F')
++ return (v - 'A' + 10);
++ if (v >= 'a' && v <= 'f')
++ return (v - 'a' + 10);
++ return (v - '0');
++}
++
++void graphics_cursor(int set) {
++ unsigned char *pat, *mem, *ptr, chr[16 << 2];
++ int i, ch, invert, offset;
++
++ if (set && (no_cursor || no_scroll))
++ return;
++
++ offset = cursorY * 80 + fontx;
++ ch = text[fonty * 80 + fontx] & 0xff;
++ invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
++ pat = font8x16 + (ch << 4);
++
++ mem = (unsigned char*)VIDEOMEM + offset;
++
++ if (!set) {
++ for (i = 0; i < 16; i++) {
++ unsigned char mask = pat[i];
++
++ if (!invert) {
++ chr[i ] = ((unsigned char*)VSHADOW1)[offset];
++ chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
++ chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
++ chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
++
++ if (shade) {
++ if (ch == DISP_VERT || ch == DISP_LL ||
++ ch == DISP_UR || ch == DISP_LR) {
++ unsigned char pmask = ~(pat[i] >> 1);
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ }
++ if (i > 0 && ch != DISP_VERT) {
++ unsigned char pmask = ~(pat[i - 1] >> 1);
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
++ pmask = ~pat[i - 1];
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ }
++ }
++ }
++ chr[i ] |= mask;
++ chr[16 + i] |= mask;
++ chr[32 + i] |= mask;
++ chr[48 + i] |= mask;
++
++ offset += 80;
++ }
++ else {
++ chr[i ] = mask;
++ chr[16 + i] = mask;
++ chr[32 + i] = mask;
++ chr[48 + i] = mask;
++ }
++ }
++ }
++ else {
++ MapMask(15);
++ ptr = mem;
++ for (i = 0; i < 16; i++, ptr += 80) {
++ cursorBuf[i] = pat[i];
++ *ptr = ~pat[i];
++ }
++ return;
++ }
++
++ offset = 0;
++ for (i = 1; i < 16; i <<= 1, offset += 16) {
++ int j;
++
++ MapMask(i);
++ ptr = mem;
++ for (j = 0; j < 16; j++, ptr += 80)
++ *ptr = chr[j + offset];
++ }
++
++ MapMask(15);
++}
++
++#endif /* SUPPORT_GRAPHICS */
+diff -Naur grub-0.97.orig/stage2/graphics.h grub-0.97/stage2/graphics.h
+--- grub-0.97.orig/stage2/graphics.h 1969-12-31 21:00:00.000000000 -0300
++++ grub-0.97/stage2/graphics.h 2005-06-12 20:56:49.000000000 -0300
+@@ -0,0 +1,44 @@
++/* graphics.h - graphics console interface */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2002 Free Software Foundation, Inc.
++ *
++ * This program 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 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef GRAPHICS_H
++#define GRAPHICS_H
++
++/* magic constant */
++#define VIDEOMEM 0xA0000
++
++/* function prototypes */
++char *graphics_get_splash(void);
++
++int read_image(char *s);
++void graphics_cursor(int set);
++
++/* function prototypes for asm functions */
++void * graphics_get_font();
++void graphics_set_palette(int idx, int red, int green, int blue);
++void set_int1c_handler();
++void unset_int1c_handler();
++
++extern short cursorX, cursorY;
++extern char cursorBuf[16];
++extern int shade;
++extern int view_x0, view_y0, view_x1, view_y1;
++
++#endif /* GRAPHICS_H */
+diff -Naur grub-0.97.orig/stage2/Makefile.am grub-0.97/stage2/Makefile.am
+--- grub-0.97.orig/stage2/Makefile.am 2005-02-02 18:37:35.000000000 -0200
++++ grub-0.97/stage2/Makefile.am 2005-06-12 20:56:49.000000000 -0300
+@@ -7,7 +7,7 @@
+ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
+ imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
+ nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
+- terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
++ terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h
+ EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
+
+ # For <stage1.h>.
+@@ -19,7 +19,7 @@
+ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
+ fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
+ fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
+- terminfo.c tparm.c
++ terminfo.c tparm.c graphics.c
+ libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
+ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
+ -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
+@@ -79,8 +79,14 @@
+ HERCULES_FLAGS =
+ endif
+
++if GRAPHICS_SUPPORT
++GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1
++else
++GRAPHICS_FLAGS =
++endif
++
+ STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
+- $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
++ $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
+
+ STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
+ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
+@@ -90,7 +96,8 @@
+ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
+ fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
+ fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
+- hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
++ hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
++ graphics.c
+ pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+ pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+ pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
+diff -Naur grub-0.97.orig/stage2/shared.h grub-0.97/stage2/shared.h
+--- grub-0.97.orig/stage2/shared.h 2004-06-19 13:40:09.000000000 -0300
++++ grub-0.97/stage2/shared.h 2005-06-12 20:56:49.000000000 -0300
+@@ -792,6 +792,11 @@
+ /* Set the cursor position. */
+ void gotoxy (int x, int y);
+
++/* Internal pager
++ Returns 1 = if pager was used
++ 0 = if pager wasn't used */
++int do_more (void);
++
+ /* Displays an ASCII character. IBM displays will translate some
+ characters to special graphical ones (see the DISP_* constants). */
+ void grub_putchar (int c);
+@@ -871,6 +876,7 @@
+ int grub_tolower (int c);
+ int grub_isspace (int c);
+ int grub_strncat (char *s1, const char *s2, int n);
++void grub_memcpy(void *dest, const void *src, int len);
+ void *grub_memmove (void *to, const void *from, int len);
+ void *grub_memset (void *start, int c, int len);
+ int grub_strncat (char *s1, const char *s2, int n);
+diff -Naur grub-0.97.orig/stage2/stage2.c grub-0.97/stage2/stage2.c
+--- grub-0.97.orig/stage2/stage2.c 2005-03-19 14:51:57.000000000 -0300
++++ grub-0.97/stage2/stage2.c 2005-06-13 22:38:08.000000000 -0300
+@@ -20,6 +20,12 @@
+ #include <shared.h>
+ #include <term.h>
+
++#ifdef SUPPORT_GRAPHICS
++# include <graphics.h>
++#endif
++
++int col_start, col_end, row_start, box_size;
++
+ grub_jmp_buf restart_env;
+
+ #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
+@@ -105,13 +111,13 @@
+ if (highlight && current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+
+- gotoxy (2, y);
++ gotoxy (2 + col_start, y);
+ grub_putchar (' ');
+- for (x = 3; x < 75; x++)
++ for (x = 3 + col_start; x < (col_end - 5); x++)
+ {
+- if (*entry && x <= 72)
++ if (*entry && x <= (col_end - 8))
+ {
+- if (x == 72)
++ if (x == (col_end - 8))
+ grub_putchar (DISP_RIGHT);
+ else
+ grub_putchar (*entry++);
+@@ -119,7 +125,7 @@
+ else
+ grub_putchar (' ');
+ }
+- gotoxy (74, y);
++ gotoxy ((col_end - 6), y);
+
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_STANDARD);
+@@ -131,7 +137,7 @@
+ {
+ int i;
+
+- gotoxy (77, y + 1);
++ gotoxy ((col_end - 3), y + 1);
+
+ if (first)
+ grub_putchar (DISP_UP);
+@@ -151,14 +157,14 @@
+ menu_entries++;
+ }
+
+- gotoxy (77, y + size);
++ gotoxy ((col_end - 3), y + size);
+
+ if (*menu_entries)
+ grub_putchar (DISP_DOWN);
+ else
+ grub_putchar (' ');
+
+- gotoxy (74, y + entryno + 1);
++ gotoxy ((col_end - 6), y + entryno + 1);
+ }
+
+ static void
+@@ -196,30 +202,30 @@
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_NORMAL);
+
+- gotoxy (1, y);
++ gotoxy (1 + col_start, y);
+
+ grub_putchar (DISP_UL);
+- for (i = 0; i < 73; i++)
++ for (i = col_start; i < (col_end - 7); i++)
+ grub_putchar (DISP_HORIZ);
+ grub_putchar (DISP_UR);
+
+ i = 1;
+ while (1)
+ {
+- gotoxy (1, y + i);
++ gotoxy (1 + col_start, y + i);
+
+ if (i > size)
+ break;
+
+ grub_putchar (DISP_VERT);
+- gotoxy (75, y + i);
++ gotoxy ((col_end - 5), y + i);
+ grub_putchar (DISP_VERT);
+
+ i++;
+ }
+
+ grub_putchar (DISP_LL);
+- for (i = 0; i < 73; i++)
++ for (i = col_start; i < (col_end - 7); i++)
+ grub_putchar (DISP_HORIZ);
+ grub_putchar (DISP_LR);
+
+@@ -233,6 +239,7 @@
+ {
+ int c, time1, time2 = -1, first_entry = 0;
+ char *cur_entry = 0;
++ struct term_entry *prev_term = NULL;
+
+ /*
+ * Main loop for menu UI.
+@@ -250,6 +257,22 @@
+ }
+ }
+
++ col_start = 0;
++ col_end = 80;
++ row_start = 0;
++ box_size = 12;
++ /* if we're using viewport we need to make sure to setup
++ coordinates correctly. */
++#ifdef SUPPORT_GRAPHICS
++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
++ {
++ col_start = view_x0;
++ col_end = view_x1;
++ row_start = view_y0;
++ box_size = (view_y1 - view_y0) - 13;
++ }
++#endif
++
+ /* If the timeout was expired or wasn't set, force to show the menu
+ interface. */
+ if (grub_timeout < 0)
+@@ -302,36 +325,36 @@
+ if (current_term->flags & TERM_DUMB)
+ print_entries_raw (num_entries, first_entry, menu_entries);
+ else
+- print_border (3, 12);
++ print_border (3 + row_start, box_size);
+
+ grub_printf ("\n\
+- Use the %c and %c keys to select which entry is highlighted.\n",
++ Use the %c and %c keys to select which entry is highlighted.\n",
+ DISP_UP, DISP_DOWN);
+
+ if (! auth && password)
+ {
+ printf ("\
+- Press enter to boot the selected OS or \'p\' to enter a\n\
+- password to unlock the next set of features.");
++ Press enter to boot the selected OS or \'p\' to enter a\n\
++ password to unlock the next set of features.");
+ }
+ else
+ {
+ if (config_entries)
+ printf ("\
+- Press enter to boot the selected OS, \'e\' to edit the\n\
+- commands before booting, or \'c\' for a command-line.");
++ Press enter to boot the selected OS, \'e\' to edit the\n\
++ commands before booting, or \'c\' for a command-line.");
+ else
+ printf ("\
+- Press \'b\' to boot, \'e\' to edit the selected command in the\n\
+- boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
+- after (\'O\' for before) the selected line, \'d\' to remove the\n\
+- selected line, or escape to go back to the main menu.");
++ Press \'b\' to boot, \'e\' to edit the selected command in the\n\
++ boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
++ after (\'O\' for before) the selected line, \'d\' to remove the\n\
++ selected line, or escape to go back to the main menu.");
+ }
+
+ if (current_term->flags & TERM_DUMB)
+ grub_printf ("\n\nThe selected entry is %d ", entryno);
+ else
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+
+ /* XX using RT clock now, need to initialize value */
+@@ -358,10 +381,10 @@
+ entryno, grub_timeout);
+ else
+ {
+- gotoxy (3, 22);
+- grub_printf ("The highlighted entry will be booted automatically in %d seconds. ",
++ gotoxy (3 + col_start, 10 + box_size + row_start);
++ grub_printf (" The highlighted entry will be booted automatically in %d seconds. ",
+ grub_timeout);
+- gotoxy (74, 4 + entryno);
++ gotoxy ((col_end - 6), 4 + entryno + row_start);
+ }
+
+ grub_timeout--;
+@@ -387,12 +410,12 @@
+ if (current_term->flags & TERM_DUMB)
+ grub_putchar ('\r');
+ else
+- gotoxy (3, 22);
++ gotoxy (3 + col_start, 10 + box_size + row_start);
+ printf (" ");
+ grub_timeout = -1;
+ fallback_entryno = -1;
+ if (! (current_term->flags & TERM_DUMB))
+- gotoxy (74, 4 + entryno);
++ gotoxy ((col_end - 6), 4 + entryno + row_start);
+ }
+
+ /* We told them above (at least in SUPPORT_SERIAL) to use
+@@ -408,12 +431,12 @@
+ {
+ if (entryno > 0)
+ {
+- print_entry (4 + entryno, 0,
++ print_entry (4 + entryno + row_start, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ entryno--;
+- print_entry (4 + entryno, 1,
++ print_entry (4 + entryno + row_start, 1,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+@@ -421,7 +444,7 @@
+ else if (first_entry > 0)
+ {
+ first_entry--;
+- print_entries (3, 12, first_entry, entryno,
++ print_entries (3 + row_start, box_size, first_entry, entryno,
+ menu_entries);
+ }
+ }
+@@ -433,29 +456,29 @@
+ entryno++;
+ else
+ {
+- if (entryno < 11)
++ if (entryno < (box_size - 1))
+ {
+- print_entry (4 + entryno, 0,
++ print_entry (4 + entryno + row_start, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ entryno++;
+- print_entry (4 + entryno, 1,
++ print_entry (4 + entryno + row_start, 1,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ }
+- else if (num_entries > 12 + first_entry)
++ else if (num_entries > box_size + first_entry)
+ {
+ first_entry++;
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+ }
+ }
+ else if (c == 7)
+ {
+ /* Page Up */
+- first_entry -= 12;
++ first_entry -= box_size;
+ if (first_entry < 0)
+ {
+ entryno += first_entry;
+@@ -463,20 +486,20 @@
+ if (entryno < 0)
+ entryno = 0;
+ }
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+ else if (c == 3)
+ {
+ /* Page Down */
+- first_entry += 12;
++ first_entry += box_size;
+ if (first_entry + entryno + 1 >= num_entries)
+ {
+- first_entry = num_entries - 12;
++ first_entry = num_entries - box_size;
+ if (first_entry < 0)
+ first_entry = 0;
+ entryno = num_entries - first_entry - 1;
+ }
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+
+ if (config_entries)
+@@ -489,7 +512,7 @@
+ if ((c == 'd') || (c == 'o') || (c == 'O'))
+ {
+ if (! (current_term->flags & TERM_DUMB))
+- print_entry (4 + entryno, 0,
++ print_entry (4 + entryno + row_start, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+@@ -537,7 +560,7 @@
+
+ if (entryno >= num_entries)
+ entryno--;
+- if (first_entry && num_entries < 12 + first_entry)
++ if (first_entry && num_entries < box_size + first_entry)
+ first_entry--;
+ }
+
+@@ -549,7 +572,7 @@
+ grub_printf ("\n");
+ }
+ else
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+
+ cur_entry = menu_entries;
+@@ -570,7 +593,7 @@
+ if (current_term->flags & TERM_DUMB)
+ grub_printf ("\r ");
+ else
+- gotoxy (1, 21);
++ gotoxy (1 + col_start, 9 + box_size + row_start);
+
+ /* Wipe out the previously entered password */
+ grub_memset (entered, 0, sizeof (entered));
+@@ -714,6 +737,15 @@
+
+ cls ();
+ setcursor (1);
++ /* if our terminal needed initialization, we should shut it down
++ * before booting the kernel, but we want to save what it was so
++ * we can come back if needed */
++ prev_term = current_term;
++ if (current_term->shutdown)
++ {
++ current_term->shutdown();
++ current_term = term_table; /* assumption: console is first */
++ }
+
+ while (1)
+ {
+@@ -748,6 +780,13 @@
+ break;
+ }
+
++ /* if we get back here, we should go back to what our term was before */
++ current_term = prev_term;
++ if (current_term->startup)
++ /* if our terminal fails to initialize, fall back to console since
++ * it should always work */
++ if (current_term->startup() == 0)
++ current_term = term_table; /* we know that console is first */
+ show_menu = 1;
+ goto restart;
+ }
+@@ -1050,6 +1089,16 @@
+ while (is_preset);
+ }
+
++ /* go ahead and make sure the terminal is setup */
++ if (current_term->startup)
++ {
++ /* If initialization fails, go back to default terminal */
++ if (current_term->startup() == 0)
++ {
++ current_term = term_table;
++ }
++ }
++
+ if (! num_entries)
+ {
+ /* If no acceptable config file, goto command-line, starting
+diff -Naur grub-0.97.orig/stage2/term.h grub-0.97/stage2/term.h
+--- grub-0.97.orig/stage2/term.h 2003-07-09 08:45:53.000000000 -0300
++++ grub-0.97/stage2/term.h 2005-06-13 14:07:40.000000000 -0300
+@@ -60,6 +60,8 @@
+ const char *name;
+ /* The feature flags defined above. */
+ unsigned long flags;
++ /* Default for maximum number of lines if not specified */
++ unsigned short max_lines;
+ /* Put a character. */
+ void (*putchar) (int c);
+ /* Check if any input character is available. */
+@@ -79,6 +81,10 @@
+ void (*setcolor) (int normal_color, int highlight_color);
+ /* Turn on/off the cursor. */
+ int (*setcursor) (int on);
++ /* function to start a terminal */
++ int (*startup) (void);
++ /* function to use to shutdown a terminal */
++ void (*shutdown) (void);
+ };
+
+ /* This lists up available terminals. */
+@@ -124,4 +130,24 @@
+ int hercules_setcursor (int on);
+ #endif
+
++#ifdef SUPPORT_GRAPHICS
++extern int foreground, background, window_border, graphics_inited, saved_videomode;
++
++void graphics_set_splash(char *splashfile);
++int set_videomode(int mode);
++int get_videomode(void);
++void graphics_putchar (int c);
++int graphics_getxy(void);
++void graphics_gotoxy(int x, int y);
++void graphics_cls(void);
++void graphics_setcolorstate (color_state state);
++void graphics_setcolor (int normal_color, int highlight_color);
++int graphics_setcursor (int on);
++int graphics_init(void);
++void graphics_end(void);
++
++int hex(int v);
++void graphics_set_palette(int idx, int red, int green, int blue);
++#endif /* SUPPORT_GRAPHICS */
++
+ #endif /* ! GRUB_TERM_HEADER */
diff --git a/stubdom/grub.patches/20print_func.diff b/stubdom/grub.patches/20print_func.diff
new file mode 100644
index 0000000000..ec9da0ea4e
--- /dev/null
+++ b/stubdom/grub.patches/20print_func.diff
@@ -0,0 +1,80 @@
+2006-01-05 Otavio Salvador <otavio@debian.org>
+
+ * Rediff.
+
+2005-16-10 Samuel Thibault <samuel.thibault@ens-lyon.org>
+
+ * docs/grub.texi: Added print command description.
+ * stage2/builtins.c(print_func): New function.
+ (builtin_print): New variable.
+ (builtin_table): Added builtin_print in table.
+
+Debian Status Following:
+ Added by: Otavio Salvador
+ Date: 2006-01-05
+
+diff -Nur grub-0.97-bkp/docs/grub.texi grub-0.97/docs/grub.texi
+--- grub-0.97-bkp/docs/grub.texi 2006-01-05 10:59:05.564347912 -0200
++++ grub-0.97/docs/grub.texi 2006-01-05 11:18:59.033912960 -0200
+@@ -2685,6 +2685,7 @@
+ * module:: Load a module
+ * modulenounzip:: Load a module without decompression
+ * pause:: Wait for a key press
++* print:: Print a message
+ * quit:: Exit from the grub shell
+ * reboot:: Reboot your computer
+ * read:: Read data from memory
+@@ -3091,6 +3092,16 @@
+ @end deffn
+
+
++@node print
++@subsection print
++
++@deffn Command print message @dots{}
++Print the @var{message}. Note that placing @key{^G} (ASCII code 7) in the
++message will cause the speaker to emit the standard beep sound, which is
++useful for visually impaired people.
++@end deffn
++
++
+ @node quit
+ @subsection quit
+
+diff -Nur grub-0.97-bkp/stage2/builtins.c grub-0.97/stage2/builtins.c
+--- grub-0.97-bkp/stage2/builtins.c 2006-01-05 10:59:05.550350040 -0200
++++ grub-0.97/stage2/builtins.c 2006-01-05 11:19:28.422445224 -0200
+@@ -2323,6 +2323,25 @@
+ "Probe I/O ports used for the drive DRIVE."
+ };
+
++/* print */
++static int
++print_func (char *arg, int flags)
++{
++ printf("%s\n", arg);
++
++ return 0;
++}
++
++static struct builtin builtin_print =
++{
++ "print",
++ print_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_NO_ECHO,
++ "print [MESSAGE ...]",
++ "Print MESSAGE."
++};
++
++
+
+ /* kernel */
+ static int
+@@ -4848,6 +4867,7 @@
+ &builtin_parttype,
+ &builtin_password,
+ &builtin_pause,
++ &builtin_print,
+ #ifdef GRUB_UTIL
+ &builtin_quit,
+ #endif /* GRUB_UTIL */
diff --git a/stubdom/grub.patches/30savedefault.diff b/stubdom/grub.patches/30savedefault.diff
new file mode 100644
index 0000000000..2902b876ec
--- /dev/null
+++ b/stubdom/grub.patches/30savedefault.diff
@@ -0,0 +1,186 @@
+Index: grub/stage2/builtins.c
+===================================================================
+--- grub.orig/stage2/builtins.c 2008-06-02 18:06:08.942580000 +0100
++++ grub/stage2/builtins.c 2008-06-06 18:35:07.548390000 +0100
+@@ -86,6 +86,10 @@
+ inside other functions. */
+ static int configfile_func (char *arg, int flags);
+
++static int savedefault_helper (char *arg, int flags);
++
++static int savedefault_shell (char *arg, int flags);
++
+ /* Initialize the data for builtins. */
+ void
+ init_builtins (void)
+@@ -3512,7 +3516,109 @@
+ static int
+ savedefault_func (char *arg, int flags)
+ {
+-#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
++#if !defined(SUPPORT_DISKLESS)
++ #if !defined(GRUB_UTIL)
++ return savedefault_helper(arg, flags);
++ #else
++ return savedefault_shell(arg, flags);
++ #endif
++#else /* !SUPPORT_DISKLESS */
++ errnum = ERR_UNRECOGNIZED;
++ return 1;
++#endif /* !SUPPORT_DISKLESS */
++}
++
++#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL)
++/* savedefault_shell */
++static int
++savedefault_shell(char *arg, int flags)
++ {
++ int once_only = 0;
++ int new_default;
++ int curr_default = -1;
++ int curr_prev_default = -1;
++ int new_prev_default = -1;
++ FILE *fp;
++ size_t bytes = 10;
++ char line[bytes];
++ char *default_file = (char *) DEFAULT_FILE_BUF;
++ char buf[bytes];
++ int i;
++
++ while (1)
++ {
++ if (grub_memcmp ("--default=", arg, sizeof ("--default=") - 1) == 0)
++ {
++ char *p = arg + sizeof ("--default=") - 1;
++ if (! safe_parse_maxint (&p, &new_default))
++ return 1;
++ arg = skip_to (0, arg);
++ }
++ else if (grub_memcmp ("--once", arg, sizeof ("--once") - 1) == 0)
++ {
++ once_only = 1;
++ arg = skip_to (0, arg);
++ }
++ else
++ break;
++ }
++
++ *default_file = 0;
++ grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN);
++ for (i = grub_strlen(default_file); i >= 0; i--)
++ if (default_file[i] == '/')
++ {
++ i++;
++ break;
++ }
++ default_file[i] = 0;
++ grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
++
++ if(!(fp = fopen(default_file,"r")))
++ {
++ errnum = ERR_READ;
++ goto fail;
++ }
++
++ fgets(line, bytes, fp);
++ fclose(fp);
++
++ sscanf(line, "%d:%d", &curr_prev_default, &curr_default);
++
++ if(curr_default != -1)
++ new_prev_default = curr_default;
++ else
++ {
++ if(curr_prev_default != -1)
++ new_prev_default = curr_prev_default;
++ else
++ new_prev_default = 0;
++ }
++
++ if(once_only)
++ sprintf(buf, "%d:%d", new_prev_default, new_default);
++ else
++ sprintf(buf, "%d", new_default);
++
++ if(!(fp = fopen(default_file,"w")))
++ {
++ errnum = ERR_READ;
++ goto fail;
++ }
++
++ fprintf(fp, buf);
++
++fail:
++ fclose(fp);
++ return errnum;
++}
++#endif
++
++/* savedefault_helper */
++static int
++savedefault_helper (char *arg, int flags)
++{
++#if !defined(SUPPORT_DISKLESS)
+ unsigned long tmp_drive = saved_drive;
+ unsigned long tmp_partition = saved_partition;
+ char *default_file = (char *) DEFAULT_FILE_BUF;
+@@ -3588,22 +3694,26 @@
+
+ disk_read_hook = disk_read_savesect_func;
+ len = grub_read (buf, sizeof (buf));
++ buf[9]='\0';/* Make sure grub_strstr() below terminates */
+ disk_read_hook = 0;
+ grub_close ();
+
+- if (len != sizeof (buf))
+- {
+- /* This is too small. Do not modify the file manually, please! */
+- errnum = ERR_READ;
+- goto fail;
+- }
+-
+ if (sector_count > 2)
+ {
+ /* Is this possible?! Too fragmented! */
+ errnum = ERR_FSYS_CORRUPT;
+ goto fail;
+ }
++
++ char *tmp;
++ if((tmp = grub_strstr(buf, ":")) != NULL)
++ {
++ int f_len = grub_strlen(buf) - grub_strlen(tmp);
++ char *def;
++ buf[f_len] = '\0';
++ def = buf;
++ safe_parse_maxint (&def, &entryno);
++ }
+
+ /* Set up a string to be written. */
+ grub_memset (buf, '\n', sizeof (buf));
+Index: grub/stage2/stage2.c
+===================================================================
+--- grub.orig/stage2/stage2.c 2008-06-02 18:06:08.858579000 +0100
++++ grub/stage2/stage2.c 2008-06-06 18:04:03.585354000 +0100
+@@ -49,7 +49,8 @@
+ return 0;
+ #endif /* GRUB_UTIL */
+
+- preset_menu_offset = 0;
++ if (preset_menu_offset)
++ return 0;
+ return preset_menu != 0;
+ }
+
+@@ -934,7 +935,11 @@
+ len = grub_read (buf, sizeof (buf));
+ if (len > 0)
+ {
++ char *tmp;
+ buf[sizeof (buf) - 1] = 0;
++ if((tmp = grub_strstr(p, ":")) != NULL)
++ p = tmp + 1;
++
+ safe_parse_maxint (&p, &saved_entryno);
+ }
+
diff --git a/stubdom/grub.patches/40ext3_256byte_inode.diff b/stubdom/grub.patches/40ext3_256byte_inode.diff
new file mode 100644
index 0000000000..0c40854f94
--- /dev/null
+++ b/stubdom/grub.patches/40ext3_256byte_inode.diff
@@ -0,0 +1,114 @@
+
+Patch from Red Hat. See #463236, #463123.
+
+Index: grub/stage2/fsys_ext2fs.c
+===================================================================
+--- grub.orig/stage2/fsys_ext2fs.c 2008-05-27 18:47:19.045183000 +0100
++++ grub/stage2/fsys_ext2fs.c 2008-05-27 19:09:21.293187000 +0100
+@@ -79,7 +79,52 @@
+ __u32 s_rev_level; /* Revision level */
+ __u16 s_def_resuid; /* Default uid for reserved blocks */
+ __u16 s_def_resgid; /* Default gid for reserved blocks */
+- __u32 s_reserved[235]; /* Padding to the end of the block */
++ /*
++ * These fields are for EXT2_DYNAMIC_REV superblocks only.
++ *
++ * Note: the difference between the compatible feature set and
++ * the incompatible feature set is that if there is a bit set
++ * in the incompatible feature set that the kernel doesn't
++ * know about, it should refuse to mount the filesystem.
++ *
++ * e2fsck's requirements are more strict; if it doesn't know
++ * about a feature in either the compatible or incompatible
++ * feature set, it must abort and not try to meddle with
++ * things it doesn't understand...
++ */
++ __u32 s_first_ino; /* First non-reserved inode */
++ __u16 s_inode_size; /* size of inode structure */
++ __u16 s_block_group_nr; /* block group # of this superblock */
++ __u32 s_feature_compat; /* compatible feature set */
++ __u32 s_feature_incompat; /* incompatible feature set */
++ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
++ __u8 s_uuid[16]; /* 128-bit uuid for volume */
++ char s_volume_name[16]; /* volume name */
++ char s_last_mounted[64]; /* directory where last mounted */
++ __u32 s_algorithm_usage_bitmap; /* For compression */
++ /*
++ * Performance hints. Directory preallocation should only
++ * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
++ */
++ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
++ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
++ __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
++ /*
++ * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
++ */
++ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
++ __u32 s_journal_inum; /* inode number of journal file */
++ __u32 s_journal_dev; /* device number of journal file */
++ __u32 s_last_orphan; /* start of list of inodes to delete */
++ __u32 s_hash_seed[4]; /* HTREE hash seed */
++ __u8 s_def_hash_version; /* Default hash version to use */
++ __u8 s_jnl_backup_type; /* Default type of journal backup */
++ __u16 s_reserved_word_pad;
++ __u32 s_default_mount_opts;
++ __u32 s_first_meta_bg; /* First metablock group */
++ __u32 s_mkfs_time; /* When the filesystem was created */
++ __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
++ __u32 s_reserved[172]; /* Padding to the end of the block */
+ };
+
+ struct ext2_group_desc
+@@ -218,6 +263,9 @@
+ #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+ #define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
+
++#define EXT2_INODE_SIZE(s) (SUPERBLOCK->s_inode_size)
++#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
++
+ /* linux/ext2_fs.h */
+ #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+ /* kind of from ext2/super.c */
+@@ -242,7 +290,14 @@
+ static __inline__ unsigned long
+ ffz (unsigned long word)
+ {
+- __asm__ ("bsfl %1,%0"
++ __asm__ ("bsf"
++#ifdef __i386__
++ "l"
++#endif
++#ifdef __x86_64__
++ "q"
++#endif
++ " %1,%0"
+ : "=r" (word)
+ : "r" (~word));
+ return word;
+@@ -553,7 +608,7 @@
+ gdp = GROUP_DESC;
+ ino_blk = gdp[desc].bg_inode_table +
+ (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
+- >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
++ >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
+ #ifdef E2DEBUG
+ printf ("inode table fsblock=%d\n", ino_blk);
+ #endif /* E2DEBUG */
+@@ -565,13 +620,12 @@
+ /* reset indirect blocks! */
+ mapblock2 = mapblock1 = -1;
+
+- raw_inode = INODE +
+- ((current_ino - 1)
+- & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
++ raw_inode = (struct ext2_inode *)((char *)INODE +
++ ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
++ EXT2_INODE_SIZE (SUPERBLOCK));
+ #ifdef E2DEBUG
+ printf ("ipb=%d, sizeof(inode)=%d\n",
+- (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
+- sizeof (struct ext2_inode));
++ EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
+ printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
+ printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
+ for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
diff --git a/stubdom/grub.patches/99minios b/stubdom/grub.patches/99minios
new file mode 100644
index 0000000000..3efc57177c
--- /dev/null
+++ b/stubdom/grub.patches/99minios
@@ -0,0 +1,1456 @@
+Index: grub/stage2/builtins.c
+===================================================================
+--- grub.orig/stage2/builtins.c 2008-06-16 15:18:14.649009000 +0100
++++ grub/stage2/builtins.c 2008-06-16 15:18:14.719009000 +0100
+@@ -45,8 +45,10 @@
+ #ifdef GRUB_UTIL
+ # include <device.h>
+ #else /* ! GRUB_UTIL */
++#ifndef __MINIOS
+ # include <apic.h>
+ # include <smp-imps.h>
++#endif
+ #endif /* ! GRUB_UTIL */
+
+ #ifdef USE_MD5_PASSWORDS
+@@ -246,11 +248,13 @@
+ boot_func (char *arg, int flags)
+ {
+ struct term_entry *prev_term = current_term;
++#ifndef __MINIOS__
+ /* Clear the int15 handler if we can boot the kernel successfully.
+ This assumes that the boot code never fails only if KERNEL_TYPE is
+ not KERNEL_TYPE_NONE. Is this assumption is bad? */
+ if (kernel_type != KERNEL_TYPE_NONE)
+ unset_int15_handler ();
++#endif
+
+ /* if our terminal needed initialization, we should shut it down
+ * before booting the kernel, but we want to save what it was so
+@@ -261,13 +265,21 @@
+ current_term = term_table; /* assumption: console is first */
+ }
+
++#ifndef __MINIOS__
+ #ifdef SUPPORT_NETBOOT
+ /* Shut down the networking. */
+ cleanup_net ();
+ #endif
++#endif
+
+ switch (kernel_type)
+ {
++#ifdef __MINIOS__
++ case KERNEL_TYPE_PV:
++ /* Paravirtualized */
++ pv_boot();
++ break;
++#else
+ case KERNEL_TYPE_FREEBSD:
+ case KERNEL_TYPE_NETBSD:
+ /* *BSD */
+@@ -319,6 +331,7 @@
+ multi_boot ((int) entry_addr, (int) &mbi);
+ break;
+
++#endif
+ default:
+ errnum = ERR_BOOT_COMMAND;
+ return 1;
+@@ -1123,6 +1136,7 @@
+ };
+
+
++#ifndef __MINIOS__
+ /* displayapm */
+ static int
+ displayapm_func (char *arg, int flags)
+@@ -1163,8 +1177,10 @@
+ "displayapm",
+ "Display APM BIOS information."
+ };
++#endif
+
+
++#ifndef __MINIOS__
+ /* displaymem */
+ static int
+ displaymem_func (char *arg, int flags)
+@@ -1218,6 +1234,7 @@
+ "Display what GRUB thinks the system address space map of the"
+ " machine is, including all regions of physical RAM installed."
+ };
++#endif
+
+
+ /* dump FROM TO */
+@@ -1280,6 +1297,7 @@
+ #endif /* GRUB_UTIL */
+
+
++#ifndef __MINIOS__
+ static char embed_info[32];
+ /* embed */
+ /* Embed a Stage 1.5 in the first cylinder after MBR or in the
+@@ -1413,6 +1431,7 @@
+ " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition."
+ " Print the number of sectors which STAGE1_5 occupies if successful."
+ };
++#endif
+
+
+ /* fallback */
+@@ -1956,6 +1975,7 @@
+ #endif /* SUPPORT_NETBOOT */
+
+
++#ifndef __MINIOS__
+ /* impsprobe */
+ static int
+ impsprobe_func (char *arg, int flags)
+@@ -1982,6 +2002,7 @@
+ " configuration table and boot the various CPUs which are found into"
+ " a tight loop."
+ };
++#endif
+
+
+ /* initrd */
+@@ -1992,6 +2013,7 @@
+ {
+ case KERNEL_TYPE_LINUX:
+ case KERNEL_TYPE_BIG_LINUX:
++ case KERNEL_TYPE_PV:
+ if (! load_initrd (arg))
+ return 1;
+ break;
+@@ -2015,6 +2037,7 @@
+ };
+
+
++#ifndef __MINIOS__
+ /* install */
+ static int
+ install_func (char *arg, int flags)
+@@ -2555,8 +2578,10 @@
+ " for LBA mode. If the option `--stage2' is specified, rewrite the Stage"
+ " 2 via your OS's filesystem instead of the raw device."
+ };
++#endif
+
+
++#ifndef __MINIOS__
+ /* ioprobe */
+ static int
+ ioprobe_func (char *arg, int flags)
+@@ -2598,6 +2623,7 @@
+ "ioprobe DRIVE",
+ "Probe I/O ports used for the drive DRIVE."
+ };
++#endif
+
+ /* print */
+ static int
+@@ -3776,6 +3802,7 @@
+ };
+
+
++#ifndef __MINIOS__
+ #ifdef SUPPORT_SERIAL
+ /* serial */
+ static int
+@@ -3927,8 +3954,10 @@
+ " default values are COM1, 9600, 8N1."
+ };
+ #endif /* SUPPORT_SERIAL */
++#endif
+
+
++#ifndef __MINIOS__
+ /* setkey */
+ struct keysym
+ {
+@@ -4174,8 +4203,10 @@
+ " is a digit), and delete. If no argument is specified, reset key"
+ " mappings."
+ };
++#endif
+
+
++#ifndef __MINIOS__
+ /* setup */
+ static int
+ setup_func (char *arg, int flags)
+@@ -4484,6 +4515,7 @@
+ " partition where GRUB images reside, specify the option `--stage2'"
+ " to tell GRUB the file name under your OS."
+ };
++#endif
+
+
+ #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+@@ -4788,6 +4820,7 @@
+ #endif /* SUPPORT_SERIAL */
+
+
++#ifndef __MINIOS__
+ /* testload */
+ static int
+ testload_func (char *arg, int flags)
+@@ -4874,8 +4907,10 @@
+ " consistent offset error. If this test succeeds, then a good next"
+ " step is to try loading a kernel."
+ };
++#endif
+
+
++#ifndef __MINIOS__
+ /* testvbe MODE */
+ static int
+ testvbe_func (char *arg, int flags)
+@@ -4979,6 +5014,7 @@
+ "testvbe MODE",
+ "Test the VBE mode MODE. Hit any key to return."
+ };
++#endif
+
+
+ #ifdef SUPPORT_NETBOOT
+@@ -5075,6 +5111,7 @@
+ };
+
+
++#ifndef __MINIOS__
+ /* uppermem */
+ static int
+ uppermem_func (char *arg, int flags)
+@@ -5095,8 +5132,10 @@
+ "Force GRUB to assume that only KBYTES kilobytes of upper memory are"
+ " installed. Any system address range maps are discarded."
+ };
++#endif
+
+
++#ifndef __MINIOS__
+ /* vbeprobe */
+ static int
+ vbeprobe_func (char *arg, int flags)
+@@ -5203,6 +5242,7 @@
+ "Probe VBE information. If the mode number MODE is specified, show only"
+ " the information about only the mode."
+ };
++#endif
+
+
+ /* The table of builtin commands. Sorted in dictionary order. */
+@@ -5233,12 +5273,16 @@
+ #ifdef SUPPORT_NETBOOT
+ &builtin_dhcp,
+ #endif /* SUPPORT_NETBOOT */
++#ifndef __MINIOS__
+ &builtin_displayapm,
+ &builtin_displaymem,
++#endif
+ #ifdef GRUB_UTIL
+ &builtin_dump,
+ #endif /* GRUB_UTIL */
++#ifndef __MINIOS__
+ &builtin_embed,
++#endif
+ &builtin_fallback,
+ &builtin_find,
+ #ifdef SUPPORT_GRAPHICS
+@@ -5253,10 +5297,14 @@
+ #ifdef SUPPORT_NETBOOT
+ &builtin_ifconfig,
+ #endif /* SUPPORT_NETBOOT */
++#ifndef __MINIOS__
+ &builtin_impsprobe,
++#endif
+ &builtin_initrd,
++#ifndef __MINIOS__
+ &builtin_install,
+ &builtin_ioprobe,
++#endif
+ &builtin_kernel,
+ &builtin_lock,
+ &builtin_makeactive,
+@@ -5283,11 +5331,13 @@
+ &builtin_root,
+ &builtin_rootnoverify,
+ &builtin_savedefault,
++#ifndef __MINIOS__
+ #ifdef SUPPORT_SERIAL
+ &builtin_serial,
+ #endif /* SUPPORT_SERIAL */
+ &builtin_setkey,
+ &builtin_setup,
++#endif
+ #ifdef SUPPORT_GRAPHICS
+ &builtin_shade,
+ &builtin_splashimage,
+@@ -5298,16 +5348,20 @@
+ #ifdef SUPPORT_SERIAL
+ &builtin_terminfo,
+ #endif /* SUPPORT_SERIAL */
++#ifndef __MINIOS__
+ &builtin_testload,
+ &builtin_testvbe,
++#endif
+ #ifdef SUPPORT_NETBOOT
+ &builtin_tftpserver,
+ #endif /* SUPPORT_NETBOOT */
+ &builtin_timeout,
+ &builtin_title,
+ &builtin_unhide,
++#ifndef __MINIOS__
+ &builtin_uppermem,
+ &builtin_vbeprobe,
++#endif
+ #ifdef SUPPORT_GRAPHICS
+ &builtin_viewport,
+ #endif
+Index: grub/stage2/char_io.c
+===================================================================
+--- grub.orig/stage2/char_io.c 2008-06-16 15:18:14.516009000 +0100
++++ grub/stage2/char_io.c 2008-06-16 15:18:14.726009000 +0100
+@@ -20,6 +20,7 @@
+
+ #include <shared.h>
+ #include <term.h>
++#include <stdarg.h>
+
+ #ifdef SUPPORT_HERCULES
+ # include <hercules.h>
+@@ -36,6 +37,7 @@
+ #ifndef STAGE1_5
+ struct term_entry term_table[] =
+ {
++#ifdef SUPPORT_CONSOLE
+ {
+ "console",
+ 0,
+@@ -52,6 +54,7 @@
+ 0,
+ 0
+ },
++#endif
+ #ifdef SUPPORT_SERIAL
+ {
+ "serial",
+@@ -131,9 +134,9 @@
+ }
+
+ char *
+-convert_to_ascii (char *buf, int c,...)
++convert_to_ascii (char *buf, int c, int _num)
+ {
+- unsigned long num = *((&c) + 1), mult = 10;
++ unsigned long num = _num, mult = 10;
+ char *ptr = buf;
+
+ #ifndef STAGE1_5
+@@ -182,11 +185,11 @@
+ void
+ grub_printf (const char *format,...)
+ {
+- int *dataptr = (int *) &format;
++ va_list ap;
+ char c, str[16];
+-
+- dataptr++;
+
++ va_start(ap, format);
++
+ while ((c = *(format++)) != 0)
+ {
+ if (c != '%')
+@@ -200,21 +203,32 @@
+ case 'X':
+ #endif
+ case 'u':
+- *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
++ {
++ unsigned i = va_arg(ap, unsigned);
++ *convert_to_ascii (str, c, i) = 0;
+ grub_putstr (str);
+ break;
++ }
+
+ #ifndef STAGE1_5
+ case 'c':
+- grub_putchar ((*(dataptr++)) & 0xff);
++ {
++ int c = va_arg(ap, int);
++ grub_putchar (c & 0xff);
+ break;
++ }
+
+ case 's':
+- grub_putstr ((char *) *(dataptr++));
++ {
++ char *s = va_arg(ap, char*);
++ grub_putstr (s);
+ break;
++ }
+ #endif
+ }
+ }
++
++ va_end(ap);
+ }
+
+ #ifndef STAGE1_5
+@@ -223,11 +237,11 @@
+ {
+ /* XXX hohmuth
+ ugly hack -- should unify with printf() */
+- int *dataptr = (int *) &format;
++ va_list ap;
+ char c, *ptr, str[16];
+ char *bp = buffer;
+
+- dataptr++;
++ va_start(ap, format);
+
+ while ((c = *format++) != 0)
+ {
+@@ -237,20 +251,27 @@
+ switch (c = *(format++))
+ {
+ case 'd': case 'u': case 'x':
+- *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
++ {
++ unsigned i = va_arg(ap, unsigned);
++ *convert_to_ascii (str, c, i) = 0;
+
+ ptr = str;
+
+ while (*ptr)
+ *bp++ = *(ptr++); /* putchar(*(ptr++)); */
+ break;
++ }
+
+- case 'c': *bp++ = (*(dataptr++))&0xff;
++ case 'c':
++ {
++ int c = va_arg(ap, int);
++ *bp++ = c&0xff;
+ /* putchar((*(dataptr++))&0xff); */
+ break;
++ }
+
+ case 's':
+- ptr = (char *) (*(dataptr++));
++ ptr = va_arg(ap, char *);
+
+ while ((c = *ptr++) != 0)
+ *bp++ = c; /* putchar(c); */
+@@ -258,6 +279,8 @@
+ }
+ }
+
++ va_end(ap);
++
+ *bp = 0;
+ return bp - buffer;
+ }
+@@ -1263,12 +1286,14 @@
+ return ! errnum;
+ #endif /* GRUB_UTIL */
+
++#ifndef __MINIOS__
+ if ((addr < RAW_ADDR (0x1000))
+ || (addr < RAW_ADDR (0x100000)
+ && RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
+ || (addr >= RAW_ADDR (0x100000)
+ && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
+ errnum = ERR_WONT_FIT;
++#endif
+
+ return ! errnum;
+ }
+@@ -1342,7 +1367,7 @@
+ }
+ #endif /* ! STAGE1_5 */
+
+-#ifndef GRUB_UTIL
++#if !defined(GRUB_UTIL) && !defined(__MINIOS__)
+ # undef memcpy
+ /* GCC emits references to memcpy() for struct copies etc. */
+ void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
+Index: grub/stage2/disk_io.c
+===================================================================
+--- grub.orig/stage2/disk_io.c 2008-06-16 15:18:03.327932000 +0100
++++ grub/stage2/disk_io.c 2008-06-16 15:18:14.733009000 +0100
+@@ -130,7 +130,14 @@
+ static inline unsigned long
+ log2 (unsigned long word)
+ {
+- asm volatile ("bsfl %1,%0"
++ asm volatile ("bsf"
++#ifdef __i386__
++ "l"
++#endif
++#ifdef __x86_64__
++ "q"
++#endif
++ " %1,%0"
+ : "=r" (word)
+ : "r" (word));
+ return word;
+Index: grub/stage2/fsys_fat.c
+===================================================================
+--- grub.orig/stage2/fsys_fat.c 2008-06-16 15:18:03.337934000 +0100
++++ grub/stage2/fsys_fat.c 2008-06-16 15:18:14.737009000 +0100
+@@ -57,7 +57,14 @@
+ static __inline__ unsigned long
+ log2 (unsigned long word)
+ {
+- __asm__ ("bsfl %1,%0"
++ __asm__ ("bsf"
++#ifdef __i386__
++ "l"
++#endif
++#ifdef __x86_64__
++ "q"
++#endif
++ " %1,%0"
+ : "=r" (word)
+ : "r" (word));
+ return word;
+Index: grub/stage2/pc_slice.h
+===================================================================
+--- grub.orig/stage2/pc_slice.h 2008-06-16 15:18:03.347932000 +0100
++++ grub/stage2/pc_slice.h 2008-06-16 15:18:14.746009000 +0100
+@@ -38,50 +38,50 @@
+ */
+
+ #define PC_MBR_CHECK_SIG(mbr_ptr) \
+- ( *( (unsigned short *) (((int) mbr_ptr) + PC_MBR_SIG_OFFSET) ) \
++ ( *( (unsigned short *) (((long) mbr_ptr) + PC_MBR_SIG_OFFSET) ) \
+ == PC_MBR_SIGNATURE )
+
+ #define PC_MBR_SIG(mbr_ptr) \
+- ( *( (unsigned short *) (((int) mbr_ptr) + PC_MBR_SIG_OFFSET) ) )
++ ( *( (unsigned short *) (((long) mbr_ptr) + PC_MBR_SIG_OFFSET) ) )
+
+ #define PC_SLICE_FLAG(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_HEAD(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 1 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 1 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_SEC(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 2 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 2 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_CYL(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 3 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 3 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_TYPE(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 4 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 4 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_EHEAD(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 5 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 5 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_ESEC(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 6 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 6 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_ECYL(mbr_ptr, part) \
+- ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 7 \
++ ( *( (unsigned char *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 7 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_START(mbr_ptr, part) \
+- ( *( (unsigned long *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 8 \
++ ( *( (unsigned long *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 8 \
+ + (part << 4)) ) )
+
+ #define PC_SLICE_LENGTH(mbr_ptr, part) \
+- ( *( (unsigned long *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 12 \
++ ( *( (unsigned long *) (((long) mbr_ptr) + PC_SLICE_OFFSET + 12 \
+ + (part << 4)) ) )
+
+
+Index: grub/stage2/shared.h
+===================================================================
+--- grub.orig/stage2/shared.h 2008-06-16 15:18:14.537009000 +0100
++++ grub/stage2/shared.h 2008-06-17 14:25:08.443906000 +0100
+@@ -39,6 +39,10 @@
+ extern char *grub_scratch_mem;
+ # define RAW_ADDR(x) ((x) + (int) grub_scratch_mem)
+ # define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4)
++#elif defined(__MINIOS__)
++extern char grub_scratch_mem[];
++# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem)
++# define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4)
+ #else
+ # define RAW_ADDR(x) (x)
+ # define RAW_SEG(x) (x)
+@@ -707,7 +711,9 @@
+
+ /* Halt the system, using APM if possible. If NO_APM is true, don't use
+ APM even if it is available. */
++#ifndef __MINIOS__
+ void grub_halt (int no_apm) __attribute__ ((noreturn));
++#endif
+
+ /* Copy MAP to the drive map and set up int13_handler. */
+ void set_int13_handler (unsigned short *map);
+@@ -857,7 +863,8 @@
+ KERNEL_TYPE_BIG_LINUX, /* Big Linux. */
+ KERNEL_TYPE_FREEBSD, /* FreeBSD. */
+ KERNEL_TYPE_NETBSD, /* NetBSD. */
+- KERNEL_TYPE_CHAINLOADER /* Chainloader. */
++ KERNEL_TYPE_CHAINLOADER, /* Chainloader. */
++ KERNEL_TYPE_PV /* Paravirtualized. */
+ }
+ kernel_t;
+
+@@ -890,7 +897,7 @@
+ int grub_strlen (const char *str);
+ char *grub_strcpy (char *dest, const char *src);
+
+-#ifndef GRUB_UTIL
++#if !defined(GRUB_UTIL) && !defined(__MINIOS__)
+ typedef unsigned long grub_jmp_buf[6];
+ #else
+ /* In the grub shell, use the libc jmp_buf instead. */
+@@ -898,7 +905,7 @@
+ # define grub_jmp_buf jmp_buf
+ #endif
+
+-#ifdef GRUB_UTIL
++#if defined(GRUB_UTIL) || defined(__MINIOS__)
+ # define grub_setjmp setjmp
+ # define grub_longjmp longjmp
+ #else /* ! GRUB_UTIL */
+@@ -914,7 +921,7 @@
+ /* misc */
+ void init_page (void);
+ void print_error (void);
+-char *convert_to_ascii (char *buf, int c, ...);
++char *convert_to_ascii (char *buf, int c, int num);
+ int get_cmdline (char *prompt, char *cmdline, int maxlen,
+ int echo_char, int history);
+ int substring (const char *s1, const char *s2);
+Index: grub/netboot/etherboot.h
+===================================================================
+--- grub.orig/netboot/etherboot.h 2008-06-16 15:18:03.446934000 +0100
++++ grub/netboot/etherboot.h 2008-06-16 15:18:14.760009000 +0100
+@@ -246,7 +246,7 @@
+
+ typedef struct
+ {
+- unsigned long s_addr;
++ unsigned int s_addr;
+ }
+ in_addr;
+
+@@ -302,7 +302,7 @@
+ char bp_htype;
+ char bp_hlen;
+ char bp_hops;
+- unsigned long bp_xid;
++ unsigned int bp_xid;
+ unsigned short bp_secs;
+ unsigned short unused;
+ in_addr bp_ciaddr;
+@@ -411,25 +411,25 @@
+
+ struct
+ {
+- long id;
+- long type;
+- long rpcvers;
+- long prog;
+- long vers;
+- long proc;
+- long data[1];
++ int id;
++ int type;
++ int rpcvers;
++ int prog;
++ int vers;
++ int proc;
++ int data[1];
+ }
+ call;
+
+ struct
+ {
+- long id;
+- long type;
+- long rstatus;
+- long verifier;
+- long v2;
+- long astatus;
+- long data[1];
++ int id;
++ int type;
++ int rstatus;
++ int verifier;
++ int v2;
++ int astatus;
++ int data[1];
+ }
+ reply;
+ }
+@@ -517,7 +517,9 @@
+
+ /* misc.c */
+ extern void twiddle (void);
++#ifndef __MINIOS__
+ extern void sleep (int secs);
++#endif
+ extern int getdec (char **s);
+ extern void etherboot_printf (const char *, ...);
+ extern int etherboot_sprintf (char *, const char *, ...);
+Index: grub/stage2/common.c
+===================================================================
+--- grub.orig/stage2/common.c 2008-06-16 15:18:03.366934000 +0100
++++ grub/stage2/common.c 2008-06-16 15:18:14.764009000 +0100
+@@ -137,6 +137,7 @@
+ }
+ #endif /* ! STAGE1_5 */
+
++#ifndef __MINIOS__
+ /* This queries for BIOS information. */
+ void
+ init_bios_info (void)
+@@ -335,3 +336,4 @@
+ /* Start main routine here. */
+ cmain ();
+ }
++#endif
+Index: grub/stage2/serial.c
+===================================================================
+--- grub.orig/stage2/serial.c 2008-06-16 15:18:03.376934000 +0100
++++ grub/stage2/serial.c 2008-06-16 15:18:14.769009000 +0100
+@@ -37,7 +37,7 @@
+
+ /* Hardware-dependent definitions. */
+
+-#ifndef GRUB_UTIL
++#if !defined(GRUB_UTIL) && !defined(__MINIOS__)
+ /* The structure for speed vs. divisor. */
+ struct divisor
+ {
+@@ -222,6 +222,8 @@
+ {('3' | ('~' << 8)), 4},
+ {('5' | ('~' << 8)), 7},
+ {('6' | ('~' << 8)), 3},
++ {('7' | ('~' << 8)), 1},
++ {('8' | ('~' << 8)), 5},
+ };
+
+ /* The buffer must start with ``ESC [''. */
+Index: grub/stage2/tparm.c
+===================================================================
+--- grub.orig/stage2/tparm.c 2008-06-16 15:18:03.390933000 +0100
++++ grub/stage2/tparm.c 2008-06-16 15:18:14.774010000 +0100
+@@ -48,6 +48,7 @@
+ #include "shared.h"
+
+ #include "tparm.h"
++#include <stdarg.h>
+
+ /*
+ * Common/troublesome character definitions
+@@ -320,7 +321,7 @@
+ #define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
+
+ static inline char *
+-tparam_internal(const char *string, int *dataptr)
++tparam_internal(const char *string, va_list ap)
+ {
+ #define NUM_VARS 26
+ char *p_is_s[9];
+@@ -461,9 +462,9 @@
+ * a char* and an int may not be the same size on the stack.
+ */
+ if (p_is_s[i] != 0) {
+- p_is_s[i] = (char *)(*(dataptr++));
++ p_is_s[i] = va_arg(ap, char *);
+ } else {
+- param[i] = (int)(*(dataptr++));
++ param[i] = va_arg(ap, int);
+ }
+ }
+
+@@ -716,11 +717,13 @@
+ grub_tparm(const char *string,...)
+ {
+ char *result;
+- int *dataptr = (int *) &string;
++ va_list ap;
+
+- dataptr++;
++ va_start(ap, string);
+
+- result = tparam_internal(string, dataptr);
++ result = tparam_internal(string, ap);
++
++ va_end(ap);
+
+ return result;
+ }
+Index: grub/stage2/fsys_iso9660.c
+===================================================================
+--- grub.orig/stage2/fsys_iso9660.c 2008-06-16 15:18:03.400933000 +0100
++++ grub/stage2/fsys_iso9660.c 2008-06-16 15:18:14.779009000 +0100
+@@ -59,7 +59,14 @@
+ static inline unsigned long
+ log2 (unsigned long word)
+ {
+- asm volatile ("bsfl %1,%0"
++ asm volatile ("bsf"
++#ifdef __i386__
++ "l"
++#endif
++#ifdef __x86_64__
++ "q"
++#endif
++ " %1,%0"
+ : "=r" (word)
+ : "r" (word));
+ return word;
+Index: grub/stage2/fsys_reiserfs.c
+===================================================================
+--- grub.orig/stage2/fsys_reiserfs.c 2008-06-16 15:18:03.410933000 +0100
++++ grub/stage2/fsys_reiserfs.c 2008-06-16 15:18:14.786009000 +0100
+@@ -369,7 +369,14 @@
+ static __inline__ unsigned long
+ log2 (unsigned long word)
+ {
+- __asm__ ("bsfl %1,%0"
++ __asm__ ("bsf"
++#ifdef __i386__
++ "l"
++#endif
++#ifdef __x86_64__
++ "q"
++#endif
++ " %1,%0"
+ : "=r" (word)
+ : "r" (word));
+ return word;
+Index: grub/netboot/misc.c
+===================================================================
+--- grub.orig/netboot/misc.c 2008-06-16 15:18:03.456934000 +0100
++++ grub/netboot/misc.c 2008-06-16 15:18:14.790009000 +0100
+@@ -21,7 +21,9 @@
+
+ #define GRUB 1
+ #include <etherboot.h>
++#include <stdarg.h>
+
++#ifndef __MINIOS__
+ void
+ sleep (int secs)
+ {
+@@ -30,6 +32,7 @@
+ while (currticks () < tmo)
+ ;
+ }
++#endif
+
+ void
+ twiddle (void)
+@@ -71,7 +74,7 @@
+ Note: width specification not supported
+ **************************************************************************/
+ static int
+-etherboot_vsprintf (char *buf, const char *fmt, const int *dp)
++etherboot_vsprintf (char *buf, const char *fmt, va_list ap)
+ {
+ char *p, *s;
+
+@@ -86,7 +89,7 @@
+
+ if (*++fmt == 's')
+ {
+- for (p = (char *) *dp++; *p != '\0'; p++)
++ for (p = va_arg(ap, char *); *p != '\0'; p++)
+ buf ? *s++ = *p : grub_putchar (*p);
+ }
+ else
+@@ -121,11 +124,9 @@
+ if ((*fmt | 0x20) == 'x')
+ {
+ /* With x86 gcc, sizeof(long) == sizeof(int) */
+- const long *lp = (const long *) dp;
+- long h = *lp++;
++ long h = va_arg(ap, int);
+ int ncase = (*fmt & 0x20);
+
+- dp = (const int *) lp;
+ if (alt)
+ {
+ *q++ = '0';
+@@ -136,7 +137,7 @@
+ }
+ else if (*fmt == 'd')
+ {
+- int i = *dp++;
++ int i = va_arg(ap, int);
+ char *r;
+
+ if (i < 0)
+@@ -171,10 +172,8 @@
+ unsigned char c[4];
+ }
+ u;
+- const long *lp = (const long *) dp;
+
+- u.l = *lp++;
+- dp = (const int *) lp;
++ u.l = va_arg(ap, int);
+
+ for (r = &u.c[0]; r < &u.c[4]; ++r)
+ q += etherboot_sprintf (q, "%d.", *r);
+@@ -184,7 +183,7 @@
+ else if (*fmt == '!')
+ {
+ char *r;
+- p = (char *) *dp++;
++ p = va_arg(ap, char *);
+
+ for (r = p + ETH_ALEN; p < r; ++p)
+ q += etherboot_sprintf (q, "%hhX:", *p);
+@@ -192,7 +191,7 @@
+ --q;
+ }
+ else if (*fmt == 'c')
+- *q++ = *dp++;
++ *q++ = va_arg(ap, int);
+ else
+ *q++ = *fmt;
+
+@@ -211,13 +210,21 @@
+ int
+ etherboot_sprintf (char *buf, const char *fmt, ...)
+ {
+- return etherboot_vsprintf (buf, fmt, ((const int *) &fmt) + 1);
++ va_list ap;
++ int ret;
++ va_start(ap, fmt);
++ ret = etherboot_vsprintf (buf, fmt, ap);
++ va_end(ap);
++ return ret;
+ }
+
+ void
+ etherboot_printf (const char *fmt, ...)
+ {
+- (void) etherboot_vsprintf (0, fmt, ((const int *) &fmt) + 1);
++ va_list ap;
++ va_start(ap, fmt);
++ etherboot_vsprintf (0, fmt, ap);
++ va_end(ap);
+ }
+
+ int
+Index: grub/netboot/main.c
+===================================================================
+--- grub.orig/netboot/main.c 2008-06-16 15:18:03.470932000 +0100
++++ grub/netboot/main.c 2008-06-16 15:18:14.797009000 +0100
+@@ -55,7 +55,7 @@
+ static int vendorext_isvalid;
+ static unsigned long netmask;
+ static struct bootpd_t bootp_data;
+-static unsigned long xid;
++static unsigned int xid;
+
+ #define BOOTP_DATA_ADDR (&bootp_data)
+
+@@ -778,7 +778,7 @@
+
+ arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
+
+- if (arpreply->opcode == htons (ARP_REPLY)
++ if (arpreply->opcode == htons (ARP_REPLY) && ptr
+ && ! grub_memcmp (arpreply->sipaddr, ptr, sizeof (in_addr))
+ && type == AWAIT_ARP)
+ {
+@@ -827,7 +827,7 @@
+ {
+ arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
+
+- if (arpreply->opcode == htons (RARP_REPLY)
++ if (arpreply->opcode == htons (RARP_REPLY) && ptr
+ && ! grub_memcmp (arpreply->thwaddr, ptr, ETH_ALEN))
+ {
+ grub_memmove ((char *) arptable[ARP_SERVER].node,
+@@ -1135,7 +1135,7 @@
+ long
+ rfc2131_sleep_interval (int base, int exp)
+ {
+- static long seed = 0;
++ static unsigned seed = 0;
+ long q;
+ unsigned long tmo;
+
+Index: grub/stage2/graphics.c
+===================================================================
+--- grub.orig/stage2/graphics.c 2008-06-16 15:18:14.524009000 +0100
++++ grub/stage2/graphics.c 2008-06-17 14:29:05.204328000 +0100
+@@ -30,7 +30,29 @@
+ #include <shared.h>
+ #include <graphics.h>
+
++#ifdef __MINIOS__
++#include <stdint.h>
++typedef uint8_t Bit8u;
++#include <vgafonts.h>
++#include <fbfront.h>
++#include <malloc.h>
++#define set_int1c_handler() (void)0
++#define unset_int1c_handler() (void)0
++static uint32_t *VIDEOMEM;
++static struct fbfront_dev *fb_dev;
++static uint32_t palette[17];
++short cursorX, cursorY;
++/* TODO: blink */
++uint32_t cursorBuf32[16*8];
++#define WIDTH 640
++#define HEIGHT 480
++#define DEPTH 32
++#define RAMSIZE (WIDTH * HEIGHT * (DEPTH / 8))
++#else
++#define fbfront_update(dev, x, y, w, h) (void)0
+ int saved_videomode;
++#endif
++
+ unsigned char *font8x16;
+
+ int graphics_inited = 0;
+@@ -38,11 +60,15 @@
+
+ int shade = 1, no_cursor = 0;
+
++#ifdef __MINIOS__
++uint32_t VSHADOW[RAMSIZE];
++#else
+ #define VSHADOW VSHADOW1
+ unsigned char VSHADOW1[38400];
+ unsigned char VSHADOW2[38400];
+ unsigned char VSHADOW4[38400];
+ unsigned char VSHADOW8[38400];
++#endif
+
+ /* define the default viewable area */
+ int view_x0 = 0;
+@@ -129,6 +155,8 @@
+ count_lines = k;
+
+ no_scroll = 0;
++
++ fbfront_update(fb_dev, view_x0 * 8, view_y0 * 16, (view_x1 - view_x0) * 8, (view_y1 - view_y0) * 16);
+ }
+
+ /* Set the splash image */
+@@ -154,17 +182,29 @@
+ int graphics_init()
+ {
+ if (!graphics_inited) {
++#ifdef __MINIOS__
++ VIDEOMEM = memalign(PAGE_SIZE, RAMSIZE);
++ if (!(fb_dev = fb_open(VIDEOMEM, WIDTH, HEIGHT, DEPTH))) {
++ free(VIDEOMEM);
++ return 0;
++ }
++#else
+ saved_videomode = set_videomode(0x12);
+ if (get_videomode() != 0x12) {
+ set_videomode(saved_videomode);
+ return 0;
+ }
++#endif
+ graphics_inited = 1;
+ }
+ else
+ return 1;
+
++#ifdef __MINIOS__
++ font8x16 = vgafont16;
++#else
+ font8x16 = (unsigned char*)graphics_get_font();
++#endif
+
+ /* make sure that the highlight color is set correctly */
+ graphics_highlight_color = ((graphics_normal_color >> 4) |
+@@ -176,7 +216,11 @@
+ grub_printf("Failed to read splash image (%s)\n", splashimage);
+ grub_printf("Press any key to continue...");
+ getkey();
++#ifdef __MINIOS__
++ fb_close();
++#else
+ set_videomode(saved_videomode);
++#endif
+ graphics_inited = 0;
+ return 0;
+ }
+@@ -190,8 +234,13 @@
+ void graphics_end(void)
+ {
+ if (graphics_inited) {
++#ifdef __MINIOS__
++ fb_close();
++ free(VIDEOMEM);
++#else
+ unset_int1c_handler();
+ set_videomode(saved_videomode);
++#endif
+ graphics_inited = 0;
+ no_cursor = 0;
+ }
+@@ -204,15 +253,19 @@
+ graphics_cursor(0);
+
+ if (ch == '\n') {
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ if (fonty + 1 < view_y1)
+ graphics_setxy(fontx, fonty + 1);
+ else
+ graphics_scroll();
+ graphics_cursor(1);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ return;
+ } else if (ch == '\r') {
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ graphics_setxy(view_x0, fonty);
+ graphics_cursor(1);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ return;
+ }
+
+@@ -224,6 +277,7 @@
+ text[fonty * 80 + fontx] |= 0x100;
+
+ graphics_cursor(0);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+
+ if ((fontx + 1) >= view_x1) {
+ graphics_setxy(view_x0, fonty);
+@@ -232,13 +286,16 @@
+ else
+ graphics_scroll();
+ graphics_cursor(1);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ do_more ();
+ graphics_cursor(0);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ } else {
+ graphics_setxy(fontx + 1, fonty);
+ }
+
+ graphics_cursor(1);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ }
+
+ /* get the current location of the cursor */
+@@ -248,10 +305,12 @@
+
+ void graphics_gotoxy(int x, int y) {
+ graphics_cursor(0);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+
+ graphics_setxy(x, y);
+
+ graphics_cursor(1);
++ fbfront_update(fb_dev, cursorX, cursorY, 8, 16);
+ }
+
+ void graphics_cls(void) {
+@@ -262,15 +321,21 @@
+ graphics_gotoxy(view_x0, view_y0);
+
+ mem = (unsigned char*)VIDEOMEM;
++#ifndef __MINIOS__
+ s1 = (unsigned char*)VSHADOW1;
+ s2 = (unsigned char*)VSHADOW2;
+ s4 = (unsigned char*)VSHADOW4;
+ s8 = (unsigned char*)VSHADOW8;
++#endif
+
+ for (i = 0; i < 80 * 30; i++)
+ text[i] = ' ';
+ graphics_cursor(1);
+
++#ifdef __MINIOS__
++ memcpy(mem, VSHADOW, RAMSIZE);
++ fbfront_update(fb_dev, 0, 0, 640, 480);
++#else
+ BitMask(0xff);
+
+ /* plane 1 */
+@@ -290,6 +355,7 @@
+ grub_memcpy(mem, s8, 38400);
+
+ MapMask(15);
++#endif
+
+ if (no_cursor) {
+ no_cursor = 0;
+@@ -337,6 +403,11 @@
+ return 0;
+ }
+
++void graphics_set_palette(int idx, int red, int green, int blue)
++{
++ palette[idx] = (red << (16 + 2)) | (green << (8 + 2)) | (blue << 2);
++}
++
+ /* Read in the splashscreen image and set the palette up appropriately.
+ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
+ * 640x480. */
+@@ -413,18 +484,19 @@
+ }
+
+ if (len == 6 && idx < 15) {
+- int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
+- int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
+- int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
++ int r = ((hex(buf[0]) << 4) | hex(buf[1]));
++ int g = ((hex(buf[2]) << 4) | hex(buf[3]));
++ int b = ((hex(buf[4]) << 4) | hex(buf[5]));
+
+ pal[idx] = base;
+- graphics_set_palette(idx, r, g, b);
++ graphics_set_palette(idx, r / 4, g / 4, b / 4);
+ ++idx;
+ }
+ }
+
+ x = y = len = 0;
+
++#ifndef __MINIOS__
+ s1 = (unsigned char*)VSHADOW1;
+ s2 = (unsigned char*)VSHADOW2;
+ s4 = (unsigned char*)VSHADOW4;
+@@ -432,6 +504,7 @@
+
+ for (i = 0; i < 38400; i++)
+ s1[i] = s2[i] = s4[i] = s8[i] = 0;
++#endif
+
+ /* parse xpm data */
+ while (y < height) {
+@@ -451,6 +524,9 @@
+ break;
+ }
+
++#ifdef __MINIOS__
++ VSHADOW[x + y * 640] = palette[i];
++#else
+ mask = 0x80 >> (x & 7);
+ if (c & 1)
+ s1[len + (x >> 3)] |= mask;
+@@ -460,6 +536,7 @@
+ s4[len + (x >> 3)] |= mask;
+ if (c & 8)
+ s8[len + (x >> 3)] |= mask;
++#endif
+
+ if (++x >= 640) {
+ x = 0;
+@@ -494,7 +571,13 @@
+ }
+
+ void graphics_cursor(int set) {
+- unsigned char *pat, *mem, *ptr, chr[16 << 2];
++ unsigned char *pat;
++#ifdef __MINIOS__
++ uint32_t *mem, *ptr, chr[16 * 8];
++ int j;
++#else
++ unsigned char *mem, *ptr, chr[16 << 2];
++#endif
+ int i, ch, invert, offset;
+
+ if (set && (no_cursor || no_scroll))
+@@ -505,71 +588,127 @@
+ invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
+ pat = font8x16 + (ch << 4);
+
+- mem = (unsigned char*)VIDEOMEM + offset;
++ mem = (unsigned char*)VIDEOMEM + offset
++#ifdef __MINIOS__
++ * 8 * 4
++#endif
++ ;
+
+ if (!set) {
+ for (i = 0; i < 16; i++) {
+ unsigned char mask = pat[i];
+
+ if (!invert) {
++#ifdef __MINIOS__
++ memcpy(chr + i * 8, VSHADOW + offset * 8, 8 * 4);
++#else
+ chr[i ] = ((unsigned char*)VSHADOW1)[offset];
+ chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
+ chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
+ chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
++#endif
+
+ if (shade) {
+ if (ch == DISP_VERT || ch == DISP_LL ||
+ ch == DISP_UR || ch == DISP_LR) {
+ unsigned char pmask = ~(pat[i] >> 1);
+
++#ifdef __MINIOS__
++ for (j = 0; j < 8; j++)
++ if (!(pmask & (1U << j)))
++ chr[i * 8 + (7 - j)] = palette[0];
++#else
+ chr[i ] &= pmask;
+ chr[16 + i] &= pmask;
+ chr[32 + i] &= pmask;
+ chr[48 + i] &= pmask;
++#endif
+ }
+ if (i > 0 && ch != DISP_VERT) {
+ unsigned char pmask = ~(pat[i - 1] >> 1);
+
++#ifdef __MINIOS__
++ for (j = 0; j < 8; j++)
++ if (!(pmask & (1U << j)))
++ chr[i * 8 + (7 - j)] = palette[0];
++#else
+ chr[i ] &= pmask;
+ chr[16 + i] &= pmask;
+ chr[32 + i] &= pmask;
+ chr[48 + i] &= pmask;
++#endif
+ if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
+ pmask = ~pat[i - 1];
+
++#ifdef __MINIOS__
++ for (j = 0; j < 8; j++)
++ if (!(pmask & (1U << j)))
++ chr[i * 8 + (7 - j)] = palette[0];
++#else
+ chr[i ] &= pmask;
+ chr[16 + i] &= pmask;
+ chr[32 + i] &= pmask;
+ chr[48 + i] &= pmask;
++#endif
+ }
+ }
+ }
++#ifdef __MINIOS__
++ for (j = 0; j < 8; j++)
++ if (mask & (1U << j))
++ chr[i * 8 + (7 - j)] = palette[15];
++#else
+ chr[i ] |= mask;
+ chr[16 + i] |= mask;
+ chr[32 + i] |= mask;
+ chr[48 + i] |= mask;
++#endif
+
+ offset += 80;
+ }
+ else {
++#ifdef __MINIOS__
++ for (j = 0; j < 8; j++)
++ if (mask & (1U << j))
++ chr[i * 8 + (7 - j)] = palette[15];
++ else
++ chr[i * 8 + (7 - j)] = palette[0];
++#else
+ chr[i ] = mask;
+ chr[16 + i] = mask;
+ chr[32 + i] = mask;
+ chr[48 + i] = mask;
++#endif
+ }
+ }
+ }
+ else {
++#ifdef __MINIOS__
++ ptr = mem;
++ for (i = 0; i < 16; i++, ptr += 80 * 8)
++ for (j = 0; j < 8; j++) {
++ if (pat[i] & (1U << (7 - j)))
++ cursorBuf32[i * 8 + j] = ptr[j] = palette[0];
++ else
++ cursorBuf32[i * 8 + j] = ptr[j] = palette[15];
++ }
++#else
+ MapMask(15);
+ ptr = mem;
+ for (i = 0; i < 16; i++, ptr += 80) {
+ cursorBuf[i] = pat[i];
+ *ptr = ~pat[i];
+ }
++#endif
+ return;
+ }
+
+ offset = 0;
++#ifdef __MINIOS__
++ ptr = mem;
++ for (j = 0; j < 16; j++, ptr += 80 * 8)
++ memcpy(ptr, chr + j * 8 + offset * 8, 8 * 4);
++#else
+ for (i = 1; i < 16; i <<= 1, offset += 16) {
+ int j;
+
+@@ -580,6 +719,7 @@
+ }
+
+ MapMask(15);
++#endif
+ }
+
+ #endif /* SUPPORT_GRAPHICS */
+Index: grub/stage2/graphics.h
+===================================================================
+--- grub.orig/stage2/graphics.h 2008-06-16 15:18:14.527010000 +0100
++++ grub/stage2/graphics.h 2008-06-16 15:18:14.805010000 +0100
+@@ -21,8 +21,10 @@
+ #ifndef GRAPHICS_H
+ #define GRAPHICS_H
+
++#ifndef __MINIOS__
+ /* magic constant */
+ #define VIDEOMEM 0xA0000
++#endif
+
+ /* function prototypes */
+ char *graphics_get_splash(void);
+Index: grub/stage2/stage2.c
+===================================================================
+--- grub.orig/stage2/stage2.c 2008-06-17 11:06:47.873523000 +0100
++++ grub/stage2/stage2.c 2008-06-17 11:07:05.225628000 +0100
+@@ -31,10 +31,10 @@
+ #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
+
+ # if defined(PRESET_MENU_STRING)
+-static const char *preset_menu = PRESET_MENU_STRING;
++const char *preset_menu = PRESET_MENU_STRING;
+ # elif defined(SUPPORT_DISKLESS)
+ /* Execute the command "bootp" automatically. */
+-static const char *preset_menu = "bootp\n";
++const char *preset_menu = "bootp\n";
+ # endif /* SUPPORT_DISKLESS */
+
+ static int preset_menu_offset;
diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile
new file mode 100644
index 0000000000..4634c0927f
--- /dev/null
+++ b/stubdom/grub/Makefile
@@ -0,0 +1,76 @@
+XEN_ROOT = ../..
+
+include $(XEN_ROOT)/Config.mk
+vpath %.c ../grub-cvs
+
+BOOT=boot-$(XEN_TARGET_ARCH).o
+
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libxc -I.
+DEF_CPPFLAGS += -I../grub-cvs/stage1
+DEF_CPPFLAGS += -I../grub-cvs/stage2
+DEF_CPPFLAGS += -I../grub-cvs/netboot
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/firmware/vgabios
+DEF_CPPFLAGS += -DWITHOUT_LIBC_STUBS
+DEF_CPPFLAGS += -DSUPPORT_NETBOOT
+DEF_CPPFLAGS += -DSUPPORT_GRAPHICS
+DEF_CPPFLAGS += -DSUPPORT_SERIAL
+DEF_CPPFLAGS += -DPRESET_MENU_STRING='""'
+DEF_CPPFLAGS += -DPACKAGE='"grubdom"' -DVERSION='"0.97"'
+
+all: main.a
+
+STAGE2_SOURCES=builtins.c char_io.c cmdline.c common.c console.c disk_io.c graphics.c gunzip.c md5.c serial.c stage2.c terminfo.c tparm.c
+
+NETBOOT_SOURCES=fsys_tftp.c main.c misc.c
+CPPFLAGS += -DFSYS_TFTP=1
+
+STAGE2_SOURCES+=fsys_ext2fs.c
+CPPFLAGS += -DFSYS_EXT2FS=1
+
+STAGE2_SOURCES+=fsys_fat.c
+CPPFLAGS += -DFSYS_FAT=1
+
+STAGE2_SOURCES+=fsys_ffs.c
+CPPFLAGS += -DFSYS_FFS=1
+
+STAGE2_SOURCES+=fsys_iso9660.c
+CPPFLAGS += -DFSYS_ISO9660=1
+
+STAGE2_SOURCES+=fsys_jfs.c
+CPPFLAGS += -DFSYS_JFS=1
+
+STAGE2_SOURCES+=fsys_minix.c
+CPPFLAGS += -DFSYS_MINIX=1
+
+STAGE2_SOURCES+=fsys_reiserfs.c
+CPPFLAGS += -DFSYS_REISERFS=1
+
+STAGE2_SOURCES+=fsys_ufs2.c
+CPPFLAGS += -DFSYS_UFS2=1
+
+STAGE2_SOURCES+=fsys_vstafs.c
+CPPFLAGS += -DFSYS_VSTAFS=1
+
+ifeq (0,1)
+STAGE2_SOURCES+=fsys_xfs.c
+CPPFLAGS += -DFSYS_XFS=1
+endif
+
+STAGE2_SOURCES:=$(addprefix stage2/,$(STAGE2_SOURCES))
+NETBOOT_SOURCES:=$(addprefix netboot/,$(NETBOOT_SOURCES))
+
+$(BOOT): DEF_CPPFLAGS+=-D__ASSEMBLY__
+
+OBJS = $(NETBOOT_SOURCES:.c=.o) $(STAGE2_SOURCES:.c=.o) kexec.o mini-os.o
+
+dirs:
+ mkdir -p netboot stage2
+ touch $@
+
+$(OBJS): dirs
+
+main.a: $(BOOT) $(OBJS)
+ $(AR) cr $@ $^
+
+clean:
+ rm -fr dirs *.a *.o stage2 netboot
diff --git a/stubdom/grub/boot-x86_32.S b/stubdom/grub/boot-x86_32.S
new file mode 100644
index 0000000000..c95fd30dd3
--- /dev/null
+++ b/stubdom/grub/boot-x86_32.S
@@ -0,0 +1,112 @@
+#include <os.h>
+#include <arch_limits.h>
+#include <xen/arch-x86_32.h>
+
+/* For simplicity, we keep all of this into just one data page */
+.data
+.globl _boot_page
+_boot_page:
+ .align __PAGE_SIZE
+
+/*
+ * The following data is initialized from C code
+ */
+
+/* Pte of this page */
+.globl _boot_page_entry
+_boot_page_entry:
+_boot_page_entry_lo:
+ .long 0
+_boot_page_entry_hi:
+ .long 0
+
+/* mmuext_op structure */
+/* Set new page directory */
+_boot_mmuext:
+ /* Op # */
+ .long MMUEXT_NEW_BASEPTR
+
+ /* MFN of target page table directory */
+.globl _boot_pdmfn
+_boot_pdmfn:
+ .long 0
+
+ /* Unused */
+ .long 0
+
+/* Unpin old page directory */
+ /* Op # */
+ .long MMUEXT_UNPIN_TABLE
+
+ /* MFN of old page table directory */
+.globl _boot_oldpdmfn
+_boot_oldpdmfn:
+ .long 0
+
+ /* Unused */
+ .long 0
+
+/* Target stack address, also target virtual address of this page */
+.globl _boot_stack
+_boot_stack:
+ .long 0
+ .long __KERNEL_SS
+.globl _boot_target
+_boot_target:
+ .long 0
+
+/* Target start info */
+.globl _boot_start_info
+_boot_start_info:
+ .long 0
+
+/* Target start address */
+.globl _boot_start
+_boot_start:
+ .long 0
+
+/*
+ * Boot target OS, does not return
+ */
+.globl _boot
+_boot:
+ /* Project ourselves at the target place. */
+ movl _boot_target, %ebx
+ movl %ebx, %ebp /* also keep it in ebp for relative addressing */
+ movl _boot_page_entry_lo, %ecx
+ movl _boot_page_entry_hi, %edx
+ movl $2, %esi /* UVMF_INVLPG */
+ movl $__HYPERVISOR_update_va_mapping, %eax
+ int $0x82
+ testl %eax, %eax
+ jz 0f
+ ud2
+
+0:
+ /* Go there. */
+ movl $(0f - _boot_page), %eax
+ movl _boot_target, %ebx
+ addl %ebx, %eax
+ jmpl *%eax
+0:
+
+ /* Load target page table and unpin old page table. */
+ /* We shouldn't have any problem since in the new page table our page is
+ mapped at the same place. */
+ leal (_boot_mmuext-_boot_page)(%ebp), %ebx
+ movl $2, %ecx
+ xorl %edx, %edx
+ movl $0x7FF0, %esi /* DOMID_SELF */
+ movl $__HYPERVISOR_mmuext_op, %eax
+ int $0x82
+ testl %eax, %eax
+ jns 0f
+ ud2
+
+0:
+ /* Initialize registers. */
+ lss (_boot_stack-_boot_page)(%ebp), %esp
+ movl (_boot_start_info-_boot_page)(%ebp), %esi
+
+ /* Jump! */
+ jmpl *(_boot_start-_boot_page)(%ebp)
diff --git a/stubdom/grub/boot-x86_64.S b/stubdom/grub/boot-x86_64.S
new file mode 100644
index 0000000000..2eae6c3437
--- /dev/null
+++ b/stubdom/grub/boot-x86_64.S
@@ -0,0 +1,108 @@
+#include <os.h>
+#include <arch_limits.h>
+#include <xen/arch-x86_64.h>
+
+/* For simplicity, we keep all of this into just one data page */
+.data
+.globl _boot_page
+_boot_page:
+ .align __PAGE_SIZE
+
+/*
+ * The following data is initialized from C code
+ */
+
+/* Pte of this page */
+.globl _boot_page_entry
+_boot_page_entry:
+ .quad 0
+
+/* mmuext_op structure */
+/* Set new page directory */
+_boot_mmuext:
+ /* Op # */
+ .long MMUEXT_NEW_BASEPTR
+ .long 0 /* pad */
+
+ /* MFN of target page table directory */
+.globl _boot_pdmfn
+_boot_pdmfn:
+ .quad 0
+
+ /* Unused */
+ .quad 0
+
+/* Unpin old page directory */
+ /* Op # */
+ .long MMUEXT_UNPIN_TABLE
+ .long 0 /* pad */
+
+ /* MFN of old page table directory */
+.globl _boot_oldpdmfn
+_boot_oldpdmfn:
+ .quad 0
+
+ /* Unused */
+ .quad 0
+
+/* Target stack address, also target virtual address of this page */
+.globl _boot_stack
+_boot_stack:
+ .quad 0
+.globl _boot_target
+_boot_target:
+ .quad 0
+
+/* Target start info */
+.globl _boot_start_info
+_boot_start_info:
+ .quad 0
+
+/* Target start address */
+.globl _boot_start
+_boot_start:
+ .quad 0
+
+/*
+ * Boot target OS, does not return
+ */
+.globl _boot
+_boot:
+ /* Project ourselves at the target place. */
+ movq _boot_target, %rdi
+ movq _boot_page_entry, %rsi
+ movq $2, %rdx /* UVMF_INVLPG */
+ movq $__HYPERVISOR_update_va_mapping, %rax
+ syscall
+ testq %rax, %rax
+ jz 0f
+ ud2
+
+0:
+ /* Go there. */
+ movq $(0f - _boot_page), %rax
+ movq _boot_target, %rbx
+ addq %rbx, %rax
+ jmpq *%rax
+0:
+
+ /* Load target page table and unpin old page table. */
+ /* We shouldn't have any problem since in the new page table our page is
+ mapped at the same place. */
+ leaq _boot_mmuext(%rip), %rdi
+ movq $2, %rsi
+ xorq %rdx, %rdx
+ movq $0x7FF0, %r10 /* DOMID_SELF */
+ movq $__HYPERVISOR_mmuext_op, %rax
+ syscall
+ testq %rax, %rax
+ jns 0f
+ ud2
+
+0:
+ /* Initialize registers. */
+ movq _boot_stack(%rip), %rsp
+ movq _boot_start_info(%rip), %rsi
+
+ /* Jump! */
+ jmpq *_boot_start(%rip)
diff --git a/stubdom/grub/config.h b/stubdom/grub/config.h
new file mode 100644
index 0000000000..dcb2e7a15c
--- /dev/null
+++ b/stubdom/grub/config.h
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#undef putchar
+#include <ctype.h>
+#include <string.h>
+#define debug _debug
+#define grub_halt(a) do_exit()
+#define printf grub_printf
+void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline);
+struct fbfront_dev *fb_open(void *fb, int width, int height, int depth);
+void fb_close(void);
+void pv_boot (void);
diff --git a/stubdom/grub/kexec.c b/stubdom/grub/kexec.c
new file mode 100644
index 0000000000..5400fe88cd
--- /dev/null
+++ b/stubdom/grub/kexec.c
@@ -0,0 +1,324 @@
+/*
+ * This supports booting another PV kernel from Mini-OS
+ *
+ * The idea is to setup it using libxc, answer to day0 memory allocation
+ * requests, and using a trampoline boot page to switch to the new page table.
+ *
+ * The procedure of the boot page is:
+ * - map itself at the target position (that may overwrite some C stuff, but we
+ * do not care any more)
+ * - jump there
+ * - switch to the target page table
+ * - unpin the old page table
+ * - jump to the new kernel
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.com>, May 2008
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include <xenctrl.h>
+#include <xc_dom.h>
+
+#include <kernel.h>
+#include <console.h>
+#include <os.h>
+#include <blkfront.h>
+#include <netfront.h>
+#include <fbfront.h>
+#include <shared.h>
+
+#include "mini-os.h"
+
+#if 0
+#define DEBUG(fmt, ...) printk(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG(fmt, ...) (void)0
+#endif
+
+/* Assembly boot page from boot.S */
+extern void _boot_page;
+extern pgentry_t _boot_page_entry;
+extern unsigned long _boot_pdmfn;
+extern unsigned long _boot_stack, _boot_target, _boot_start_info, _boot_start;
+extern xen_pfn_t _boot_oldpdmfn;
+extern void _boot(void);
+
+static unsigned long *pages;
+static unsigned long *pages_mfns;
+static unsigned long allocated;
+
+int pin_table(int xc_handle, unsigned int type, unsigned long mfn,
+ domid_t dom);
+
+/* We need mfn to appear as target_pfn, so exchange with the MFN there */
+static void do_exchange(struct xc_dom_image *dom, xen_pfn_t target_pfn, xen_pfn_t source_mfn)
+{
+ xen_pfn_t source_pfn;
+ xen_pfn_t target_mfn;
+
+ for (source_pfn = 0; source_pfn < start_info.nr_pages; source_pfn++)
+ if (dom->p2m_host[source_pfn] == source_mfn)
+ break;
+ ASSERT(source_pfn < start_info.nr_pages);
+
+ target_mfn = dom->p2m_host[target_pfn];
+
+ /* Put target MFN at source PFN */
+ dom->p2m_host[source_pfn] = target_mfn;
+
+ /* Put source MFN at target PFN */
+ dom->p2m_host[target_pfn] = source_mfn;
+}
+
+int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to)
+{
+ unsigned long new_allocated = (up_to - dom->parms.virt_base) / PAGE_SIZE;
+ unsigned long i;
+
+ pages = realloc(pages, new_allocated * sizeof(*pages));
+ pages_mfns = realloc(pages_mfns, new_allocated * sizeof(*pages_mfns));
+ for (i = allocated; i < new_allocated; i++) {
+ /* Exchange old page of PFN i with a newly allocated page. */
+ xen_pfn_t old_mfn = dom->p2m_host[i];
+ xen_pfn_t new_pfn;
+ xen_pfn_t new_mfn;
+
+ pages[i] = alloc_page();
+ memset((void*) pages[i], 0, PAGE_SIZE);
+ new_pfn = PHYS_PFN(to_phys(pages[i]));
+ pages_mfns[i] = new_mfn = pfn_to_mfn(new_pfn);
+
+ /* Put old page at new PFN */
+ dom->p2m_host[new_pfn] = old_mfn;
+
+ /* Put new page at PFN i */
+ dom->p2m_host[i] = new_mfn;
+ }
+
+ allocated = new_allocated;
+
+ return 0;
+}
+
+void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline)
+{
+ struct xc_dom_image *dom;
+ int rc;
+ domid_t domid = DOMID_SELF;
+ xen_pfn_t pfn;
+ int xc_handle;
+ unsigned long i;
+ void *seg;
+ xen_pfn_t boot_page_mfn = virt_to_mfn(&_boot_page);
+ char features[] = "";
+ struct mmu_update *m2p_updates;
+ unsigned long nr_m2p_updates;
+
+ DEBUG("booting with cmdline %s\n", cmdline);
+ xc_handle = xc_interface_open();
+
+ dom = xc_dom_allocate(cmdline, features);
+ dom->allocate = kexec_allocate;
+
+ dom->kernel_blob = kernel;
+ dom->kernel_size = kernel_size;
+
+ dom->ramdisk_blob = module;
+ dom->ramdisk_size = module_size;
+
+ dom->flags = 0;
+ dom->console_evtchn = start_info.console.domU.evtchn;
+ dom->xenstore_evtchn = start_info.store_evtchn;
+
+ if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) {
+ grub_printf("xc_dom_boot_xen_init returned %d\n", rc);
+ errnum = ERR_BOOT_FAILURE;
+ goto out;
+ }
+ if ( (rc = xc_dom_parse_image(dom)) != 0 ) {
+ grub_printf("xc_dom_parse_image returned %d\n", rc);
+ errnum = ERR_BOOT_FAILURE;
+ goto out;
+ }
+
+#ifdef __i386__
+ if (strcmp(dom->guest_type, "xen-3.0-x86_32p")) {
+ grub_printf("can only boot x86 32 PAE kernels, not %s\n", dom->guest_type);
+ errnum = ERR_EXEC_FORMAT;
+ goto out;
+ }
+#endif
+#ifdef __x86_64__
+ if (strcmp(dom->guest_type, "xen-3.0-x86_64")) {
+ grub_printf("can only boot x86 64 kernels, not %s\n", dom->guest_type);
+ errnum = ERR_EXEC_FORMAT;
+ goto out;
+ }
+#endif
+
+ /* equivalent of xc_dom_mem_init */
+ dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type);
+ dom->total_pages = start_info.nr_pages;
+
+ /* equivalent of arch_setup_meminit */
+
+ /* setup initial p2m */
+ dom->p2m_host = malloc(sizeof(*dom->p2m_host) * dom->total_pages);
+
+ /* Start with our current P2M */
+ for (i = 0; i < dom->total_pages; i++)
+ dom->p2m_host[i] = pfn_to_mfn(i);
+
+ if ( (rc = xc_dom_build_image(dom)) != 0 ) {
+ grub_printf("xc_dom_build_image returned %d\n", rc);
+ errnum = ERR_BOOT_FAILURE;
+ goto out;
+ }
+
+ /* copy hypercall page */
+ /* TODO: domctl instead, but requires privileges */
+ if (dom->parms.virt_hypercall != -1) {
+ pfn = PHYS_PFN(dom->parms.virt_hypercall - dom->parms.virt_base);
+ memcpy((void *) pages[pfn], hypercall_page, PAGE_SIZE);
+ }
+
+ /* Equivalent of xc_dom_boot_image */
+ dom->shared_info_mfn = PHYS_PFN(start_info.shared_info);
+
+ if (!xc_dom_compat_check(dom)) {
+ grub_printf("xc_dom_compat_check failed\n");
+ errnum = ERR_EXEC_FORMAT;
+ goto out;
+ }
+
+ /* Move current console, xenstore and boot MFNs to the allocated place */
+ do_exchange(dom, dom->console_pfn, start_info.console.domU.mfn);
+ do_exchange(dom, dom->xenstore_pfn, start_info.store_mfn);
+ DEBUG("virt base at %llx\n", dom->parms.virt_base);
+ DEBUG("bootstack_pfn %lx\n", dom->bootstack_pfn);
+ _boot_target = dom->parms.virt_base + PFN_PHYS(dom->bootstack_pfn);
+ DEBUG("_boot_target %lx\n", _boot_target);
+ do_exchange(dom, PHYS_PFN(_boot_target - dom->parms.virt_base),
+ virt_to_mfn(&_boot_page));
+
+ /* Make sure the bootstrap page table does not RW-map any of our current
+ * page table frames */
+ kexec_allocate(dom, dom->virt_pgtab_end);
+
+ if ( (rc = xc_dom_update_guest_p2m(dom))) {
+ grub_printf("xc_dom_update_guest_p2m returned %d\n", rc);
+ errnum = ERR_BOOT_FAILURE;
+ goto out;
+ }
+
+ if ( dom->arch_hooks->setup_pgtables )
+ if ( (rc = dom->arch_hooks->setup_pgtables(dom))) {
+ grub_printf("setup_pgtables returned %d\n", rc);
+ errnum = ERR_BOOT_FAILURE;
+ goto out;
+ }
+
+ /* start info page */
+#undef start_info
+ if ( dom->arch_hooks->start_info )
+ dom->arch_hooks->start_info(dom);
+#define start_info (start_info_union.start_info)
+
+ xc_dom_log_memory_footprint(dom);
+
+ /* Unmap libxc's projection of the boot page table */
+ seg = xc_dom_seg_to_ptr(dom, &dom->pgtables_seg);
+ munmap(seg, dom->pgtables_seg.vend - dom->pgtables_seg.vstart);
+
+ /* Unmap day0 pages to avoid having a r/w mapping of the future page table */
+ for (pfn = 0; pfn < allocated; pfn++)
+ munmap((void*) pages[pfn], PAGE_SIZE);
+
+ /* Pin the boot page table base */
+ if ( (rc = pin_table(dom->guest_xc,
+#ifdef __i386__
+ MMUEXT_PIN_L3_TABLE,
+#endif
+#ifdef __x86_64__
+ MMUEXT_PIN_L4_TABLE,
+#endif
+ xc_dom_p2m_host(dom, dom->pgtables_seg.pfn),
+ dom->guest_domid)) != 0 ) {
+ grub_printf("pin_table(%lx) returned %d\n", xc_dom_p2m_host(dom,
+ dom->pgtables_seg.pfn), rc);
+ errnum = ERR_BOOT_FAILURE;
+ goto out_remap;
+ }
+
+ /* We populate the Mini-OS page table here so that boot.S can just call
+ * update_va_mapping to project itself there. */
+ need_pgt(_boot_target);
+ DEBUG("day0 pages %lx\n", allocated);
+ DEBUG("boot target page %lx\n", _boot_target);
+ DEBUG("boot page %p\n", &_boot_page);
+ DEBUG("boot page mfn %lx\n", boot_page_mfn);
+ _boot_page_entry = PFN_PHYS(boot_page_mfn) | L1_PROT;
+ DEBUG("boot page entry %llx\n", _boot_page_entry);
+ _boot_oldpdmfn = virt_to_mfn(start_info.pt_base);
+ DEBUG("boot old pd mfn %lx\n", _boot_oldpdmfn);
+ DEBUG("boot pd virt %lx\n", dom->pgtables_seg.vstart);
+ _boot_pdmfn = dom->p2m_host[PHYS_PFN(dom->pgtables_seg.vstart - dom->parms.virt_base)];
+ DEBUG("boot pd mfn %lx\n", _boot_pdmfn);
+ _boot_stack = _boot_target + PAGE_SIZE;
+ DEBUG("boot stack %lx\n", _boot_stack);
+ _boot_start_info = dom->parms.virt_base + PFN_PHYS(dom->start_info_pfn);
+ DEBUG("boot start info %lx\n", _boot_start_info);
+ _boot_start = dom->parms.virt_entry;
+ DEBUG("boot start %lx\n", _boot_start);
+
+ /* Keep only useful entries */
+ for (nr_m2p_updates = pfn = 0; pfn < start_info.nr_pages; pfn++)
+ if (dom->p2m_host[pfn] != pfn_to_mfn(pfn))
+ nr_m2p_updates++;
+
+ m2p_updates = malloc(sizeof(*m2p_updates) * nr_m2p_updates);
+ for (i = pfn = 0; pfn < start_info.nr_pages; pfn++)
+ if (dom->p2m_host[pfn] != pfn_to_mfn(pfn)) {
+ m2p_updates[i].ptr = PFN_PHYS(dom->p2m_host[pfn]) | MMU_MACHPHYS_UPDATE;
+ m2p_updates[i].val = pfn;
+ i++;
+ }
+
+ for (i = 0; i < blk_nb; i++)
+ shutdown_blkfront(blk_dev[i]);
+ if (net_dev)
+ shutdown_netfront(net_dev);
+ if (kbd_dev)
+ shutdown_kbdfront(kbd_dev);
+ stop_kernel();
+
+ /* Update M2P */
+ if ((rc = HYPERVISOR_mmu_update(m2p_updates, nr_m2p_updates, NULL, DOMID_SELF)) < 0) {
+ xprintk("Could not update M2P\n");
+ ASSERT(0);
+ }
+
+ xprintk("go!\n");
+
+ /* Jump to trampoline boot page */
+ _boot();
+
+ ASSERT(0);
+
+out_remap:
+ for (pfn = 0; pfn < allocated; pfn++)
+ do_map_frames(pages[pfn], &pages_mfns[pfn], 1, 0, 0, DOMID_SELF, 0, L1_PROT);
+out:
+ xc_dom_release(dom);
+ for (pfn = 0; pfn < allocated; pfn++)
+ free_page((void*)pages[pfn]);
+ free(pages);
+ free(pages_mfns);
+ pages = NULL;
+ pages_mfns = NULL;
+ allocated = 0;
+ xc_interface_close(xc_handle );
+}
diff --git a/stubdom/grub/mini-os.c b/stubdom/grub/mini-os.c
new file mode 100644
index 0000000000..49e1f21f86
--- /dev/null
+++ b/stubdom/grub/mini-os.c
@@ -0,0 +1,702 @@
+/*
+ * Mini-OS support for GRUB.
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.com>, May 2008
+ */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <unistd.h>
+
+#include <hypervisor.h>
+#include <blkfront.h>
+#include <netfront.h>
+#include <fbfront.h>
+#include <semaphore.h>
+
+#include <osdep.h>
+#include <shared.h>
+#include <nic.h>
+#include <etherboot.h>
+#include <terminfo.h>
+#include <term.h>
+
+#include "mini-os.h"
+
+extern const char *preset_menu;
+char config_file[DEFAULT_FILE_BUFLEN] = "(hd0,0)/boot/grub/menu.lst";
+unsigned long boot_drive = NETWORK_DRIVE;
+unsigned long install_partition = 0xFFFFFF;
+
+char version_string[] = VERSION;
+
+/* Variables from asm.S */
+int saved_entryno;
+
+/*
+ * Disk
+ */
+
+struct blkfront_dev **blk_dev;
+int blk_nb;
+static struct blkfront_info *blk_info;
+
+static int vbdcmp(const void *_vbd1, const void *_vbd2) {
+ char *vbd1 = *(char **)_vbd1;
+ char *vbd2 = *(char **)_vbd2;
+ int vbdn1 = atoi(vbd1);
+ int vbdn2 = atoi(vbd2);
+ return vbdn1 - vbdn2;
+}
+
+void init_disk (void)
+{
+ char **list;
+ char *msg;
+ int i;
+ char *path;
+
+ msg = xenbus_ls(XBT_NIL, "device/vbd", &list);
+ if (msg) {
+ printk("Error %s while reading list of disks\n", msg);
+ free(msg);
+ return;
+ }
+ blk_nb = 0;
+ while (list[blk_nb])
+ blk_nb++;
+ blk_dev = malloc(blk_nb * sizeof(*blk_dev));
+ blk_info = malloc(blk_nb * sizeof(*blk_info));
+
+ qsort(list, blk_nb, sizeof(*list), vbdcmp);
+
+ for (i = 0; i < blk_nb; i++) {
+ printk("vbd %s is hd%d\n", list[i], i);
+ asprintf(&path, "device/vbd/%s", list[i]);
+ blk_dev[i] = init_blkfront(path, &blk_info[i]);
+ free(path);
+ free(list[i]);
+ }
+}
+
+/* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return
+ non-zero, otherwise zero. */
+int get_diskinfo (int drive, struct geometry *geometry)
+{
+ int i;
+ if (!(drive & 0x80))
+ return -1;
+
+ i = drive - 0x80;
+ if (i >= blk_nb)
+ return -1;
+
+ /* Bogus geometry */
+ geometry->cylinders = 65535;
+ geometry->heads = 255;
+ geometry->sectors = 63;
+
+ geometry->total_sectors = blk_info[i].sectors;
+ geometry->sector_size = blk_info[i].sector_size;
+ geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION;
+ if (blk_info[i].info & VDISK_CDROM)
+ geometry->flags |= BIOSDISK_FLAG_CDROM;
+ return 0;
+}
+
+/* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY
+ from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it,
+ else if READ is BIOSDISK_WRITE, then write it. If an geometry error
+ occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then
+ return the error number. Otherwise, return 0. */
+int
+biosdisk (int read, int drive, struct geometry *geometry,
+ unsigned int sector, int nsec, int segment)
+{
+ void *addr = (void *) ((unsigned long)segment << 4);
+ struct blkfront_aiocb aiocb;
+ int i;
+
+ if (!(drive & 0x80))
+ return -1;
+
+ i = drive - 0x80;
+ if (i >= blk_nb)
+ return -1;
+
+ aiocb.aio_dev = blk_dev[i];
+ aiocb.aio_buf = addr;
+ aiocb.aio_nbytes = (size_t)nsec * blk_info[i].sector_size;
+ aiocb.aio_offset = (off_t)sector * blk_info[i].sector_size;
+ aiocb.aio_cb = NULL;
+
+ blkfront_io(&aiocb, read == BIOSDISK_WRITE);
+
+ return 0;
+}
+
+static int
+load_file(char *name, void **ptr, long *size)
+{
+ char *buf = NULL;
+ int allocated = 1 * 1024 * 1024;
+ int len, filled = 0;
+
+ if (!grub_open (name))
+ return -1;
+
+ buf = malloc(allocated);
+
+ errnum = 0;
+ while (1) {
+ len = grub_read (buf + filled, allocated - filled);
+ if (! len) {
+ if (!errnum)
+ break;
+ grub_close ();
+ return -1;
+ }
+ filled += len;
+ if (filled < allocated)
+ break;
+ allocated *= 2;
+ buf = realloc(buf, allocated);
+ }
+ grub_close ();
+ *ptr = buf;
+ *size = filled;
+ return 0;
+}
+
+void *kernel_image, *module_image;
+long kernel_size, module_size;
+char *kernel_arg, *module_arg;
+
+kernel_t
+load_image (char *kernel, char *arg, kernel_t suggested_type,
+ unsigned long load_flags)
+{
+ arg = skip_to(0, arg);
+ if (kernel_image)
+ free(kernel_image);
+ kernel_image = NULL;
+ if (load_file (kernel, &kernel_image, &kernel_size))
+ return KERNEL_TYPE_NONE;
+ if (kernel_arg)
+ free(kernel_arg);
+ kernel_arg = strdup(arg);
+ return KERNEL_TYPE_PV;
+}
+
+int
+load_initrd (char *initrd)
+{
+ if (module_image)
+ free(module_image);
+ module_image = NULL;
+ load_file (initrd, &module_image, &module_size);
+ return ! errnum;
+}
+
+int
+load_module (char *module, char *arg)
+{
+ if (module_image)
+ free(module_image);
+ module_image = NULL;
+ load_file (module, &module_image, &module_size);
+ if (module_arg)
+ free(module_arg);
+ module_arg = strdup(arg);
+ return ! errnum;
+}
+
+void
+pv_boot (void)
+{
+ kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg);
+}
+
+/*
+ * Network
+ */
+
+struct netfront_dev *net_dev;
+
+int
+minios_probe (struct nic *nic)
+{
+ char *ip;
+
+ if (net_dev)
+ return 1;
+
+ /* Clear the ARP table. */
+ grub_memset ((char *) arptable, 0,
+ MAX_ARP * sizeof (struct arptable_t));
+
+ net_dev = init_netfront(NULL, (void*) -1, nic->node_addr, &ip);
+ if (!net_dev)
+ return 0;
+
+ return 1;
+}
+
+/* reset adapter */
+static void minios_reset(struct nic *nic)
+{
+ /* TODO? */
+}
+
+static void minios_disable(struct nic *nic)
+{
+}
+
+/* Wait for a frame */
+static int minios_poll(struct nic *nic)
+{
+ return !! (nic->packetlen = netfront_receive(net_dev, (void*) nic->packet, ETH_FRAME_LEN));
+}
+
+/* Transmit a frame */
+struct frame {
+ uint8_t dest[ETH_ALEN];
+ uint8_t src[ETH_ALEN];
+ uint16_t type;
+ unsigned char data[];
+};
+static void minios_transmit (struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p)
+{
+ struct frame *frame = alloca(sizeof(frame) + s);
+
+ memcpy(frame->dest, d, ETH_ALEN);
+ memcpy(frame->src, nic->node_addr, ETH_ALEN);
+ frame->type = htons(t);
+ memcpy(frame->data, p, s);
+
+ netfront_xmit(net_dev, (void*) frame, sizeof(*frame) + s);
+}
+
+static char packet[ETH_FRAME_LEN];
+
+struct nic nic = {
+ .reset = minios_reset,
+ .poll = minios_poll,
+ .transmit = minios_transmit,
+ .disable = minios_disable,
+ .flags = 0,
+ .rom_info = NULL,
+ .node_addr = arptable[ARP_CLIENT].node,
+ .packet = packet,
+ .packetlen = 0,
+ .priv_data = NULL,
+};
+
+int
+eth_probe (void)
+{
+ return minios_probe(&nic);
+}
+
+int
+eth_poll (void)
+{
+ return minios_poll (&nic);
+}
+
+void
+eth_disable (void)
+{
+ minios_disable (&nic);
+}
+
+void
+eth_transmit (const char *d, unsigned int t,
+ unsigned int s, const void *p)
+{
+ minios_transmit (&nic, d, t, s, p);
+ if (t == IP)
+ twiddle();
+}
+
+/*
+ * Console
+ */
+void
+serial_hw_put (int _c)
+{
+ char c = _c;
+ console_print(&c, 1);
+}
+
+int
+serial_hw_fetch (void)
+{
+ char key;
+
+ if (!xencons_ring_avail())
+ return -1;
+
+ read(STDIN_FILENO, &key, 1);
+ switch (key) {
+ case 0x7f: key = '\b'; break;
+ }
+ return key;
+}
+
+/*
+ * PVFB
+ */
+struct kbdfront_dev *kbd_dev;
+struct fbfront_dev *fb_dev;
+static union xenkbd_in_event ev;
+static int has_ev;
+int console_checkkey (void)
+{
+ if (has_ev)
+ return 1;
+ has_ev = kbdfront_receive(kbd_dev, &ev, 1);
+ return has_ev;
+}
+
+/* static QWERTY layout, that's what most PC BIOSes do anyway */
+static char linux2ascii[] = {
+ [ 1 ] = 27,
+ [ 2 ] = '1',
+ [ 3 ] = '2',
+ [ 4 ] = '3',
+ [ 5 ] = '4',
+ [ 6 ] = '5',
+ [ 7 ] = '6',
+ [ 8 ] = '7',
+ [ 9 ] = '8',
+ [ 10 ] = '9',
+ [ 11 ] = '0',
+ [ 12 ] = '-',
+ [ 13 ] = '=',
+ [ 14 ] = '\b',
+ [ 15 ] = '\t',
+ [ 16 ] = 'q',
+ [ 17 ] = 'w',
+ [ 18 ] = 'e',
+ [ 19 ] = 'r',
+ [ 20 ] = 't',
+ [ 21 ] = 'y',
+ [ 22 ] = 'u',
+ [ 23 ] = 'i',
+ [ 24 ] = 'o',
+ [ 25 ] = 'p',
+ [ 26 ] = '[',
+ [ 27 ] = ']',
+ [ 28 ] = '\n',
+
+ [ 30 ] = 'a',
+ [ 31 ] = 's',
+ [ 32 ] = 'd',
+ [ 33 ] = 'f',
+ [ 34 ] = 'g',
+ [ 35 ] = 'h',
+ [ 36 ] = 'j',
+ [ 37 ] = 'k',
+ [ 38 ] = 'l',
+ [ 39 ] = ';',
+ [ 40 ] = '\'',
+ [ 41 ] = '`',
+
+ [ 43 ] = '\\',
+ [ 44 ] = 'z',
+ [ 45 ] = 'x',
+ [ 46 ] = 'c',
+ [ 47 ] = 'v',
+ [ 48 ] = 'b',
+ [ 49 ] = 'n',
+ [ 50 ] = 'm',
+ [ 51 ] = ',',
+ [ 52 ] = '.',
+ [ 53 ] = '/',
+
+ [ 55 ] = '*',
+ [ 57 ] = ' ',
+
+ [ 71 ] = '7',
+ [ 72 ] = '8',
+ [ 73 ] = '9',
+ [ 74 ] = '-',
+ [ 75 ] = '4',
+ [ 76 ] = '5',
+ [ 77 ] = '6',
+ [ 78 ] = '+',
+ [ 79 ] = '1',
+ [ 80 ] = '2',
+ [ 81 ] = '3',
+ [ 82 ] = '0',
+ [ 83 ] = '.',
+
+ [ 86 ] = '<',
+
+ [ 96 ] = '\n',
+
+ [ 98 ] = '/',
+
+ [ 102 ] = 1, /* home */
+ [ 103 ] = 16, /* up */
+ [ 104 ] = 7, /* page up */
+ [ 105 ] = 2, /* left */
+ [ 106 ] = 6, /* right */
+ [ 107 ] = 5, /* end */
+ [ 108 ] = 14, /* down */
+ [ 109 ] = 3, /* page down */
+
+ [ 111 ] = 4, /* delete */
+};
+
+static char linux2ascii_shifted[] = {
+ [ 1 ] = 27,
+ [ 2 ] = '!',
+ [ 3 ] = '@',
+ [ 4 ] = '#',
+ [ 5 ] = '$',
+ [ 6 ] = '%',
+ [ 7 ] = '^',
+ [ 8 ] = '&',
+ [ 9 ] = '*',
+ [ 10 ] = '(',
+ [ 11 ] = ')',
+ [ 12 ] = '_',
+ [ 13 ] = '+',
+ [ 14 ] = '\b',
+ [ 15 ] = '\t',
+ [ 16 ] = 'Q',
+ [ 17 ] = 'W',
+ [ 18 ] = 'E',
+ [ 19 ] = 'R',
+ [ 20 ] = 'T',
+ [ 21 ] = 'Y',
+ [ 22 ] = 'U',
+ [ 23 ] = 'I',
+ [ 24 ] = 'O',
+ [ 25 ] = 'P',
+ [ 26 ] = '{',
+ [ 27 ] = '}',
+ [ 28 ] = '\n',
+
+ [ 30 ] = 'A',
+ [ 31 ] = 'S',
+ [ 32 ] = 'D',
+ [ 33 ] = 'F',
+ [ 34 ] = 'G',
+ [ 35 ] = 'H',
+ [ 36 ] = 'J',
+ [ 37 ] = 'K',
+ [ 38 ] = 'L',
+ [ 39 ] = ':',
+ [ 40 ] = '"',
+ [ 41 ] = '~',
+
+ [ 43 ] = '|',
+ [ 44 ] = 'Z',
+ [ 45 ] = 'X',
+ [ 46 ] = 'C',
+ [ 47 ] = 'V',
+ [ 48 ] = 'B',
+ [ 49 ] = 'N',
+ [ 50 ] = 'M',
+ [ 51 ] = '<',
+ [ 52 ] = '>',
+ [ 53 ] = '?',
+
+ [ 55 ] = '*',
+ [ 57 ] = ' ',
+
+ [ 71 ] = '7',
+ [ 72 ] = '8',
+ [ 73 ] = '9',
+ [ 74 ] = '-',
+ [ 75 ] = '4',
+ [ 76 ] = '5',
+ [ 77 ] = '6',
+ [ 78 ] = '+',
+ [ 79 ] = '1',
+ [ 80 ] = '2',
+ [ 81 ] = '3',
+ [ 82 ] = '0',
+ [ 83 ] = '.',
+
+ [ 86 ] = '>',
+
+ [ 96 ] = '\n',
+
+ [ 98 ] = '/',
+
+ [ 102 ] = 1, /* home */
+ [ 103 ] = 16, /* up */
+ [ 104 ] = 7, /* page up */
+ [ 105 ] = 2, /* left */
+ [ 106 ] = 6, /* right */
+ [ 107 ] = 5, /* end */
+ [ 108 ] = 14, /* down */
+ [ 109 ] = 3, /* page down */
+
+ [ 111 ] = 4, /* delete */
+};
+
+int console_getkey (void)
+{
+ static int shift, control, alt, caps_lock;
+
+ if (!has_ev)
+ has_ev = kbdfront_receive(kbd_dev, &ev, 1);
+ if (!has_ev)
+ return 0;
+
+ has_ev = 0;
+ if (ev.type != XENKBD_TYPE_KEY)
+ return 0;
+
+ if (ev.key.keycode == 42 || ev.key.keycode == 54) {
+ caps_lock = 0;
+ shift = ev.key.pressed;
+ return 0;
+ }
+ if (ev.key.keycode == 58) {
+ caps_lock ^= 1;
+ return 0;
+ }
+ if (ev.key.keycode == 29 || ev.key.keycode == 97) {
+ control = ev.key.pressed;
+ return 0;
+ }
+ if (ev.key.keycode == 56) {
+ alt = ev.key.pressed;
+ return 0;
+ }
+
+ if (!ev.key.pressed)
+ return 0;
+
+ if (ev.key.keycode < sizeof(linux2ascii) / sizeof(*linux2ascii)) {
+ char val;
+ if (shift || caps_lock)
+ val = linux2ascii_shifted[ev.key.keycode];
+ else
+ val = linux2ascii[ev.key.keycode];
+ if (control)
+ val &= ~0x60;
+ return val;
+ }
+
+ return 0;
+}
+
+static void kbd_thread(void *p)
+{
+ struct semaphore *sem = p;
+
+ kbd_dev = init_kbdfront(NULL, 1);
+ up(sem);
+}
+
+struct fbfront_dev *fb_open(void *fb, int width, int height, int depth)
+{
+ unsigned long *mfns;
+ int linesize = width * (depth / 8);
+ int memsize = linesize * height;
+ int numpages = (memsize + PAGE_SIZE - 1) / PAGE_SIZE;
+ DECLARE_MUTEX_LOCKED(sem);
+ int i;
+
+ create_thread("kbdfront", kbd_thread, &sem);
+
+ mfns = malloc(numpages * sizeof(*mfns));
+ for (i = 0; i < numpages; i++) {
+ memset(fb + i * PAGE_SIZE, 0, PAGE_SIZE);
+ mfns[i] = virtual_to_mfn(fb + i * PAGE_SIZE);
+ }
+ fb_dev = init_fbfront(NULL, mfns, width, height, depth, linesize, numpages);
+ free(mfns);
+
+ if (!fb_dev)
+ return NULL;
+
+ down(&sem);
+ if (!kbd_dev)
+ return NULL;
+
+ return fb_dev;
+}
+
+void kbd_close(void *foo)
+{
+ shutdown_kbdfront(kbd_dev);
+ kbd_dev = NULL;
+}
+
+void fb_close(void)
+{
+ create_thread("kbdfront close", kbd_close, NULL);
+ shutdown_fbfront(fb_dev);
+ fb_dev = NULL;
+}
+
+/*
+ * Misc
+ */
+
+int getrtsecs (void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec;
+}
+
+int currticks (void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return ((tv.tv_sec * 1000000ULL + tv.tv_usec) * TICKS_PER_SEC) / 1000000;
+}
+
+void __attribute__ ((noreturn)) grub_reboot (void)
+{
+ for ( ;; )
+ {
+ struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_reboot };
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+ }
+}
+
+#define SCRATCH_MEMSIZE (4 * 1024 * 1024)
+
+/* Note: not allocating it dynamically permits to make sure it lays below 4G
+ * for grub's 32bit pointers to work */
+char grub_scratch_mem[SCRATCH_MEMSIZE] __attribute__((aligned(PAGE_SIZE)));
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1) {
+ strncpy(config_file, argv[1], sizeof(config_file) - 1);
+ config_file[sizeof(config_file) - 1] = 0;
+ if (!strncmp(config_file, "(nd)", 4))
+ preset_menu = "dhcp";
+ } else
+ preset_menu = "dhcp --with-configfile";
+
+ mbi.drives_addr = BOOTSEC_LOCATION + (60 * 1024);
+ mbi.drives_length = 0;
+
+ mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION;
+ mbi.mem_lower = (start_info.nr_pages * PAGE_SIZE) / 1024;
+ mbi.mem_upper = 0;
+ saved_drive = boot_drive;
+ saved_partition = install_partition;
+
+ init_disk();
+
+ /* Try to make sure the client part got launched */
+ sleep(1);
+ cmain();
+ printk("cmain returned!\n");
+}
diff --git a/stubdom/grub/mini-os.h b/stubdom/grub/mini-os.h
new file mode 100644
index 0000000000..6c6844122e
--- /dev/null
+++ b/stubdom/grub/mini-os.h
@@ -0,0 +1,5 @@
+extern int blk_nb;
+extern struct blkfront_dev **blk_dev;
+extern struct netfront_dev *net_dev;
+extern struct kbdfront_dev *kbd_dev;
+extern struct fbfront_dev *fb_dev;
diff --git a/stubdom/grub/osdep.h b/stubdom/grub/osdep.h
new file mode 100644
index 0000000000..1d3e50adbf
--- /dev/null
+++ b/stubdom/grub/osdep.h
@@ -0,0 +1,30 @@
+#ifndef __OSDEP_H__
+#define __OSDEP_H__
+
+#include <byteswap.h>
+#define swap32(x) bswap_32(x)
+#define swap16(x) bswap_16(x)
+
+#include <machine/endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+#define htons(x) (x)
+#define ntohs(x) (x)
+#define htonl(x) (x)
+#define ntohl(x) (x)
+#else
+#define htons(x) swap16(x)
+#define ntohs(x) swap16(x)
+#define htonl(x) swap32(x)
+#define ntohl(x) swap32(x)
+#endif
+
+typedef unsigned long Address;
+
+/* ANSI prototyping macro */
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#endif
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
index 30111c98e2..770e00bba2 100644
--- a/tools/libxc/xc_dom.h
+++ b/tools/libxc/xc_dom.h
@@ -107,6 +107,8 @@ struct xc_dom_image {
/* kernel loader */
struct xc_dom_arch *arch_hooks;
+ /* allocate up to virt_alloc_end */
+ int (*allocate) (struct xc_dom_image * dom, xen_vaddr_t up_to);
};
/* --- pluggable kernel loader ------------------------------------- */
@@ -167,6 +169,7 @@ int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
size_t memsize);
int xc_dom_parse_image(struct xc_dom_image *dom);
+struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type);
int xc_dom_build_image(struct xc_dom_image *dom);
int xc_dom_update_guest_p2m(struct xc_dom_image *dom);
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
index 9a158ef5e2..2b6f6b6868 100644
--- a/tools/libxc/xc_dom_core.c
+++ b/tools/libxc/xc_dom_core.c
@@ -409,6 +409,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
seg->vend = start + pages * page_size;
seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
dom->virt_alloc_end = seg->vend;
+ if (dom->allocate)
+ dom->allocate(dom, dom->virt_alloc_end);
xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " -> 0x%" PRIx64
" (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n",
@@ -431,6 +433,8 @@ int xc_dom_alloc_page(struct xc_dom_image *dom, char *name)
start = dom->virt_alloc_end;
dom->virt_alloc_end += page_size;
+ if (dom->allocate)
+ dom->allocate(dom, dom->virt_alloc_end);
pfn = (start - dom->parms.virt_base) / page_size;
xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n",
@@ -506,7 +510,7 @@ void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks)
first_hook = hooks;
}
-static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
+struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
{
struct xc_dom_arch *hooks = first_hook;