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@eu.citrix.com> 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@cvs.sv.gnu.org:/sources/grub co -D $(GRUB_DATE) -d $@ grub + for i in grub.patches/* ; do \ + patch -d $@ -p1 < $$i ; \ + done + +.PHONY: grub +grub: grub-cvs cross-newlib mk-symlinks + $(MAKE) -C $@ + ######## # minios ######## .PHONY: ioemu-stubdom ioemu-stubdom: mini-os-ioemu lwip-cvs libxc ioemu - $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/ioemu/i386-dm-stubdom/qemu.a $(CURDIR)/ioemu/i386-dm-stubdom/libqemu.a" CFLAGS=-DCONFIG_QEMU + DEF_CFLAGS=-DCONFIG_QEMU $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/ioemu/i386-dm-stubdom/qemu.a $(CURDIR)/ioemu/i386-dm-stubdom/libqemu.a" CAMLLIB = $(shell ocamlc -where) .PHONY: caml-stubdom caml-stubdom: mini-os-caml lwip-cvs libxc caml - $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o $(CAMLLIB)/libasmrun.a" CFLAGS=-DCONFIG_CAML + DEF_CFLAGS=-DCONFIG_CAML $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o $(CAMLLIB)/libasmrun.a" .PHONY: c-stubdom c-stubdom: mini-os-c lwip-cvs libxc c - $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS=$(CURDIR)/c/main.a CFLAGS=-DCONFIG_C + DEF_CFLAGS=-DCONFIG_C $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS=$(CURDIR)/c/main.a + +.PHONY: pv-grub +pv-grub: mini-os-grub libxc grub + DEF_CFLAGS=-DCONFIG_GRUB $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< APP_OBJS=$(CURDIR)/grub/main.a ######### # install ######### -install: mini-os-ioemu/mini-os.gz +install: install-ioemu install-grub + +install-ioemu: mini-os-ioemu/mini-os.gz $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin" - $(INSTALL_PROG) $< "$(DESTDIR)/usr/lib/xen/boot/stubdom.gz" + $(INSTALL_PROG) $< "$(DESTDIR)/usr/lib/xen/boot/ioemu-stubdom.gz" + +install-grub: mini-os-grub/mini-os.gz + $(INSTALL_PROG) $< "$(DESTDIR)/usr/lib/xen/boot/pv-grub.gz" ####### # clean @@ -256,8 +280,10 @@ 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@redhat.com> based ++ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br> ++ * Options and enhancements made by Herton Ronaldo Krzesinski ++ * <herton@mandriva.com> ++ * ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2001,2002 Red Hat, Inc. ++ * Portions copyright (C) 2000 Conectiva, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifdef SUPPORT_GRAPHICS ++ ++#include <term.h> ++#include <shared.h> ++#include <graphics.h> ++ ++int saved_videomode; ++unsigned char *font8x16; ++ ++int graphics_inited = 0; ++static char splashimage[256]; ++ ++int shade = 1, no_cursor = 0; ++ ++#define VSHADOW VSHADOW1 ++unsigned char VSHADOW1[38400]; ++unsigned char VSHADOW2[38400]; ++unsigned char VSHADOW4[38400]; ++unsigned char VSHADOW8[38400]; ++ ++/* define the default viewable area */ ++int view_x0 = 0; ++int view_y0 = 0; ++int view_x1 = 80; ++int view_y1 = 30; ++ ++/* text buffer has to be kept around so that we can write things as we ++ * scroll and the like */ ++unsigned short text[80 * 30]; ++ ++/* graphics options */ ++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, window_border = 0; ++ ++/* current position */ ++static int fontx = 0; ++static int fonty = 0; ++ ++/* global state so that we don''t try to recursively scroll or cursor */ ++static int no_scroll = 0; ++ ++/* color state */ ++static int graphics_standard_color = A_NORMAL; ++static int graphics_normal_color = A_NORMAL; ++static int graphics_highlight_color = A_REVERSE; ++static int graphics_current_color = A_NORMAL; ++static color_state graphics_color_state = COLOR_STATE_STANDARD; ++ ++static inline void outb(unsigned short port, unsigned char val) ++{ ++ __asm __volatile ("outb %0,%1"::"a" (val), "d" (port)); ++} ++ ++static void MapMask(int value) { ++ outb(0x3c4, 2); ++ outb(0x3c5, value); ++} ++ ++/* bit mask register */ ++static void BitMask(int value) { ++ outb(0x3ce, 8); ++ outb(0x3cf, value); ++} ++ ++/* move the graphics cursor location to col, row */ ++static void graphics_setxy(int col, int row) { ++ if (col >= view_x0 && col < view_x1) { ++ fontx = col; ++ cursorX = col << 3; ++ } ++ if (row >= view_y0 && row < view_y1) { ++ fonty = row; ++ cursorY = row << 4; ++ } ++} ++ ++/* scroll the screen */ ++static void graphics_scroll() { ++ int i, j, k; ++ ++ /* we don''t want to scroll recursively... that would be bad */ ++ if (no_scroll) ++ return; ++ no_scroll = 1; ++ ++ /* disable pager temporarily */ ++ k = count_lines; ++ count_lines = -1; ++ ++ /* move everything up a line */ ++ for (j = view_y0 + 1; j < view_y1; j++) { ++ graphics_gotoxy(view_x0, j - 1); ++ for (i = view_x0; i < view_x1; i++) { ++ graphics_putchar(text[j * 80 + i]); ++ } ++ } ++ ++ /* last line should be blank */ ++ graphics_gotoxy(view_x0, view_y1 - 1); ++ for (i = view_x0; i < view_x1; i++) ++ graphics_putchar('' ''); ++ graphics_setxy(view_x0, view_y1 - 1); ++ ++ count_lines = k; ++ ++ no_scroll = 0; ++} ++ ++/* Set the splash image */ ++void graphics_set_splash(char *splashfile) { ++ grub_strcpy(splashimage, splashfile); ++} ++ ++/* Get the current splash image */ ++char *graphics_get_splash(void) { ++ return splashimage; ++} ++ ++/* ++ * Initialize a vga16 graphics display with the palette based off of ++ * the image in splashimage. If the image doesn''t exist, leave graphics ++ * mode. The mode initiated is 12h. From "Ralf Brown''s Interrupt List": ++ * text/ text pixel pixel colors disply scrn system ++ * grph resol box resolution pages addr ++ * 12h G 80x30 8x16 640x480 16/256K . A000 VGA,ATI VIP ++ * G 80x30 8x16 640x480 16/64 . A000 ATI EGA Wonder ++ * G . . 640x480 16 . . UltraVision+256K EGA ++ */ ++int graphics_init() ++{ ++ if (!graphics_inited) { ++ saved_videomode = set_videomode(0x12); ++ if (get_videomode() != 0x12) { ++ set_videomode(saved_videomode); ++ return 0; ++ } ++ graphics_inited = 1; ++ } ++ else ++ return 1; ++ ++ font8x16 = (unsigned char*)graphics_get_font(); ++ ++ /* make sure that the highlight color is set correctly */ ++ graphics_highlight_color = ((graphics_normal_color >> 4) | ++ ((graphics_normal_color & 0xf) << 4)); ++ ++ graphics_cls(); ++ ++ if (!read_image(splashimage)) { ++ grub_printf("Failed to read splash image (%s)\n", splashimage); ++ grub_printf("Press any key to continue..."); ++ getkey(); ++ set_videomode(saved_videomode); ++ graphics_inited = 0; ++ return 0; ++ } ++ ++ set_int1c_handler(); ++ ++ return 1; ++} ++ ++/* Leave graphics mode */ ++void graphics_end(void) ++{ ++ if (graphics_inited) { ++ unset_int1c_handler(); ++ set_videomode(saved_videomode); ++ graphics_inited = 0; ++ no_cursor = 0; ++ } ++} ++ ++/* Print ch on the screen. Handle any needed scrolling or the like */ ++void graphics_putchar(int ch) { ++ ch &= 0xff; ++ ++ graphics_cursor(0); ++ ++ if (ch == ''\n'') { ++ if (fonty + 1 < view_y1) ++ graphics_setxy(fontx, fonty + 1); ++ else ++ graphics_scroll(); ++ graphics_cursor(1); ++ return; ++ } else if (ch == ''\r'') { ++ graphics_setxy(view_x0, fonty); ++ graphics_cursor(1); ++ return; ++ } ++ ++ graphics_cursor(0); ++ ++ text[fonty * 80 + fontx] = ch; ++ text[fonty * 80 + fontx] &= 0x00ff; ++ if (graphics_current_color & 0xf0) ++ text[fonty * 80 + fontx] |= 0x100; ++ ++ graphics_cursor(0); ++ ++ if ((fontx + 1) >= view_x1) { ++ graphics_setxy(view_x0, fonty); ++ if (fonty + 1 < view_y1) ++ graphics_setxy(view_x0, fonty + 1); ++ else ++ graphics_scroll(); ++ graphics_cursor(1); ++ do_more (); ++ graphics_cursor(0); ++ } else { ++ graphics_setxy(fontx + 1, fonty); ++ } ++ ++ graphics_cursor(1); ++} ++ ++/* get the current location of the cursor */ ++int graphics_getxy(void) { ++ return (fontx << 8) | fonty; ++} ++ ++void graphics_gotoxy(int x, int y) { ++ graphics_cursor(0); ++ ++ graphics_setxy(x, y); ++ ++ graphics_cursor(1); ++} ++ ++void graphics_cls(void) { ++ int i; ++ unsigned char *mem, *s1, *s2, *s4, *s8; ++ ++ graphics_cursor(0); ++ graphics_gotoxy(view_x0, view_y0); ++ ++ mem = (unsigned char*)VIDEOMEM; ++ s1 = (unsigned char*)VSHADOW1; ++ s2 = (unsigned char*)VSHADOW2; ++ s4 = (unsigned char*)VSHADOW4; ++ s8 = (unsigned char*)VSHADOW8; ++ ++ for (i = 0; i < 80 * 30; i++) ++ text[i] = '' ''; ++ graphics_cursor(1); ++ ++ BitMask(0xff); ++ ++ /* plane 1 */ ++ MapMask(1); ++ grub_memcpy(mem, s1, 38400); ++ ++ /* plane 2 */ ++ MapMask(2); ++ grub_memcpy(mem, s2, 38400); ++ ++ /* plane 3 */ ++ MapMask(4); ++ grub_memcpy(mem, s4, 38400); ++ ++ /* plane 4 */ ++ MapMask(8); ++ grub_memcpy(mem, s8, 38400); ++ ++ MapMask(15); ++ ++ if (no_cursor) { ++ no_cursor = 0; ++ set_int1c_handler(); ++ } ++} ++ ++void graphics_setcolorstate (color_state state) { ++ switch (state) { ++ case COLOR_STATE_STANDARD: ++ graphics_current_color = graphics_standard_color; ++ break; ++ case COLOR_STATE_NORMAL: ++ graphics_current_color = graphics_normal_color; ++ break; ++ case COLOR_STATE_HIGHLIGHT: ++ graphics_current_color = graphics_highlight_color; ++ break; ++ default: ++ graphics_current_color = graphics_standard_color; ++ break; ++ } ++ ++ graphics_color_state = state; ++} ++ ++void graphics_setcolor (int normal_color, int highlight_color) { ++ graphics_normal_color = normal_color; ++ graphics_highlight_color = highlight_color; ++ ++ graphics_setcolorstate (graphics_color_state); ++} ++ ++int graphics_setcursor (int on) { ++ if (!no_cursor && !on) { ++ no_cursor = 1; ++ unset_int1c_handler(); ++ graphics_cursor(0); ++ } ++ else if(no_cursor && on) { ++ no_cursor = 0; ++ set_int1c_handler(); ++ graphics_cursor(1); ++ } ++ return 0; ++} ++ ++/* Read in the splashscreen image and set the palette up appropriately. ++ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and ++ * 640x480. */ ++int read_image(char *s) ++{ ++ char buf[32], pal[16], c; ++ unsigned char base, mask, *s1, *s2, *s4, *s8; ++ unsigned i, len, idx, colors, x, y, width, height; ++ ++ if (!grub_open(s)) ++ return 0; ++ ++ /* read header */ ++ if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) { ++ grub_close(); ++ return 0; ++ } ++ ++ /* parse info */ ++ while (grub_read(&c, 1)) { ++ if (c == ''"'') ++ break; ++ } ++ ++ while (grub_read(&c, 1) && (c == '' '' || c == ''\t'')) ++ ; ++ ++ i = 0; ++ width = c - ''0''; ++ while (grub_read(&c, 1)) { ++ if (c >= ''0'' && c <= ''9'') ++ width = width * 10 + c - ''0''; ++ else ++ break; ++ } ++ while (grub_read(&c, 1) && (c == '' '' || c == ''\t'')) ++ ; ++ ++ height = c - ''0''; ++ while (grub_read(&c, 1)) { ++ if (c >= ''0'' && c <= ''9'') ++ height = height * 10 + c - ''0''; ++ else ++ break; ++ } ++ while (grub_read(&c, 1) && (c == '' '' || c == ''\t'')) ++ ; ++ ++ colors = c - ''0''; ++ while (grub_read(&c, 1)) { ++ if (c >= ''0'' && c <= ''9'') ++ colors = colors * 10 + c - ''0''; ++ else ++ break; ++ } ++ ++ base = 0; ++ while (grub_read(&c, 1) && c != ''"'') ++ ; ++ ++ /* palette */ ++ for (i = 0, idx = 1; i < colors; i++) { ++ len = 0; ++ ++ while (grub_read(&c, 1) && c != ''"'') ++ ; ++ grub_read(&c, 1); /* char */ ++ base = c; ++ grub_read(buf, 4); /* \t c # */ ++ ++ while (grub_read(&c, 1) && c != ''"'') { ++ if (len < sizeof(buf)) ++ buf[len++] = c; ++ } ++ ++ if (len == 6 && idx < 15) { ++ int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2; ++ int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2; ++ int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2; ++ ++ pal[idx] = base; ++ graphics_set_palette(idx, r, g, b); ++ ++idx; ++ } ++ } ++ ++ x = y = len = 0; ++ ++ s1 = (unsigned char*)VSHADOW1; ++ s2 = (unsigned char*)VSHADOW2; ++ s4 = (unsigned char*)VSHADOW4; ++ s8 = (unsigned char*)VSHADOW8; ++ ++ for (i = 0; i < 38400; i++) ++ s1[i] = s2[i] = s4[i] = s8[i] = 0; ++ ++ /* parse xpm data */ ++ while (y < height) { ++ while (1) { ++ if (!grub_read(&c, 1)) { ++ grub_close(); ++ return 0; ++ } ++ if (c == ''"'') ++ break; ++ } ++ ++ while (grub_read(&c, 1) && c != ''"'') { ++ for (i = 1; i < 15; i++) ++ if (pal[i] == c) { ++ c = i; ++ break; ++ } ++ ++ mask = 0x80 >> (x & 7); ++ if (c & 1) ++ s1[len + (x >> 3)] |= mask; ++ if (c & 2) ++ s2[len + (x >> 3)] |= mask; ++ if (c & 4) ++ s4[len + (x >> 3)] |= mask; ++ if (c & 8) ++ s8[len + (x >> 3)] |= mask; ++ ++ if (++x >= 640) { ++ x = 0; ++ ++ if (y < 480) ++ len += 80; ++ ++y; ++ } ++ } ++ } ++ ++ grub_close(); ++ ++ graphics_set_palette(0, (background >> 16), (background >> 8) & 63, ++ background & 63); ++ graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63, ++ foreground & 63); ++ graphics_set_palette(0x11, (window_border >> 16), (window_border >> 8) & 63, ++ window_border & 63); ++ ++ return 1; ++} ++ ++/* Convert a character which is a hex digit to the appropriate integer */ ++int hex(int v) ++{ ++ if (v >= ''A'' && v <= ''F'') ++ return (v - ''A'' + 10); ++ if (v >= ''a'' && v <= ''f'') ++ return (v - ''a'' + 10); ++ return (v - ''0''); ++} ++ ++void graphics_cursor(int set) { ++ unsigned char *pat, *mem, *ptr, chr[16 << 2]; ++ int i, ch, invert, offset; ++ ++ if (set && (no_cursor || no_scroll)) ++ return; ++ ++ offset = cursorY * 80 + fontx; ++ ch = text[fonty * 80 + fontx] & 0xff; ++ invert = (text[fonty * 80 + fontx] & 0xff00) != 0; ++ pat = font8x16 + (ch << 4); ++ ++ mem = (unsigned char*)VIDEOMEM + offset; ++ ++ if (!set) { ++ for (i = 0; i < 16; i++) { ++ unsigned char mask = pat[i]; ++ ++ if (!invert) { ++ chr[i ] = ((unsigned char*)VSHADOW1)[offset]; ++ chr[16 + i] = ((unsigned char*)VSHADOW2)[offset]; ++ chr[32 + i] = ((unsigned char*)VSHADOW4)[offset]; ++ chr[48 + i] = ((unsigned char*)VSHADOW8)[offset]; ++ ++ if (shade) { ++ if (ch == DISP_VERT || ch == DISP_LL || ++ ch == DISP_UR || ch == DISP_LR) { ++ unsigned char pmask = ~(pat[i] >> 1); ++ ++ chr[i ] &= pmask; ++ chr[16 + i] &= pmask; ++ chr[32 + i] &= pmask; ++ chr[48 + i] &= pmask; ++ } ++ if (i > 0 && ch != DISP_VERT) { ++ unsigned char pmask = ~(pat[i - 1] >> 1); ++ ++ chr[i ] &= pmask; ++ chr[16 + i] &= pmask; ++ chr[32 + i] &= pmask; ++ chr[48 + i] &= pmask; ++ if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) { ++ pmask = ~pat[i - 1]; ++ ++ chr[i ] &= pmask; ++ chr[16 + i] &= pmask; ++ chr[32 + i] &= pmask; ++ chr[48 + i] &= pmask; ++ } ++ } ++ } ++ chr[i ] |= mask; ++ chr[16 + i] |= mask; ++ chr[32 + i] |= mask; ++ chr[48 + i] |= mask; ++ ++ offset += 80; ++ } ++ else { ++ chr[i ] = mask; ++ chr[16 + i] = mask; ++ chr[32 + i] = mask; ++ chr[48 + i] = mask; ++ } ++ } ++ } ++ else { ++ MapMask(15); ++ ptr = mem; ++ for (i = 0; i < 16; i++, ptr += 80) { ++ cursorBuf[i] = pat[i]; ++ *ptr = ~pat[i]; ++ } ++ return; ++ } ++ ++ offset = 0; ++ for (i = 1; i < 16; i <<= 1, offset += 16) { ++ int j; ++ ++ MapMask(i); ++ ptr = mem; ++ for (j = 0; j < 16; j++, ptr += 80) ++ *ptr = chr[j + offset]; ++ } ++ ++ MapMask(15); ++} ++ ++#endif /* SUPPORT_GRAPHICS */ +diff -Naur grub-0.97.orig/stage2/graphics.h grub-0.97/stage2/graphics.h +--- grub-0.97.orig/stage2/graphics.h 1969-12-31 21:00:00.000000000 -0300 ++++ grub-0.97/stage2/graphics.h 2005-06-12 20:56:49.000000000 -0300 +@@ -0,0 +1,44 @@ ++/* graphics.h - graphics console interface */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002 Free Software Foundation, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef GRAPHICS_H ++#define GRAPHICS_H ++ ++/* magic constant */ ++#define VIDEOMEM 0xA0000 ++ ++/* function prototypes */ ++char *graphics_get_splash(void); ++ ++int read_image(char *s); ++void graphics_cursor(int set); ++ ++/* function prototypes for asm functions */ ++void * graphics_get_font(); ++void graphics_set_palette(int idx, int red, int green, int blue); ++void set_int1c_handler(); ++void unset_int1c_handler(); ++ ++extern short cursorX, cursorY; ++extern char cursorBuf[16]; ++extern int shade; ++extern int view_x0, view_y0, view_x1, view_y1; ++ ++#endif /* GRAPHICS_H */ +diff -Naur grub-0.97.orig/stage2/Makefile.am grub-0.97/stage2/Makefile.am +--- grub-0.97.orig/stage2/Makefile.am 2005-02-02 18:37:35.000000000 -0200 ++++ grub-0.97/stage2/Makefile.am 2005-06-12 20:56:49.000000000 -0300 +@@ -7,7 +7,7 @@ + fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \ + imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \ + nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \ +- terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h ++ terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h + EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) + + # For <stage1.h>. +@@ -19,7 +19,7 @@ + disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \ + fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \ + fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \ +- terminfo.c tparm.c ++ terminfo.c tparm.c graphics.c + libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ + -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ + -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \ +@@ -79,8 +79,14 @@ + HERCULES_FLAGS + endif + ++if GRAPHICS_SUPPORT ++GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1 ++else ++GRAPHICS_FLAGS ++endif ++ + STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ +- $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) ++ $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS) + + STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 + STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 +@@ -90,7 +96,8 @@ + cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \ + fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \ + fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \ +- hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c ++ hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \ ++ graphics.c + pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) + pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) + pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) +diff -Naur grub-0.97.orig/stage2/shared.h grub-0.97/stage2/shared.h +--- grub-0.97.orig/stage2/shared.h 2004-06-19 13:40:09.000000000 -0300 ++++ grub-0.97/stage2/shared.h 2005-06-12 20:56:49.000000000 -0300 +@@ -792,6 +792,11 @@ + /* Set the cursor position. */ + void gotoxy (int x, int y); + ++/* Internal pager ++ Returns 1 = if pager was used ++ 0 = if pager wasn''t used */ ++int do_more (void); ++ + /* Displays an ASCII character. IBM displays will translate some + characters to special graphical ones (see the DISP_* constants). */ + void grub_putchar (int c); +@@ -871,6 +876,7 @@ + int grub_tolower (int c); + int grub_isspace (int c); + int grub_strncat (char *s1, const char *s2, int n); ++void grub_memcpy(void *dest, const void *src, int len); + void *grub_memmove (void *to, const void *from, int len); + void *grub_memset (void *start, int c, int len); + int grub_strncat (char *s1, const char *s2, int n); +diff -Naur grub-0.97.orig/stage2/stage2.c grub-0.97/stage2/stage2.c +--- grub-0.97.orig/stage2/stage2.c 2005-03-19 14:51:57.000000000 -0300 ++++ grub-0.97/stage2/stage2.c 2005-06-13 22:38:08.000000000 -0300 +@@ -20,6 +20,12 @@ + #include <shared.h> + #include <term.h> + ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#endif ++ ++int col_start, col_end, row_start, box_size; ++ + grub_jmp_buf restart_env; + + #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) +@@ -105,13 +111,13 @@ + if (highlight && current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); + +- gotoxy (2, y); ++ gotoxy (2 + col_start, y); + grub_putchar ('' ''); +- for (x = 3; x < 75; x++) ++ for (x = 3 + col_start; x < (col_end - 5); x++) + { +- if (*entry && x <= 72) ++ if (*entry && x <= (col_end - 8)) + { +- if (x == 72) ++ if (x == (col_end - 8)) + grub_putchar (DISP_RIGHT); + else + grub_putchar (*entry++); +@@ -119,7 +125,7 @@ + else + grub_putchar ('' ''); + } +- gotoxy (74, y); ++ gotoxy ((col_end - 6), y); + + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_STANDARD); +@@ -131,7 +137,7 @@ + { + int i; + +- gotoxy (77, y + 1); ++ gotoxy ((col_end - 3), y + 1); + + if (first) + grub_putchar (DISP_UP); +@@ -151,14 +157,14 @@ + menu_entries++; + } + +- gotoxy (77, y + size); ++ gotoxy ((col_end - 3), y + size); + + if (*menu_entries) + grub_putchar (DISP_DOWN); + else + grub_putchar ('' ''); + +- gotoxy (74, y + entryno + 1); ++ gotoxy ((col_end - 6), y + entryno + 1); + } + + static void +@@ -196,30 +202,30 @@ + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_NORMAL); + +- gotoxy (1, y); ++ gotoxy (1 + col_start, y); + + grub_putchar (DISP_UL); +- for (i = 0; i < 73; i++) ++ for (i = col_start; i < (col_end - 7); i++) + grub_putchar (DISP_HORIZ); + grub_putchar (DISP_UR); + + i = 1; + while (1) + { +- gotoxy (1, y + i); ++ gotoxy (1 + col_start, y + i); + + if (i > size) + break; + + grub_putchar (DISP_VERT); +- gotoxy (75, y + i); ++ gotoxy ((col_end - 5), y + i); + grub_putchar (DISP_VERT); + + i++; + } + + grub_putchar (DISP_LL); +- for (i = 0; i < 73; i++) ++ for (i = col_start; i < (col_end - 7); i++) + grub_putchar (DISP_HORIZ); + grub_putchar (DISP_LR); + +@@ -233,6 +239,7 @@ + { + int c, time1, time2 = -1, first_entry = 0; + char *cur_entry = 0; ++ struct term_entry *prev_term = NULL; + + /* + * Main loop for menu UI. +@@ -250,6 +257,22 @@ + } + } + ++ col_start = 0; ++ col_end = 80; ++ row_start = 0; ++ box_size = 12; ++ /* if we''re using viewport we need to make sure to setup ++ coordinates correctly. */ ++#ifdef SUPPORT_GRAPHICS ++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) ++ { ++ col_start = view_x0; ++ col_end = view_x1; ++ row_start = view_y0; ++ box_size = (view_y1 - view_y0) - 13; ++ } ++#endif ++ + /* If the timeout was expired or wasn''t set, force to show the menu + interface. */ + if (grub_timeout < 0) +@@ -302,36 +325,36 @@ + if (current_term->flags & TERM_DUMB) + print_entries_raw (num_entries, first_entry, menu_entries); + else +- print_border (3, 12); ++ print_border (3 + row_start, box_size); + + grub_printf ("\n\ +- Use the %c and %c keys to select which entry is highlighted.\n", ++ Use the %c and %c keys to select which entry is highlighted.\n", + DISP_UP, DISP_DOWN); + + if (! auth && password) + { + printf ("\ +- Press enter to boot the selected OS or \''p\'' to enter a\n\ +- password to unlock the next set of features."); ++ Press enter to boot the selected OS or \''p\'' to enter a\n\ ++ password to unlock the next set of features."); + } + else + { + if (config_entries) + printf ("\ +- Press enter to boot the selected OS, \''e\'' to edit the\n\ +- commands before booting, or \''c\'' for a command-line."); ++ Press enter to boot the selected OS, \''e\'' to edit the\n\ ++ commands before booting, or \''c\'' for a command-line."); + else + printf ("\ +- Press \''b\'' to boot, \''e\'' to edit the selected command in the\n\ +- boot sequence, \''c\'' for a command-line, \''o\'' to open a new line\n\ +- after (\''O\'' for before) the selected line, \''d\'' to remove the\n\ +- selected line, or escape to go back to the main menu."); ++ Press \''b\'' to boot, \''e\'' to edit the selected command in the\n\ ++ boot sequence, \''c\'' for a command-line, \''o\'' to open a new line\n\ ++ after (\''O\'' for before) the selected line, \''d\'' to remove the\n\ ++ selected line, or escape to go back to the main menu."); + } + + if (current_term->flags & TERM_DUMB) + grub_printf ("\n\nThe selected entry is %d ", entryno); + else +- print_entries (3, 12, first_entry, entryno, menu_entries); ++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + } + + /* XX using RT clock now, need to initialize value */ +@@ -358,10 +381,10 @@ + entryno, grub_timeout); + else + { +- gotoxy (3, 22); +- grub_printf ("The highlighted entry will be booted automatically in %d seconds. ", ++ gotoxy (3 + col_start, 10 + box_size + row_start); ++ grub_printf (" The highlighted entry will be booted automatically in %d seconds. ", + grub_timeout); +- gotoxy (74, 4 + entryno); ++ gotoxy ((col_end - 6), 4 + entryno + row_start); + } + + grub_timeout--; +@@ -387,12 +410,12 @@ + if (current_term->flags & TERM_DUMB) + grub_putchar (''\r''); + else +- gotoxy (3, 22); ++ gotoxy (3 + col_start, 10 + box_size + row_start); + printf (" "); + grub_timeout = -1; + fallback_entryno = -1; + if (! (current_term->flags & TERM_DUMB)) +- gotoxy (74, 4 + entryno); ++ gotoxy ((col_end - 6), 4 + entryno + row_start); + } + + /* We told them above (at least in SUPPORT_SERIAL) to use +@@ -408,12 +431,12 @@ + { + if (entryno > 0) + { +- print_entry (4 + entryno, 0, ++ print_entry (4 + entryno + row_start, 0, + get_entry (menu_entries, + first_entry + entryno, + 0)); + entryno--; +- print_entry (4 + entryno, 1, ++ print_entry (4 + entryno + row_start, 1, + get_entry (menu_entries, + first_entry + entryno, + 0)); +@@ -421,7 +444,7 @@ + else if (first_entry > 0) + { + first_entry--; +- print_entries (3, 12, first_entry, entryno, ++ print_entries (3 + row_start, box_size, first_entry, entryno, + menu_entries); + } + } +@@ -433,29 +456,29 @@ + entryno++; + else + { +- if (entryno < 11) ++ if (entryno < (box_size - 1)) + { +- print_entry (4 + entryno, 0, ++ print_entry (4 + entryno + row_start, 0, + get_entry (menu_entries, + first_entry + entryno, + 0)); + entryno++; +- print_entry (4 + entryno, 1, ++ print_entry (4 + entryno + row_start, 1, + get_entry (menu_entries, + first_entry + entryno, + 0)); + } +- else if (num_entries > 12 + first_entry) ++ else if (num_entries > box_size + first_entry) + { + first_entry++; +- print_entries (3, 12, first_entry, entryno, menu_entries); ++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + } + } + } + else if (c == 7) + { + /* Page Up */ +- first_entry -= 12; ++ first_entry -= box_size; + if (first_entry < 0) + { + entryno += first_entry; +@@ -463,20 +486,20 @@ + if (entryno < 0) + entryno = 0; + } +- print_entries (3, 12, first_entry, entryno, menu_entries); ++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + } + else if (c == 3) + { + /* Page Down */ +- first_entry += 12; ++ first_entry += box_size; + if (first_entry + entryno + 1 >= num_entries) + { +- first_entry = num_entries - 12; ++ first_entry = num_entries - box_size; + if (first_entry < 0) + first_entry = 0; + entryno = num_entries - first_entry - 1; + } +- print_entries (3, 12, first_entry, entryno, menu_entries); ++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + } + + if (config_entries) +@@ -489,7 +512,7 @@ + if ((c == ''d'') || (c == ''o'') || (c == ''O'')) + { + if (! (current_term->flags & TERM_DUMB)) +- print_entry (4 + entryno, 0, ++ print_entry (4 + entryno + row_start, 0, + get_entry (menu_entries, + first_entry + entryno, + 0)); +@@ -537,7 +560,7 @@ + + if (entryno >= num_entries) + entryno--; +- if (first_entry && num_entries < 12 + first_entry) ++ if (first_entry && num_entries < box_size + first_entry) + first_entry--; + } + +@@ -549,7 +572,7 @@ + grub_printf ("\n"); + } + else +- print_entries (3, 12, first_entry, entryno, menu_entries); ++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + } + + cur_entry = menu_entries; +@@ -570,7 +593,7 @@ + if (current_term->flags & TERM_DUMB) + grub_printf ("\r "); + else +- gotoxy (1, 21); ++ gotoxy (1 + col_start, 9 + box_size + row_start); + + /* Wipe out the previously entered password */ + grub_memset (entered, 0, sizeof (entered)); +@@ -714,6 +737,15 @@ + + cls (); + setcursor (1); ++ /* if our terminal needed initialization, we should shut it down ++ * before booting the kernel, but we want to save what it was so ++ * we can come back if needed */ ++ prev_term = current_term; ++ if (current_term->shutdown) ++ { ++ current_term->shutdown(); ++ current_term = term_table; /* assumption: console is first */ ++ } + + while (1) + { +@@ -748,6 +780,13 @@ + break; + } + ++ /* if we get back here, we should go back to what our term was before */ ++ current_term = prev_term; ++ if (current_term->startup) ++ /* if our terminal fails to initialize, fall back to console since ++ * it should always work */ ++ if (current_term->startup() == 0) ++ current_term = term_table; /* we know that console is first */ + show_menu = 1; + goto restart; + } +@@ -1050,6 +1089,16 @@ + while (is_preset); + } + ++ /* go ahead and make sure the terminal is setup */ ++ if (current_term->startup) ++ { ++ /* If initialization fails, go back to default terminal */ ++ if (current_term->startup() == 0) ++ { ++ current_term = term_table; ++ } ++ } ++ + if (! num_entries) + { + /* If no acceptable config file, goto command-line, starting +diff -Naur grub-0.97.orig/stage2/term.h grub-0.97/stage2/term.h +--- grub-0.97.orig/stage2/term.h 2003-07-09 08:45:53.000000000 -0300 ++++ grub-0.97/stage2/term.h 2005-06-13 14:07:40.000000000 -0300 +@@ -60,6 +60,8 @@ + const char *name; + /* The feature flags defined above. */ + unsigned long flags; ++ /* Default for maximum number of lines if not specified */ ++ unsigned short max_lines; + /* Put a character. */ + void (*putchar) (int c); + /* Check if any input character is available. */ +@@ -79,6 +81,10 @@ + void (*setcolor) (int normal_color, int highlight_color); + /* Turn on/off the cursor. */ + int (*setcursor) (int on); ++ /* function to start a terminal */ ++ int (*startup) (void); ++ /* function to use to shutdown a terminal */ ++ void (*shutdown) (void); + }; + + /* This lists up available terminals. */ +@@ -124,4 +130,24 @@ + int hercules_setcursor (int on); + #endif + ++#ifdef SUPPORT_GRAPHICS ++extern int foreground, background, window_border, graphics_inited, saved_videomode; ++ ++void graphics_set_splash(char *splashfile); ++int set_videomode(int mode); ++int get_videomode(void); ++void graphics_putchar (int c); ++int graphics_getxy(void); ++void graphics_gotoxy(int x, int y); ++void graphics_cls(void); ++void graphics_setcolorstate (color_state state); ++void graphics_setcolor (int normal_color, int highlight_color); ++int graphics_setcursor (int on); ++int graphics_init(void); ++void graphics_end(void); ++ ++int hex(int v); ++void graphics_set_palette(int idx, int red, int green, int blue); ++#endif /* SUPPORT_GRAPHICS */ ++ + #endif /* ! GRUB_TERM_HEADER */ --- /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@debian.org> + + * Rediff. + +2005-16-10 Samuel Thibault <samuel.thibault@ens-lyon.org> + + * docs/grub.texi: Added print command description. + * stage2/builtins.c(print_func): New function. + (builtin_print): New variable. + (builtin_table): Added builtin_print in table. + +Debian Status Following: + Added by: Otavio Salvador + Date: 2006-01-05 + +diff -Nur grub-0.97-bkp/docs/grub.texi grub-0.97/docs/grub.texi +--- grub-0.97-bkp/docs/grub.texi 2006-01-05 10:59:05.564347912 -0200 ++++ grub-0.97/docs/grub.texi 2006-01-05 11:18:59.033912960 -0200 +@@ -2685,6 +2685,7 @@ + * module:: Load a module + * modulenounzip:: Load a module without decompression + * pause:: Wait for a key press ++* print:: Print a message + * quit:: Exit from the grub shell + * reboot:: Reboot your computer + * read:: Read data from memory +@@ -3091,6 +3092,16 @@ + @end deffn + + ++@node print ++@subsection print ++ ++@deffn Command print message @dots{} ++Print the @var{message}. Note that placing @key{^G} (ASCII code 7) in the ++message will cause the speaker to emit the standard beep sound, which is ++useful for visually impaired people. ++@end deffn ++ ++ + @node quit + @subsection quit + +diff -Nur grub-0.97-bkp/stage2/builtins.c grub-0.97/stage2/builtins.c +--- grub-0.97-bkp/stage2/builtins.c 2006-01-05 10:59:05.550350040 -0200 ++++ grub-0.97/stage2/builtins.c 2006-01-05 11:19:28.422445224 -0200 +@@ -2323,6 +2323,25 @@ + "Probe I/O ports used for the drive DRIVE." + }; + ++/* print */ ++static int ++print_func (char *arg, int flags) ++{ ++ printf("%s\n", arg); ++ ++ return 0; ++} ++ ++static struct builtin builtin_print ++{ ++ "print", ++ print_func, ++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_NO_ECHO, ++ "print [MESSAGE ...]", ++ "Print MESSAGE." ++}; ++ ++ + + /* kernel */ + static int +@@ -4848,6 +4867,7 @@ + &builtin_parttype, + &builtin_password, + &builtin_pause, ++ &builtin_print, + #ifdef GRUB_UTIL + &builtin_quit, + #endif /* GRUB_UTIL */ --- /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@eu.citrix.com>, May 2008 + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/mman.h> + +#include <xenctrl.h> +#include <xc_dom.h> + +#include <kernel.h> +#include <console.h> +#include <os.h> +#include <blkfront.h> +#include <netfront.h> +#include <fbfront.h> +#include <shared.h> + +#include "mini-os.h" + +#if 0 +#define DEBUG(fmt, ...) printk(fmt, ## __VA_ARGS__) +#else +#define DEBUG(fmt, ...) (void)0 +#endif + +/* Assembly boot page from boot.S */ +extern void _boot_page; +extern pgentry_t _boot_page_entry; +extern unsigned long _boot_pdmfn; +extern unsigned long _boot_stack, _boot_target, _boot_start_info, _boot_start; +extern xen_pfn_t _boot_oldpdmfn; +extern void _boot(void); + +static unsigned long *pages; +static unsigned long *pages_mfns; +static unsigned long allocated; + +int pin_table(int xc_handle, unsigned int type, unsigned long mfn, + domid_t dom); + +/* We need mfn to appear as target_pfn, so exchange with the MFN there */ +static void do_exchange(struct xc_dom_image *dom, xen_pfn_t target_pfn, xen_pfn_t source_mfn) +{ + xen_pfn_t source_pfn; + xen_pfn_t target_mfn; + + for (source_pfn = 0; source_pfn < start_info.nr_pages; source_pfn++) + if (dom->p2m_host[source_pfn] == source_mfn) + break; + ASSERT(source_pfn < start_info.nr_pages); + + target_mfn = dom->p2m_host[target_pfn]; + + /* Put target MFN at source PFN */ + dom->p2m_host[source_pfn] = target_mfn; + + /* Put source MFN at target PFN */ + dom->p2m_host[target_pfn] = source_mfn; +} + +int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to) +{ + unsigned long new_allocated = (up_to - dom->parms.virt_base) / PAGE_SIZE; + unsigned long i; + + pages = realloc(pages, new_allocated * sizeof(*pages)); + pages_mfns = realloc(pages_mfns, new_allocated * sizeof(*pages_mfns)); + for (i = allocated; i < new_allocated; i++) { + /* Exchange old page of PFN i with a newly allocated page. */ + xen_pfn_t old_mfn = dom->p2m_host[i]; + xen_pfn_t new_pfn; + xen_pfn_t new_mfn; + + pages[i] = alloc_page(); + memset((void*) pages[i], 0, PAGE_SIZE); + new_pfn = PHYS_PFN(to_phys(pages[i])); + pages_mfns[i] = new_mfn = pfn_to_mfn(new_pfn); + + /* Put old page at new PFN */ + dom->p2m_host[new_pfn] = old_mfn; + + /* Put new page at PFN i */ + dom->p2m_host[i] = new_mfn; + } + + allocated = new_allocated; + + return 0; +} + +void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline) +{ + struct xc_dom_image *dom; + int rc; + domid_t domid = DOMID_SELF; + xen_pfn_t pfn; + int xc_handle; + unsigned long i; + void *seg; + xen_pfn_t boot_page_mfn = virt_to_mfn(&_boot_page); + char features[] = ""; + struct mmu_update *m2p_updates; + unsigned long nr_m2p_updates; + + DEBUG("booting with cmdline %s\n", cmdline); + xc_handle = xc_interface_open(); + + dom = xc_dom_allocate(cmdline, features); + dom->allocate = kexec_allocate; + + dom->kernel_blob = kernel; + dom->kernel_size = kernel_size; + + dom->ramdisk_blob = module; + dom->ramdisk_size = module_size; + + dom->flags = 0; + dom->console_evtchn = start_info.console.domU.evtchn; + dom->xenstore_evtchn = start_info.store_evtchn; + + if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) { + grub_printf("xc_dom_boot_xen_init returned %d\n", rc); + errnum = ERR_BOOT_FAILURE; + goto out; + } + if ( (rc = xc_dom_parse_image(dom)) != 0 ) { + grub_printf("xc_dom_parse_image returned %d\n", rc); + errnum = ERR_BOOT_FAILURE; + goto out; + } + +#ifdef __i386__ + if (strcmp(dom->guest_type, "xen-3.0-x86_32p")) { + grub_printf("can only boot x86 32 PAE kernels, not %s\n", dom->guest_type); + errnum = ERR_EXEC_FORMAT; + goto out; + } +#endif +#ifdef __x86_64__ + if (strcmp(dom->guest_type, "xen-3.0-x86_64")) { + grub_printf("can only boot x86 64 kernels, not %s\n", dom->guest_type); + errnum = ERR_EXEC_FORMAT; + goto out; + } +#endif + + /* equivalent of xc_dom_mem_init */ + dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type); + dom->total_pages = start_info.nr_pages; + + /* equivalent of arch_setup_meminit */ + + /* setup initial p2m */ + dom->p2m_host = malloc(sizeof(*dom->p2m_host) * dom->total_pages); + + /* Start with our current P2M */ + for (i = 0; i < dom->total_pages; i++) + dom->p2m_host[i] = pfn_to_mfn(i); + + if ( (rc = xc_dom_build_image(dom)) != 0 ) { + grub_printf("xc_dom_build_image returned %d\n", rc); + errnum = ERR_BOOT_FAILURE; + goto out; + } + + /* copy hypercall page */ + /* TODO: domctl instead, but requires privileges */ + if (dom->parms.virt_hypercall != -1) { + pfn = PHYS_PFN(dom->parms.virt_hypercall - dom->parms.virt_base); + memcpy((void *) pages[pfn], hypercall_page, PAGE_SIZE); + } + + /* Equivalent of xc_dom_boot_image */ + dom->shared_info_mfn = PHYS_PFN(start_info.shared_info); + + if (!xc_dom_compat_check(dom)) { + grub_printf("xc_dom_compat_check failed\n"); + errnum = ERR_EXEC_FORMAT; + goto out; + } + + /* Move current console, xenstore and boot MFNs to the allocated place */ + do_exchange(dom, dom->console_pfn, start_info.console.domU.mfn); + do_exchange(dom, dom->xenstore_pfn, start_info.store_mfn); + DEBUG("virt base at %llx\n", dom->parms.virt_base); + DEBUG("bootstack_pfn %lx\n", dom->bootstack_pfn); + _boot_target = dom->parms.virt_base + PFN_PHYS(dom->bootstack_pfn); + DEBUG("_boot_target %lx\n", _boot_target); + do_exchange(dom, PHYS_PFN(_boot_target - dom->parms.virt_base), + virt_to_mfn(&_boot_page)); + + /* Make sure the bootstrap page table does not RW-map any of our current + * page table frames */ + kexec_allocate(dom, dom->virt_pgtab_end); + + if ( (rc = xc_dom_update_guest_p2m(dom))) { + grub_printf("xc_dom_update_guest_p2m returned %d\n", rc); + errnum = ERR_BOOT_FAILURE; + goto out; + } + + if ( dom->arch_hooks->setup_pgtables ) + if ( (rc = dom->arch_hooks->setup_pgtables(dom))) { + grub_printf("setup_pgtables returned %d\n", rc); + errnum = ERR_BOOT_FAILURE; + goto out; + } + + /* start info page */ +#undef start_info + if ( dom->arch_hooks->start_info ) + dom->arch_hooks->start_info(dom); +#define start_info (start_info_union.start_info) + + xc_dom_log_memory_footprint(dom); + + /* Unmap libxc''s projection of the boot page table */ + seg = xc_dom_seg_to_ptr(dom, &dom->pgtables_seg); + munmap(seg, dom->pgtables_seg.vend - dom->pgtables_seg.vstart); + + /* Unmap day0 pages to avoid having a r/w mapping of the future page table */ + for (pfn = 0; pfn < allocated; pfn++) + munmap((void*) pages[pfn], PAGE_SIZE); + + /* Pin the boot page table base */ + if ( (rc = pin_table(dom->guest_xc, +#ifdef __i386__ + MMUEXT_PIN_L3_TABLE, +#endif +#ifdef __x86_64__ + MMUEXT_PIN_L4_TABLE, +#endif + xc_dom_p2m_host(dom, dom->pgtables_seg.pfn), + dom->guest_domid)) != 0 ) { + grub_printf("pin_table(%lx) returned %d\n", xc_dom_p2m_host(dom, + dom->pgtables_seg.pfn), rc); + errnum = ERR_BOOT_FAILURE; + goto out_remap; + } + + /* We populate the Mini-OS page table here so that boot.S can just call + * update_va_mapping to project itself there. */ + need_pgt(_boot_target); + DEBUG("day0 pages %lx\n", allocated); + DEBUG("boot target page %lx\n", _boot_target); + DEBUG("boot page %p\n", &_boot_page); + DEBUG("boot page mfn %lx\n", boot_page_mfn); + _boot_page_entry = PFN_PHYS(boot_page_mfn) | L1_PROT; + DEBUG("boot page entry %llx\n", _boot_page_entry); + _boot_oldpdmfn = virt_to_mfn(start_info.pt_base); + DEBUG("boot old pd mfn %lx\n", _boot_oldpdmfn); + DEBUG("boot pd virt %lx\n", dom->pgtables_seg.vstart); + _boot_pdmfn = dom->p2m_host[PHYS_PFN(dom->pgtables_seg.vstart - dom->parms.virt_base)]; + DEBUG("boot pd mfn %lx\n", _boot_pdmfn); + _boot_stack = _boot_target + PAGE_SIZE; + DEBUG("boot stack %lx\n", _boot_stack); + _boot_start_info = dom->parms.virt_base + PFN_PHYS(dom->start_info_pfn); + DEBUG("boot start info %lx\n", _boot_start_info); + _boot_start = dom->parms.virt_entry; + DEBUG("boot start %lx\n", _boot_start); + + /* Keep only useful entries */ + for (nr_m2p_updates = pfn = 0; pfn < start_info.nr_pages; pfn++) + if (dom->p2m_host[pfn] != pfn_to_mfn(pfn)) + nr_m2p_updates++; + + m2p_updates = malloc(sizeof(*m2p_updates) * nr_m2p_updates); + for (i = pfn = 0; pfn < start_info.nr_pages; pfn++) + if (dom->p2m_host[pfn] != pfn_to_mfn(pfn)) { + m2p_updates[i].ptr = PFN_PHYS(dom->p2m_host[pfn]) | MMU_MACHPHYS_UPDATE; + m2p_updates[i].val = pfn; + i++; + } + + for (i = 0; i < blk_nb; i++) + shutdown_blkfront(blk_dev[i]); + if (net_dev) + shutdown_netfront(net_dev); + if (kbd_dev) + shutdown_kbdfront(kbd_dev); + stop_kernel(); + + /* Update M2P */ + if ((rc = HYPERVISOR_mmu_update(m2p_updates, nr_m2p_updates, NULL, DOMID_SELF)) < 0) { + xprintk("Could not update M2P\n"); + ASSERT(0); + } + + xprintk("go!\n"); + + /* Jump to trampoline boot page */ + _boot(); + + ASSERT(0); + +out_remap: + for (pfn = 0; pfn < allocated; pfn++) + do_map_frames(pages[pfn], &pages_mfns[pfn], 1, 0, 0, DOMID_SELF, 0, L1_PROT); +out: + xc_dom_release(dom); + for (pfn = 0; pfn < allocated; pfn++) + free_page((void*)pages[pfn]); + free(pages); + free(pages_mfns); + pages = NULL; + pages_mfns = NULL; + allocated = 0; + xc_interface_close(xc_handle ); +} --- /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@eu.citrix.com>, May 2008 + */ +#include <sys/types.h> +#include <sys/time.h> +#include <stdarg.h> +#include <stdlib.h> +#include <malloc.h> +#include <unistd.h> + +#include <hypervisor.h> +#include <blkfront.h> +#include <netfront.h> +#include <fbfront.h> +#include <semaphore.h> + +#include <osdep.h> +#include <shared.h> +#include <nic.h> +#include <etherboot.h> +#include <terminfo.h> +#include <term.h> + +#include "mini-os.h" + +extern const char *preset_menu; +char config_file[DEFAULT_FILE_BUFLEN] = "(hd0,0)/boot/grub/menu.lst"; +unsigned long boot_drive = NETWORK_DRIVE; +unsigned long install_partition = 0xFFFFFF; + +char version_string[] = VERSION; + +/* Variables from asm.S */ +int saved_entryno; + +/* + * Disk + */ + +struct blkfront_dev **blk_dev; +int blk_nb; +static struct blkfront_info *blk_info; + +static int vbdcmp(const void *_vbd1, const void *_vbd2) { + char *vbd1 = *(char **)_vbd1; + char *vbd2 = *(char **)_vbd2; + int vbdn1 = atoi(vbd1); + int vbdn2 = atoi(vbd2); + return vbdn1 - vbdn2; +} + +void init_disk (void) +{ + char **list; + char *msg; + int i; + char *path; + + msg = xenbus_ls(XBT_NIL, "device/vbd", &list); + if (msg) { + printk("Error %s while reading list of disks\n", msg); + free(msg); + return; + } + blk_nb = 0; + while (list[blk_nb]) + blk_nb++; + blk_dev = malloc(blk_nb * sizeof(*blk_dev)); + blk_info = malloc(blk_nb * sizeof(*blk_info)); + + qsort(list, blk_nb, sizeof(*list), vbdcmp); + + for (i = 0; i < blk_nb; i++) { + printk("vbd %s is hd%d\n", list[i], i); + asprintf(&path, "device/vbd/%s", list[i]); + blk_dev[i] = init_blkfront(path, &blk_info[i]); + free(path); + free(list[i]); + } +} + +/* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return + non-zero, otherwise zero. */ +int get_diskinfo (int drive, struct geometry *geometry) +{ + int i; + if (!(drive & 0x80)) + return -1; + + i = drive - 0x80; + if (i >= blk_nb) + return -1; + + /* Bogus geometry */ + geometry->cylinders = 65535; + geometry->heads = 255; + geometry->sectors = 63; + + geometry->total_sectors = blk_info[i].sectors; + geometry->sector_size = blk_info[i].sector_size; + geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION; + if (blk_info[i].info & VDISK_CDROM) + geometry->flags |= BIOSDISK_FLAG_CDROM; + return 0; +} + +/* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY + from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it, + else if READ is BIOSDISK_WRITE, then write it. If an geometry error + occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then + return the error number. Otherwise, return 0. */ +int +biosdisk (int read, int drive, struct geometry *geometry, + unsigned int sector, int nsec, int segment) +{ + void *addr = (void *) ((unsigned long)segment << 4); + struct blkfront_aiocb aiocb; + int i; + + if (!(drive & 0x80)) + return -1; + + i = drive - 0x80; + if (i >= blk_nb) + return -1; + + aiocb.aio_dev = blk_dev[i]; + aiocb.aio_buf = addr; + aiocb.aio_nbytes = (size_t)nsec * blk_info[i].sector_size; + aiocb.aio_offset = (off_t)sector * blk_info[i].sector_size; + aiocb.aio_cb = NULL; + + blkfront_io(&aiocb, read == BIOSDISK_WRITE); + + return 0; +} + +static int +load_file(char *name, void **ptr, long *size) +{ + char *buf = NULL; + int allocated = 1 * 1024 * 1024; + int len, filled = 0; + + if (!grub_open (name)) + return -1; + + buf = malloc(allocated); + + errnum = 0; + while (1) { + len = grub_read (buf + filled, allocated - filled); + if (! len) { + if (!errnum) + break; + grub_close (); + return -1; + } + filled += len; + if (filled < allocated) + break; + allocated *= 2; + buf = realloc(buf, allocated); + } + grub_close (); + *ptr = buf; + *size = filled; + return 0; +} + +void *kernel_image, *module_image; +long kernel_size, module_size; +char *kernel_arg, *module_arg; + +kernel_t +load_image (char *kernel, char *arg, kernel_t suggested_type, + unsigned long load_flags) +{ + arg = skip_to(0, arg); + if (kernel_image) + free(kernel_image); + kernel_image = NULL; + if (load_file (kernel, &kernel_image, &kernel_size)) + return KERNEL_TYPE_NONE; + if (kernel_arg) + free(kernel_arg); + kernel_arg = strdup(arg); + return KERNEL_TYPE_PV; +} + +int +load_initrd (char *initrd) +{ + if (module_image) + free(module_image); + module_image = NULL; + load_file (initrd, &module_image, &module_size); + return ! errnum; +} + +int +load_module (char *module, char *arg) +{ + if (module_image) + free(module_image); + module_image = NULL; + load_file (module, &module_image, &module_size); + if (module_arg) + free(module_arg); + module_arg = strdup(arg); + return ! errnum; +} + +void +pv_boot (void) +{ + kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg); +} + +/* + * Network + */ + +struct netfront_dev *net_dev; + +int +minios_probe (struct nic *nic) +{ + char *ip; + + if (net_dev) + return 1; + + /* Clear the ARP table. */ + grub_memset ((char *) arptable, 0, + MAX_ARP * sizeof (struct arptable_t)); + + net_dev = init_netfront(NULL, (void*) -1, nic->node_addr, &ip); + if (!net_dev) + return 0; + + return 1; +} + +/* reset adapter */ +static void minios_reset(struct nic *nic) +{ + /* TODO? */ +} + +static void minios_disable(struct nic *nic) +{ +} + +/* Wait for a frame */ +static int minios_poll(struct nic *nic) +{ + return !! (nic->packetlen = netfront_receive(net_dev, (void*) nic->packet, ETH_FRAME_LEN)); +} + +/* Transmit a frame */ +struct frame { + uint8_t dest[ETH_ALEN]; + uint8_t src[ETH_ALEN]; + uint16_t type; + unsigned char data[]; +}; +static void minios_transmit (struct nic *nic, const char *d, unsigned int t, + unsigned int s, const char *p) +{ + struct frame *frame = alloca(sizeof(frame) + s); + + memcpy(frame->dest, d, ETH_ALEN); + memcpy(frame->src, nic->node_addr, ETH_ALEN); + frame->type = htons(t); + memcpy(frame->data, p, s); + + netfront_xmit(net_dev, (void*) frame, sizeof(*frame) + s); +} + +static char packet[ETH_FRAME_LEN]; + +struct nic nic = { + .reset = minios_reset, + .poll = minios_poll, + .transmit = minios_transmit, + .disable = minios_disable, + .flags = 0, + .rom_info = NULL, + .node_addr = arptable[ARP_CLIENT].node, + .packet = packet, + .packetlen = 0, + .priv_data = NULL, +}; + +int +eth_probe (void) +{ + return minios_probe(&nic); +} + +int +eth_poll (void) +{ + return minios_poll (&nic); +} + +void +eth_disable (void) +{ + minios_disable (&nic); +} + +void +eth_transmit (const char *d, unsigned int t, + unsigned int s, const void *p) +{ + minios_transmit (&nic, d, t, s, p); + if (t == IP) + twiddle(); +} + +/* + * Console + */ +void +serial_hw_put (int _c) +{ + char c = _c; + console_print(&c, 1); +} + +int +serial_hw_fetch (void) +{ + char key; + + if (!xencons_ring_avail()) + return -1; + + read(STDIN_FILENO, &key, 1); + switch (key) { + case 0x7f: key = ''\b''; break; + } + return key; +} + +/* + * PVFB + */ +struct kbdfront_dev *kbd_dev; +struct fbfront_dev *fb_dev; +static union xenkbd_in_event ev; +static int has_ev; +int console_checkkey (void) +{ + if (has_ev) + return 1; + has_ev = kbdfront_receive(kbd_dev, &ev, 1); + return has_ev; +} + +/* static QWERTY layout, that''s what most PC BIOSes do anyway */ +static char linux2ascii[] = { + [ 1 ] = 27, + [ 2 ] = ''1'', + [ 3 ] = ''2'', + [ 4 ] = ''3'', + [ 5 ] = ''4'', + [ 6 ] = ''5'', + [ 7 ] = ''6'', + [ 8 ] = ''7'', + [ 9 ] = ''8'', + [ 10 ] = ''9'', + [ 11 ] = ''0'', + [ 12 ] = ''-'', + [ 13 ] = ''='', + [ 14 ] = ''\b'', + [ 15 ] = ''\t'', + [ 16 ] = ''q'', + [ 17 ] = ''w'', + [ 18 ] = ''e'', + [ 19 ] = ''r'', + [ 20 ] = ''t'', + [ 21 ] = ''y'', + [ 22 ] = ''u'', + [ 23 ] = ''i'', + [ 24 ] = ''o'', + [ 25 ] = ''p'', + [ 26 ] = ''['', + [ 27 ] = '']'', + [ 28 ] = ''\n'', + + [ 30 ] = ''a'', + [ 31 ] = ''s'', + [ 32 ] = ''d'', + [ 33 ] = ''f'', + [ 34 ] = ''g'', + [ 35 ] = ''h'', + [ 36 ] = ''j'', + [ 37 ] = ''k'', + [ 38 ] = ''l'', + [ 39 ] = '';'', + [ 40 ] = ''\'''', + [ 41 ] = ''`'', + + [ 43 ] = ''\\'', + [ 44 ] = ''z'', + [ 45 ] = ''x'', + [ 46 ] = ''c'', + [ 47 ] = ''v'', + [ 48 ] = ''b'', + [ 49 ] = ''n'', + [ 50 ] = ''m'', + [ 51 ] = '','', + [ 52 ] = ''.'', + [ 53 ] = ''/'', + + [ 55 ] = ''*'', + [ 57 ] = '' '', + + [ 71 ] = ''7'', + [ 72 ] = ''8'', + [ 73 ] = ''9'', + [ 74 ] = ''-'', + [ 75 ] = ''4'', + [ 76 ] = ''5'', + [ 77 ] = ''6'', + [ 78 ] = ''+'', + [ 79 ] = ''1'', + [ 80 ] = ''2'', + [ 81 ] = ''3'', + [ 82 ] = ''0'', + [ 83 ] = ''.'', + + [ 86 ] = ''<'', + + [ 96 ] = ''\n'', + + [ 98 ] = ''/'', + + [ 102 ] = 1, /* home */ + [ 103 ] = 16, /* up */ + [ 104 ] = 7, /* page up */ + [ 105 ] = 2, /* left */ + [ 106 ] = 6, /* right */ + [ 107 ] = 5, /* end */ + [ 108 ] = 14, /* down */ + [ 109 ] = 3, /* page down */ + + [ 111 ] = 4, /* delete */ +}; + +static char linux2ascii_shifted[] = { + [ 1 ] = 27, + [ 2 ] = ''!'', + [ 3 ] = ''@'', + [ 4 ] = ''#'', + [ 5 ] = ''$'', + [ 6 ] = ''%'', + [ 7 ] = ''^'', + [ 8 ] = ''&'', + [ 9 ] = ''*'', + [ 10 ] = ''('', + [ 11 ] = '')'', + [ 12 ] = ''_'', + [ 13 ] = ''+'', + [ 14 ] = ''\b'', + [ 15 ] = ''\t'', + [ 16 ] = ''Q'', + [ 17 ] = ''W'', + [ 18 ] = ''E'', + [ 19 ] = ''R'', + [ 20 ] = ''T'', + [ 21 ] = ''Y'', + [ 22 ] = ''U'', + [ 23 ] = ''I'', + [ 24 ] = ''O'', + [ 25 ] = ''P'', + [ 26 ] = ''{'', + [ 27 ] = ''}'', + [ 28 ] = ''\n'', + + [ 30 ] = ''A'', + [ 31 ] = ''S'', + [ 32 ] = ''D'', + [ 33 ] = ''F'', + [ 34 ] = ''G'', + [ 35 ] = ''H'', + [ 36 ] = ''J'', + [ 37 ] = ''K'', + [ 38 ] = ''L'', + [ 39 ] = '':'', + [ 40 ] = ''"'', + [ 41 ] = ''~'', + + [ 43 ] = ''|'', + [ 44 ] = ''Z'', + [ 45 ] = ''X'', + [ 46 ] = ''C'', + [ 47 ] = ''V'', + [ 48 ] = ''B'', + [ 49 ] = ''N'', + [ 50 ] = ''M'', + [ 51 ] = ''<'', + [ 52 ] = ''>'', + [ 53 ] = ''?'', + + [ 55 ] = ''*'', + [ 57 ] = '' '', + + [ 71 ] = ''7'', + [ 72 ] = ''8'', + [ 73 ] = ''9'', + [ 74 ] = ''-'', + [ 75 ] = ''4'', + [ 76 ] = ''5'', + [ 77 ] = ''6'', + [ 78 ] = ''+'', + [ 79 ] = ''1'', + [ 80 ] = ''2'', + [ 81 ] = ''3'', + [ 82 ] = ''0'', + [ 83 ] = ''.'', + + [ 86 ] = ''>'', + + [ 96 ] = ''\n'', + + [ 98 ] = ''/'', + + [ 102 ] = 1, /* home */ + [ 103 ] = 16, /* up */ + [ 104 ] = 7, /* page up */ + [ 105 ] = 2, /* left */ + [ 106 ] = 6, /* right */ + [ 107 ] = 5, /* end */ + [ 108 ] = 14, /* down */ + [ 109 ] = 3, /* page down */ + + [ 111 ] = 4, /* delete */ +}; + +int console_getkey (void) +{ + static int shift, control, alt, caps_lock; + + if (!has_ev) + has_ev = kbdfront_receive(kbd_dev, &ev, 1); + if (!has_ev) + return 0; + + has_ev = 0; + if (ev.type != XENKBD_TYPE_KEY) + return 0; + + if (ev.key.keycode == 42 || ev.key.keycode == 54) { + caps_lock = 0; + shift = ev.key.pressed; + return 0; + } + if (ev.key.keycode == 58) { + caps_lock ^= 1; + return 0; + } + if (ev.key.keycode == 29 || ev.key.keycode == 97) { + control = ev.key.pressed; + return 0; + } + if (ev.key.keycode == 56) { + alt = ev.key.pressed; + return 0; + } + + if (!ev.key.pressed) + return 0; + + if (ev.key.keycode < sizeof(linux2ascii) / sizeof(*linux2ascii)) { + char val; + if (shift || caps_lock) + val = linux2ascii_shifted[ev.key.keycode]; + else + val = linux2ascii[ev.key.keycode]; + if (control) + val &= ~0x60; + return val; + } + + return 0; +} + +static void kbd_thread(void *p) +{ + struct semaphore *sem = p; + + kbd_dev = init_kbdfront(NULL, 1); + up(sem); +} + +struct fbfront_dev *fb_open(void *fb, int width, int height, int depth) +{ + unsigned long *mfns; + int linesize = width * (depth / 8); + int memsize = linesize * height; + int numpages = (memsize + PAGE_SIZE - 1) / PAGE_SIZE; + DECLARE_MUTEX_LOCKED(sem); + int i; + + create_thread("kbdfront", kbd_thread, &sem); + + mfns = malloc(numpages * sizeof(*mfns)); + for (i = 0; i < numpages; i++) { + memset(fb + i * PAGE_SIZE, 0, PAGE_SIZE); + mfns[i] = virtual_to_mfn(fb + i * PAGE_SIZE); + } + fb_dev = init_fbfront(NULL, mfns, width, height, depth, linesize, numpages); + free(mfns); + + if (!fb_dev) + return NULL; + + down(&sem); + if (!kbd_dev) + return NULL; + + return fb_dev; +} + +void kbd_close(void *foo) +{ + shutdown_kbdfront(kbd_dev); + kbd_dev = NULL; +} + +void fb_close(void) +{ + create_thread("kbdfront close", kbd_close, NULL); + shutdown_fbfront(fb_dev); + fb_dev = NULL; +} + +/* + * Misc + */ + +int getrtsecs (void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + +int currticks (void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return ((tv.tv_sec * 1000000ULL + tv.tv_usec) * TICKS_PER_SEC) / 1000000; +} + +void __attribute__ ((noreturn)) grub_reboot (void) +{ + for ( ;; ) + { + struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_reboot }; + HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); + } +} + +#define SCRATCH_MEMSIZE (4 * 1024 * 1024) + +/* Note: not allocating it dynamically permits to make sure it lays below 4G + * for grub''s 32bit pointers to work */ +char grub_scratch_mem[SCRATCH_MEMSIZE] __attribute__((aligned(PAGE_SIZE))); + +int main(int argc, char *argv[]) +{ + if (argc > 1) { + strncpy(config_file, argv[1], sizeof(config_file) - 1); + config_file[sizeof(config_file) - 1] = 0; + if (!strncmp(config_file, "(nd)", 4)) + preset_menu = "dhcp"; + } else + preset_menu = "dhcp --with-configfile"; + + mbi.drives_addr = BOOTSEC_LOCATION + (60 * 1024); + mbi.drives_length = 0; + + mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION; + mbi.mem_lower = (start_info.nr_pages * PAGE_SIZE) / 1024; + mbi.mem_upper = 0; + saved_drive = boot_drive; + saved_partition = install_partition; + + init_disk(); + + /* Try to make sure the client part got launched */ + sleep(1); + cmain(); + printk("cmain returned!\n"); +} --- /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@lists.xensource.com http://lists.xensource.com/xen-devel