WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Add PV-GRUB

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Add PV-GRUB
From: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Date: Tue, 17 Jun 2008 15:06:05 +0100
Delivery-date: Tue, 17 Jun 2008 07:06:40 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.12-2006-07-14
Add PV-GRUB

This fetches GRUB1 sources, applies the {graphical, print function, save
default, and ext3_256byte} patches from debian, and applies a patch to
make it work on x86_64 and port it to Mini-OS.  By using libxc, PV-GRUB
can then "kexec" the loaded kernel from inside the domain itself, hence
permitting to avoid the security-concerned pygrub.

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>

diff -r 0f495b493f40 .hgignore
--- a/.hgignore Tue Jun 17 12:04:18 2008 +0100
+++ b/.hgignore Tue Jun 17 14:46:35 2008 +0100
@@ -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$
--- a/extras/mini-os/arch/x86/mm.c      Tue Jun 17 12:04:18 2008 +0100
+++ b/extras/mini-os/arch/x86/mm.c      Tue Jun 17 14:46:35 2008 +0100
@@ -372,7 +372,7 @@
     return &tab[offset];
 }
 
-static pgentry_t *need_pgt(unsigned long addr)
+pgentry_t *need_pgt(unsigned long addr)
 {
     unsigned long mfn;
     pgentry_t *tab;
--- a/extras/mini-os/blkfront.c Tue Jun 17 12:04:18 2008 +0100
+++ b/extras/mini-os/blkfront.c Tue Jun 17 14:46:35 2008 +0100
@@ -242,9 +242,15 @@
     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);
 }
--- a/extras/mini-os/fbfront.c  Tue Jun 17 12:04:18 2008 +0100
+++ b/extras/mini-os/fbfront.c  Tue Jun 17 14:46:35 2008 +0100
@@ -229,9 +229,18 @@
     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 @@
     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);
 
--- a/extras/mini-os/include/x86/arch_mm.h      Tue Jun 17 12:04:18 2008 +0100
+++ b/extras/mini-os/include/x86/arch_mm.h      Tue Jun 17 14:46:35 2008 +0100
@@ -221,4 +221,6 @@
 #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_ */
--- a/extras/mini-os/main.c     Tue Jun 17 12:04:18 2008 +0100
+++ b/extras/mini-os/main.c     Tue Jun 17 14:46:35 2008 +0100
@@ -59,11 +59,13 @@
      * 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 @@
 #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 };
--- a/extras/mini-os/netfront.c Tue Jun 17 12:04:18 2008 +0100
+++ b/extras/mini-os/netfront.c Tue Jun 17 14:46:35 2008 +0100
@@ -497,15 +497,26 @@
     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);
 }
--- a/stubdom/Makefile  Tue Jun 17 12:04:18 2008 +0100
+++ b/stubdom/Makefile  Tue Jun 17 14:46:35 2008 +0100
@@ -14,6 +14,7 @@
 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 @@
 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 @@
 c: cross-newlib mk-symlinks
        $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-cvs 
 
+######
+# Grub
+######
+
+grub-cvs:
+       cvs -z 9 -d :pserver:anonymous@xxxxxxxxxxxxxx:/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 @@
        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 @@
        rm -fr gcc-$(GCC_VERSION)
        rm -fr newlib-cvs
        rm -fr lwip-cvs
+       rm -fr grub-cvs
 
 # clean downloads
 .PHONY: downloadclean
--- a/stubdom/README    Tue Jun 17 12:04:18 2008 +0100
+++ b/stubdom/README    Tue Jun 17 14:46:35 2008 +0100
@@ -6,12 +6,19 @@
 
 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 @@
 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 @@
 
 * 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 @@
 /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.
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub.patches/10graphics.diff      Tue Jun 17 14:46:35 2008 +0100
@@ -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@xxxxxxxxxx> based
++ * on a patch by Paulo César Pereira de Andrade <pcpa@xxxxxxxxxxxxxxxx>
++ * Options and enhancements made by Herton Ronaldo Krzesinski
++ * <herton@xxxxxxxxxxxx>
++ *
++ *  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 */
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub.patches/20print_func.diff    Tue Jun 17 14:46:35 2008 +0100
@@ -0,0 +1,80 @@
+2006-01-05  Otavio Salvador  <otavio@xxxxxxxxxx>
+
+       * Rediff.
+
+2005-16-10  Samuel Thibault  <samuel.thibault@xxxxxxxxxxxx>
+
+       * 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 */
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub.patches/30savedefault.diff   Tue Jun 17 14:46:35 2008 +0100
@@ -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);
+               }
+ 
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub.patches/40ext3_256byte_inode.diff    Tue Jun 17 14:46:35 
2008 +0100
@@ -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;
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub.patches/99minios     Tue Jun 17 14:46:35 2008 +0100
@@ -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;
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/Makefile     Tue Jun 17 14:46:35 2008 +0100
@@ -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
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/boot-x86_32.S        Tue Jun 17 14:46:35 2008 +0100
@@ -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)
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/boot-x86_64.S        Tue Jun 17 14:46:35 2008 +0100
@@ -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)
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/config.h     Tue Jun 17 14:46:35 2008 +0100
@@ -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);
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/kexec.c      Tue Jun 17 14:46:35 2008 +0100
@@ -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@xxxxxxxxxxxxx>, 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 );
+}
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/mini-os.c    Tue Jun 17 14:46:35 2008 +0100
@@ -0,0 +1,702 @@
+/*
+ * Mini-OS support for GRUB.
+ *
+ * Samuel Thibault <Samuel.Thibault@xxxxxxxxxxxxx>, 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");
+}
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/mini-os.h    Tue Jun 17 14:46:35 2008 +0100
@@ -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;
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/grub/osdep.h      Tue Jun 17 14:46:35 2008 +0100
@@ -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
--- a/tools/libxc/xc_dom.h      Tue Jun 17 12:04:18 2008 +0100
+++ b/tools/libxc/xc_dom.h      Tue Jun 17 14:46:35 2008 +0100
@@ -107,6 +107,8 @@
 
     /* 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 @@
                        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);
 
--- a/tools/libxc/xc_dom_core.c Tue Jun 17 12:04:18 2008 +0100
+++ b/tools/libxc/xc_dom_core.c Tue Jun 17 14:46:35 2008 +0100
@@ -409,6 +409,8 @@
     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 @@
 
     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 @@
     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;
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] Add PV-GRUB, Samuel Thibault <=