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,584 @@
+/*
+ * 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, see <http://www.gnu.org/licenses/>
+ */
+
+#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,43 @@
+/* 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, see <http://www.gnu.org/licenses/>
+ */
+
+#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 */
