--- grub-0.95/stage2/asm.S.graphics	2004-06-18 17:35:51.932054040 -0400
+++ grub-0.95/stage2/asm.S	2004-06-18 17:35:52.473971656 -0400
@@ -2215,6 +2215,156 @@
 	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
+
+	
+/*
+ * int set_videomode(mode)
+ * BIOS call "INT 10H Function 0h" to set video mode
+ *	Call with	%ah = 0x0
+ *			%al = video mode
+ *      Returns old videomode.
+ */
+ENTRY(set_videomode)
+	push	%ebp
+	push	%ebx
+	push	%ecx
+
+	movb	0x10(%esp), %cl
+
+	call	EXT_C(prot_to_real)
+	.code16
+
+	xorw	%bx, %bx
+	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
+
+	xorb	%ah, %ah
+	movb	%ch, %al
+
+	pop	%ecx
+	pop	%ebx
+	pop	%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()
--- grub-0.95/stage2/stage2.c.graphics	2004-06-18 17:35:52.314995824 -0400
+++ grub-0.95/stage2/stage2.c	2004-06-18 17:35:52.494968464 -0400
@@ -233,6 +233,7 @@
 {
   int c, time1, time2 = -1, first_entry = 0;
   char *cur_entry = 0;
+  struct term_entry *prev_term = NULL;
 
   /*
    *  Main loop for menu UI.
@@ -807,6 +808,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)
     {
@@ -838,6 +848,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;
 }
@@ -1082,6 +1099,10 @@
 	  while (is_preset);
 	}
 
+      /* go ahead and make sure the terminal is setup */
+      if (current_term->startup)
+        (*current_term->startup)();
+
       if (! num_entries)
 	{
 	  /* If no acceptable config file, goto command-line, starting
--- grub-0.95/stage2/builtins.c.graphics	2004-06-18 17:35:52.370987312 -0400
+++ grub-0.95/stage2/builtins.c	2004-06-18 17:35:52.482970288 -0400
@@ -858,6 +858,138 @@
 };
 #endif /* SUPPORT_NETBOOT */
 
+static int terminal_func (char *arg, int flags);
+
+#ifdef SUPPORT_GRAPHICS
+
+static int splashimage_func(char *arg, int flags) {
+    char splashimage[64];
+    int i;
+    
+    /* filename can only be 64 characters due to our buffer size */
+    if (strlen(arg) > 63)
+	return 1;
+    if (flags == BUILTIN_CMDLINE) {
+	if (!grub_open(arg))
+	    return 1;
+	grub_close();
+    }
+
+    strcpy(splashimage, arg);
+
+    /* 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(splashimage);
+
+    if (flags == BUILTIN_CMDLINE && graphics_inited) {
+	graphics_end();
+	graphics_init();
+	graphics_cls();
+    }
+
+    /* FIXME: should we be explicitly switching the terminal as a 
+     * side effect here? */
+    terminal_func("graphics", flags);
+
+    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."
+};
+
+
+/* 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."
+};
+
+#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
@@ -4090,7 +4222,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)
@@ -4249,17 +4381,21 @@
  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)
+      current_term->startup();
     grub_longjmp (restart_cmdline_env, 0);
+  }
   
   return 0;
 }
@@ -4269,7 +4405,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"
@@ -4281,7 +4417,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
@@ -4809,6 +4945,9 @@
 /* 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
@@ -4816,6 +4955,7 @@
 #endif /* SUPPORT_NETBOOT */
   &builtin_cat,
   &builtin_chainloader,
+  &builtin_clear,
   &builtin_cmp,
   &builtin_color,
   &builtin_configfile,
@@ -4835,6 +4975,9 @@
   &builtin_embed,
   &builtin_fallback,
   &builtin_find,
+#ifdef SUPPORT_GRAPHICS
+  &builtin_foreground,
+#endif
   &builtin_fstest,
   &builtin_geometry,
   &builtin_halt,
@@ -4878,9 +5021,12 @@
 #endif /* SUPPORT_SERIAL */
   &builtin_setkey,
   &builtin_setup,
-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
+#ifdef SUPPORT_GRAPHICS
+  &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 */
--- /dev/null	2004-02-23 16:02:56.000000000 -0500
+++ grub-0.95/stage2/graphics.c	2004-06-18 17:35:52.488969376 -0400
@@ -0,0 +1,552 @@
+/* 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>
+ */
+/*
+ *  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[64];
+
+#define VSHADOW VSHADOW1
+unsigned char VSHADOW1[38400];
+unsigned char VSHADOW2[38400];
+unsigned char VSHADOW4[38400];
+unsigned char VSHADOW8[38400];
+
+/* constants to define the viewable area */
+const int x0 = 0;
+const int x1 = 80;
+const int y0 = 0;
+const int 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];
+
+/* why do these have to be kept here? */
+int foreground = (63 << 16) | (63 << 8) | (63), background = 0, 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;
+
+
+/* graphics local functions */
+static void graphics_setxy(int col, int row);
+static void graphics_scroll();
+
+/* FIXME: where do these really belong? */
+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);
+}
+
+
+
+/* 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.  */
+int graphics_init()
+{
+    if (!graphics_inited) {
+        saved_videomode = set_videomode(0x12);
+    }
+
+    if (!read_image(splashimage)) {
+        set_videomode(saved_videomode);
+        grub_printf("failed to read image\n");
+        return 0;
+    }
+
+    font8x16 = (unsigned char*)graphics_get_font();
+
+    graphics_inited = 1;
+
+    /* make sure that the highlight color is set correctly */
+    graphics_highlight_color = ((graphics_normal_color >> 4) | 
+				((graphics_normal_color & 0xf) << 4));
+
+    return 1;
+}
+
+/* Leave graphics mode */
+void graphics_end(void)
+{
+    if (graphics_inited) {
+        set_videomode(saved_videomode);
+        graphics_inited = 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 < y1)
+            graphics_setxy(fontx, fonty + 1);
+        else
+            graphics_scroll();
+        graphics_cursor(1);
+        return;
+    } else if (ch == '\r') {
+        graphics_setxy(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) >= x1) {
+        graphics_setxy(x0, fonty);
+        if (fonty + 1 < y1)
+            graphics_setxy(x0, fonty + 1);
+        else
+            graphics_scroll();
+    } 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(x0, 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);
+
+    /* plano 1 */
+    MapMask(1);
+    grub_memcpy(mem, s1, 38400);
+
+    /* plano 2 */
+    MapMask(2);
+    grub_memcpy(mem, s2, 38400);
+
+    /* plano 3 */
+    MapMask(4);
+    grub_memcpy(mem, s4, 38400);
+
+    /* plano 4 */
+    MapMask(8);
+    grub_memcpy(mem, s8, 38400);
+
+    MapMask(15);
+ 
+}
+
+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);
+}
+
+void graphics_setcursor (int on) {
+    /* FIXME: we don't have a cursor in graphics */
+    return;
+}
+
+/* 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];
+    unsigned char c, 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, (border >> 16), (border >> 8) & 63, 
+                         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');
+}
+
+
+/* move the graphics cursor location to col, row */
+static void graphics_setxy(int col, int row) {
+    if (col >= x0 && col < x1) {
+        fontx = col;
+        cursorX = col << 3;
+    }
+    if (row >= y0 && row < y1) {
+        fonty = row;
+        cursorY = row << 4;
+    }
+}
+
+/* scroll the screen */
+static void graphics_scroll() {
+    int i, j;
+
+    /* we don't want to scroll recursively... that would be bad */
+    if (no_scroll)
+        return;
+    no_scroll = 1;
+
+    /* move everything up a line */
+    for (j = y0 + 1; j < y1; j++) {
+        graphics_gotoxy(x0, j - 1);
+        for (i = x0; i < x1; i++) {
+            graphics_putchar(text[j * 80 + i]);
+        }
+    }
+
+    /* last line should be blank */
+    graphics_gotoxy(x0, y1 - 1);
+    for (i = x0; i < x1; i++)
+        graphics_putchar(' ');
+    graphics_setxy(x0, y1 - 1);
+
+    no_scroll = 0;
+}
+
+
+void graphics_cursor(int set) {
+    unsigned char *pat, *mem, *ptr, chr[16 << 2];
+    int i, ch, invert, offset;
+
+    if (set && 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];
+
+                /* FIXME: if (shade) */
+                if (1) {
+                    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 */
--- grub-0.95/stage2/Makefile.am.graphics	2004-06-13 13:57:27.000000000 -0400
+++ grub-0.95/stage2/Makefile.am	2004-06-18 17:36:58.289966104 -0400
@@ -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 \
@@ -80,8 +80,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
@@ -91,7 +97,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)
--- grub-0.95/stage2/term.h.graphics	2003-07-09 07:45:53.000000000 -0400
+++ grub-0.95/stage2/term.h	2004-06-18 17:35:52.496968160 -0400
@@ -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,11 @@
   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 +131,23 @@
 int hercules_setcursor (int on);
 #endif
 
+#ifdef SUPPORT_GRAPHICS
+extern int foreground, background, border, graphics_inited;
+
+void graphics_set_splash(char *splashfile);
+int set_videomode (int mode);
+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);
+void 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	2004-02-23 16:02:56.000000000 -0500
+++ grub-0.95/stage2/graphics.h	2004-06-18 17:35:52.490969072 -0400
@@ -0,0 +1,42 @@
+/* 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];
+
+#endif /* GRAPHICS_H */
--- grub-0.95/stage2/shared.h.graphics	2004-06-18 17:35:52.372987008 -0400
+++ grub-0.95/stage2/shared.h	2004-06-18 17:35:52.492968768 -0400
@@ -873,6 +873,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);
--- grub-0.95/stage2/char_io.c.graphics	2004-05-23 12:45:43.000000000 -0400
+++ grub-0.95/stage2/char_io.c	2004-06-18 17:35:52.485969832 -0400
@@ -35,6 +35,7 @@
     {
       "console",
       0,
+      24,
       console_putchar,
       console_checkkey,
       console_getkey,
@@ -43,13 +44,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 +62,8 @@
       serial_cls,
       serial_setcolorstate,
       0,
+      0,
+      0, 
       0
     },
 #endif /* SUPPORT_SERIAL */
@@ -65,6 +71,7 @@
     {
       "hercules",
       0,
+      24,
       hercules_putchar,
       console_checkkey,
       console_getkey,
@@ -73,9 +80,28 @@
       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 }
   };
@@ -1046,13 +1072,15 @@
 		 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 ("\n[Hit return to continue]");
+	      grub_printf ("[Hit return to continue]");
 
 	      if (current_term->setcolorstate)
 		current_term->setcolorstate (COLOR_STATE_NORMAL);
+	        
 	      
 	      do
 		{
@@ -1090,7 +1118,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 ();
@@ -1214,6 +1242,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)
 {
--- grub-0.95/configure.ac.graphics	2004-06-18 17:35:52.211011632 -0400
+++ grub-0.95/configure.ac	2004-06-18 17:35:52.498967856 -0400
@@ -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])
