1diff -Naur grub-0.97.orig/configure.ac grub-0.97/configure.ac
2--- grub-0.97.orig/configure.ac	2005-05-07 23:36:03.000000000 -0300
3+++ grub-0.97/configure.ac	2005-06-12 20:56:49.000000000 -0300
4@@ -595,6 +595,11 @@
5   [  --enable-diskless       enable diskless support])
6 AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
7
8+dnl Graphical splashscreen support
9+AC_ARG_ENABLE(graphics,
10+  [  --disable-graphics      disable graphics terminal support])
11+AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
12+
13 dnl Hercules terminal
14 AC_ARG_ENABLE(hercules,
15   [  --disable-hercules      disable hercules terminal support])
16diff -Naur grub-0.97.orig/stage2/asm.S grub-0.97/stage2/asm.S
17--- grub-0.97.orig/stage2/asm.S	2004-06-19 13:55:22.000000000 -0300
18+++ grub-0.97/stage2/asm.S	2005-06-13 14:05:31.000000000 -0300
19@@ -2216,7 +2216,304 @@
20 	pop	%ebx
21 	pop	%ebp
22 	ret
23-
24+
25+
26+/* graphics mode functions */
27+#ifdef SUPPORT_GRAPHICS
28+VARIABLE(cursorX)
29+.word	0
30+VARIABLE(cursorY)
31+.word	0
32+VARIABLE(cursorCount)
33+.word 0
34+VARIABLE(cursorBuf)
35+.byte	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
36+
37+
38+/*
39+ * set_int1c_handler(void)
40+ */
41+ENTRY(set_int1c_handler)
42+	pushl   %edi
43+
44+	/* save the original int1c handler */
45+	movl    $0x70, %edi
46+	movw    (%edi), %ax
47+	movw    %ax, ABS(int1c_offset)
48+	movw    2(%edi), %ax
49+	movw    %ax, ABS(int1c_segment)
50+
51+	/* save the new int1c handler */
52+	movw    $ABS(int1c_handler), %ax
53+	movw    %ax, (%edi)
54+	xorw    %ax, %ax
55+	movw    %ax, 2(%edi)
56+
57+	popl    %edi
58+	ret
59+
60+
61+/*
62+ * unset_int1c_handler(void)
63+ */
64+ENTRY(unset_int1c_handler)
65+	pushl   %edi
66+
67+	/* check if int1c_handler is set */
68+	movl    $0x70, %edi
69+	movw    $ABS(int1c_handler), %ax
70+	cmpw    %ax, (%edi)
71+	jne     int1c_1
72+	xorw    %ax, %ax
73+	cmpw    %ax, 2(%edi)
74+	jne     int1c_1
75+
76+	/* restore the original */
77+	movw    ABS(int1c_offset), %ax
78+	movw    %ax, (%edi)
79+	movw    ABS(int1c_segment), %ax
80+	movw    %ax, 2(%edi)
81+
82+int1c_1:
83+	popl    %edi
84+	ret
85+
86+
87+/*
88+ * blinks graphics cursor
89+ */
90+	.code16
91+write_data:
92+	movw    $0, %ax
93+	movw    %ax, %ds
94+
95+	mov     $0xA000, %ax            /* video in es:di */
96+	mov     %ax, %es
97+	mov     $80, %ax
98+	movw    $ABS(cursorY), %si
99+	mov     %ds:(%si), %bx
100+	mul     %bx
101+	movw    $ABS(cursorX), %si
102+	mov     %ds:(%si), %bx
103+	shr     $3, %bx                 /* %bx /= 8 */
104+	add     %bx, %ax
105+	mov     %ax, %di
106+
107+	movw    $ABS(cursorBuf), %si    /* fontBuf in ds:si */
108+
109+	/* prepare for data moving */
110+	mov     $16, %dx                /* altura da fonte */
111+	mov     $80, %bx                /* bytes por linha */
112+
113+write_loop:
114+	movb    %ds:(%si), %al
115+	xorb    $0xff, %al
116+	movb    %al, %ds:(%si)          /* invert cursorBuf */
117+	movb    %al, %es:(%di)          /* write to video */
118+	add     %bx, %di
119+	inc     %si
120+	dec     %dx
121+	jg      write_loop
122+	ret
123+
124+int1c_handler:
125+	pusha
126+	mov     $0, %ax
127+	mov     %ax, %ds
128+	mov     $ABS(cursorCount), %si
129+	mov     %ds:(%si), %ax
130+	inc     %ax
131+	mov     %ax, %ds:(%si)
132+	cmp     $9, %ax
133+	jne     int1c_done
134+
135+	mov     $0, %ax
136+	mov     %ax, %ds:(%si)
137+	call    write_data
138+
139+int1c_done:
140+	popa
141+	iret
142+	/* call previous int1c handler */
143+	/* ljmp */
144+	.byte   0xea
145+int1c_offset:  .word   0
146+int1c_segment: .word   0
147+	.code32
148+
149+
150+/*
151+ * unsigned char set_videomode(unsigned char mode)
152+ * BIOS call "INT 10H Function 0h" to set video mode
153+ *	Call with	%ah = 0x0
154+ *			%al = video mode
155+ *  Returns old videomode.
156+ */
157+ENTRY(set_videomode)
158+	pushl	%ebp
159+	movl	%esp,%ebp
160+	pushl	%ebx
161+	pushl	%ecx
162+
163+	movb	8(%ebp), %cl
164+
165+	call	EXT_C(prot_to_real)
166+	.code16
167+
168+	xorb	%al, %al
169+	movb	$0xf, %ah
170+	int	$0x10			/* Get Current Video mode */
171+	movb	%al, %ch
172+	xorb	%ah, %ah
173+	movb	%cl, %al
174+	int	$0x10			/* Set Video mode */
175+
176+	DATA32	call	EXT_C(real_to_prot)
177+	.code32
178+
179+	xorl	%eax, %eax
180+	movb	%ch, %al
181+
182+	popl	%ecx
183+	popl	%ebx
184+	popl	%ebp
185+	ret
186+
187+
188+/*
189+ * int get_videomode()
190+ * BIOS call "INT 10H Function 0Fh" to get current video mode
191+ *	Call with	%al = 0x0
192+ *			%ah = 0xF
193+ *	Returns current videomode.
194+ */
195+ENTRY(get_videomode)
196+	pushl	%ebp
197+	movl	%esp,%ebp
198+	pushl	%ebx
199+	pushl	%ecx
200+
201+	call	EXT_C(prot_to_real)
202+	.code16
203+
204+	xorb	%al, %al
205+	movb	$0xF, %ah
206+	int	$0x10			/* Get Current Video mode */
207+	movb	%al, %cl	/* For now we only want display mode */
208+
209+	DATA32	call	EXT_C(real_to_prot)
210+	.code32
211+
212+	xorl	%eax, %eax
213+	movb	%cl, %al
214+
215+	popl	%ecx
216+	popl	%ebx
217+	popl	%ebp
218+	ret
219+
220+
221+/*
222+ * unsigned char * graphics_get_font()
223+ * BIOS call "INT 10H Function 11h" to set font
224+ *      Call with       %ah = 0x11
225+ */
226+ENTRY(graphics_get_font)
227+	push	%ebp
228+	push	%ebx
229+	push	%ecx
230+	push	%edx
231+
232+	call	EXT_C(prot_to_real)
233+	.code16
234+
235+	movw	$0x1130, %ax
236+	movb	$6, %bh		/* font 8x16 */
237+	int	$0x10
238+	movw	%bp, %dx
239+	movw	%es, %cx
240+
241+	DATA32	call	EXT_C(real_to_prot)
242+	.code32
243+
244+	xorl	%eax, %eax
245+	movw	%cx, %ax
246+	shll	$4, %eax
247+	movw	%dx, %ax
248+
249+	pop	%edx
250+	pop	%ecx
251+	pop	%ebx
252+	pop	%ebp
253+	ret
254+
255+
256+/*
257+ * graphics_set_palette(index, red, green, blue)
258+ * BIOS call "INT 10H Function 10h" to set individual dac register
259+ *	Call with	%ah = 0x10
260+ *			%bx = register number
261+ *			%ch = new value for green (0-63)
262+ *			%cl = new value for blue (0-63)
263+ *			%dh = new value for red (0-63)
264+ */
265+
266+ENTRY(graphics_set_palette)
267+	push	%ebp
268+	push	%eax
269+	push	%ebx
270+	push	%ecx
271+	push	%edx
272+
273+	movw	$0x3c8, %bx		/* address write mode register */
274+
275+	/* wait vertical retrace */
276+	movw	$0x3da, %dx
277+l1b:
278+	inb	%dx, %al	/* wait vertical active display */
279+	test	$8, %al
280+	jnz	l1b
281+
282+l2b:
283+	inb	%dx, %al	/* wait vertical retrace */
284+	test	$8, %al
285+	jnz	l2b
286+
287+	mov	%bx, %dx
288+	movb	0x18(%esp), %al		/* index */
289+	outb	%al, %dx
290+	inc	%dx
291+
292+	movb	0x1c(%esp), %al		/* red */
293+	outb	%al, %dx
294+
295+	movb	0x20(%esp), %al		/* green */
296+	outb	%al, %dx
297+
298+	movb	0x24(%esp), %al		/* blue */
299+	outb	%al, %dx
300+
301+	movw	0x18(%esp), %bx
302+
303+	call	EXT_C(prot_to_real)
304+	.code16
305+
306+	movb	%bl, %bh
307+	movw	$0x1000, %ax
308+	int	$0x10
309+
310+	DATA32	call	EXT_C(real_to_prot)
311+	.code32
312+
313+	pop	%edx
314+	pop	%ecx
315+	pop	%ebx
316+	pop	%eax
317+	pop	%ebp
318+	ret
319+#endif /* SUPPORT_GRAPHICS */
320+
321+
322 /*
323  * getrtsecs()
324  *	if a seconds value can be read, read it and return it (BCD),
325diff -Naur grub-0.97.orig/stage2/builtins.c grub-0.97/stage2/builtins.c
326--- grub-0.97.orig/stage2/builtins.c	2005-02-15 19:58:23.000000000 -0200
327+++ grub-0.97/stage2/builtins.c	2005-06-13 18:44:03.000000000 -0300
328@@ -28,6 +28,10 @@
329 #include <filesys.h>
330 #include <term.h>
331
332+#ifdef SUPPORT_GRAPHICS
333+# include <graphics.h>
334+#endif
335+
336 #ifdef SUPPORT_NETBOOT
337 # define GRUB	1
338 # include <etherboot.h>
339@@ -237,12 +241,22 @@
340 static int
341 boot_func (char *arg, int flags)
342 {
343+  struct term_entry *prev_term = current_term;
344   /* Clear the int15 handler if we can boot the kernel successfully.
345      This assumes that the boot code never fails only if KERNEL_TYPE is
346      not KERNEL_TYPE_NONE. Is this assumption is bad?  */
347   if (kernel_type != KERNEL_TYPE_NONE)
348     unset_int15_handler ();
349
350+  /* if our terminal needed initialization, we should shut it down
351+   * before booting the kernel, but we want to save what it was so
352+   * we can come back if needed */
353+  if (current_term->shutdown)
354+    {
355+      current_term->shutdown();
356+      current_term = term_table; /* assumption: console is first */
357+    }
358+
359 #ifdef SUPPORT_NETBOOT
360   /* Shut down the networking.  */
361   cleanup_net ();
362@@ -306,6 +320,13 @@
363       return 1;
364     }
365
366+  /* if we get back here, we should go back to what our term was before */
367+  current_term = prev_term;
368+  if (current_term->startup)
369+      /* if our terminal fails to initialize, fall back to console since
370+       * it should always work */
371+      if (current_term->startup() == 0)
372+          current_term = term_table; /* we know that console is first */
373   return 0;
374 }
375
376@@ -852,6 +873,251 @@
377 };
378 #endif /* SUPPORT_NETBOOT */
379
380+#ifdef SUPPORT_GRAPHICS
381+
382+static int splashimage_func(char *arg, int flags) {
383+  int i;
384+
385+  /* filename can only be 256 characters due to our buffer size */
386+  if (grub_strlen(arg) > 256) {
387+    grub_printf("Splash image filename too large\n");
388+    grub_printf("Press any key to continue...");
389+    getkey();
390+    return 1;
391+  }
392+
393+  /* get rid of TERM_NEED_INIT from the graphics terminal. */
394+  for (i = 0; term_table[i].name; i++) {
395+    if (grub_strcmp (term_table[i].name, "graphics") == 0) {
396+      term_table[i].flags &= ~TERM_NEED_INIT;
397+      break;
398+    }
399+  }
400+
401+  graphics_set_splash(arg);
402+
403+  if (flags == BUILTIN_CMDLINE && graphics_inited) {
404+    graphics_end();
405+    if (graphics_init() == 0) {
406+      /* Fallback to default term */
407+      current_term = term_table;
408+      max_lines = current_term->max_lines;
409+      if (current_term->cls)
410+        current_term->cls();
411+      grub_printf("Failed to set splash image and/or graphics mode\n");
412+      return 1;
413+    }
414+    graphics_cls();
415+  }
416+
417+  if (flags == BUILTIN_MENU)
418+    current_term = term_table + i;
419+
420+  return 0;
421+}
422+
423+static struct builtin builtin_splashimage =
424+{
425+  "splashimage",
426+  splashimage_func,
427+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
428+  "splashimage FILE",
429+  "Load FILE as the background image when in graphics mode."
430+};
431+
432+
433+/* shade */
434+static int
435+shade_func(char *arg, int flags)
436+{
437+    int new_shade;
438+
439+    if (!arg || safe_parse_maxint(&arg, &new_shade) == 0)
440+       return (1);
441+
442+    if (shade != new_shade) {
443+       shade = new_shade;
444+       if (flags == BUILTIN_CMDLINE && graphics_inited) {
445+           graphics_end();
446+           graphics_init();
447+           graphics_cls();
448+       }
449+    }
450+
451+    return 0;
452+}
453+
454+static struct builtin builtin_shade =
455+{
456+  "shade",
457+  shade_func,
458+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
459+  "shade INTEGER",
460+  "If set to 0, disables the use of shaded text, else enables it."
461+};
462+
463+
464+/* foreground */
465+static int
466+foreground_func(char *arg, int flags)
467+{
468+    if (grub_strlen(arg) == 6) {
469+	int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
470+	int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
471+	int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
472+
473+	foreground = (r << 16) | (g << 8) | b;
474+	if (graphics_inited)
475+	    graphics_set_palette(15, r, g, b);
476+
477+	return 0;
478+    }
479+
480+    return 1;
481+}
482+
483+static struct builtin builtin_foreground =
484+{
485+  "foreground",
486+  foreground_func,
487+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
488+  "foreground RRGGBB",
489+  "Sets the foreground color when in graphics mode."
490+  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
491+};
492+
493+
494+/* background */
495+static int
496+background_func(char *arg, int flags)
497+{
498+    if (grub_strlen(arg) == 6) {
499+	int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
500+	int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
501+	int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
502+
503+	background = (r << 16) | (g << 8) | b;
504+	if (graphics_inited)
505+	    graphics_set_palette(0, r, g, b);
506+	return 0;
507+    }
508+
509+    return 1;
510+}
511+
512+static struct builtin builtin_background =
513+{
514+  "background",
515+  background_func,
516+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
517+  "background RRGGBB",
518+  "Sets the background color when in graphics mode."
519+  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
520+};
521+
522+
523+/* border */
524+static int
525+border_func(char *arg, int flags)
526+{
527+    if (grub_strlen(arg) == 6) {
528+       int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
529+       int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
530+       int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
531+
532+       window_border = (r << 16) | (g << 8) | b;
533+       if (graphics_inited)
534+           graphics_set_palette(0x11, r, g, b);
535+
536+       return 0;
537+    }
538+
539+    return 1;
540+}
541+
542+static struct builtin builtin_border =
543+{
544+  "border",
545+  border_func,
546+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
547+  "border RRGGBB",
548+  "Sets the border video color when in graphics mode."
549+  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
550+};
551+
552+
553+/* viewport */
554+static int
555+viewport_func (char *arg, int flags)
556+{
557+    int i;
558+    int x0 = 0, y0 = 0, x1 = 80, y1 = 30;
559+    int *pos[4] = { &x0, &y0, &x1, &y1 };
560+
561+    if (!arg)
562+       return (1);
563+    for (i = 0; i < 4; i++) {
564+       if (!*arg)
565+           return (1);
566+    while (*arg && (*arg == ' ' || *arg == '\t'))
567+           ++arg;
568+       if (!safe_parse_maxint(&arg, pos[i]))
569+           return (1);
570+       while (*arg && (*arg != ' ' && *arg != '\t'))
571+           ++arg;
572+    }
573+
574+    /* minimum size is 65 colums and 16 rows */
575+    if (x0 > x1 - 66 || y0 > y1 - 16 || x0 < 0 || y0 < 0 || x1 > 80 || y1 > 30)
576+       return 1;
577+
578+    view_x0 = x0;
579+    view_y0 = y0;
580+    view_x1 = x1;
581+    view_y1 = y1;
582+
583+    if (flags == BUILTIN_CMDLINE && graphics_inited) {
584+       graphics_end();
585+       graphics_init();
586+       graphics_cls();
587+    }
588+
589+    return 0;
590+}
591+
592+static struct builtin builtin_viewport =
593+{
594+  "viewport",
595+  viewport_func,
596+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
597+  "viewport x0 y0 x1 y1",
598+  "Changes grub internals to output text in the window defined by"
599+  " four parameters. The x and y parameters are 0 based. This option"
600+  " only works with the graphics interface."
601+};
602+
603+#endif /* SUPPORT_GRAPHICS */
604+
605+
606+/* clear */
607+static int
608+clear_func()
609+{
610+  if (current_term->cls)
611+    current_term->cls();
612+
613+  return 0;
614+}
615+
616+static struct builtin builtin_clear =
617+{
618+  "clear",
619+  clear_func,
620+  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
621+  "clear",
622+  "Clear the screen"
623+};
624+
625
626 /* displayapm */
627 static int
628@@ -1454,14 +1720,20 @@
629
630
631 /* help */
632-#define MAX_SHORT_DOC_LEN	39
633-#define MAX_LONG_DOC_LEN	66
634-
635 static int
636 help_func (char *arg, int flags)
637 {
638-  int all = 0;
639-
640+  int all = 0, max_short_doc_len, max_long_doc_len;
641+  max_short_doc_len = 39;
642+  max_long_doc_len = 66;
643+#ifdef SUPPORT_GRAPHICS
644+  if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
645+    {
646+      max_short_doc_len = (view_x1 - view_x0 + 1) / 2 - 1;
647+      max_long_doc_len = (view_x1 - view_x0) - 14;
648+    }
649+#endif
650+
651   if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
652     {
653       all = 1;
654@@ -1491,13 +1763,13 @@
655
656 	  len = grub_strlen ((*builtin)->short_doc);
657 	  /* If the length of SHORT_DOC is too long, truncate it.  */
658-	  if (len > MAX_SHORT_DOC_LEN - 1)
659-	    len = MAX_SHORT_DOC_LEN - 1;
660+	  if (len > max_short_doc_len - 1)
661+	    len = max_short_doc_len - 1;
662
663 	  for (i = 0; i < len; i++)
664 	    grub_putchar ((*builtin)->short_doc[i]);
665
666-	  for (; i < MAX_SHORT_DOC_LEN; i++)
667+	  for (; i < max_short_doc_len; i++)
668 	    grub_putchar (' ');
669
670 	  if (! left)
671@@ -1546,10 +1818,10 @@
672 		      int i;
673
674 		      /* If LEN is too long, fold DOC.  */
675-		      if (len > MAX_LONG_DOC_LEN)
676+		      if (len > max_long_doc_len)
677 			{
678 			  /* Fold this line at the position of a space.  */
679-			  for (len = MAX_LONG_DOC_LEN; len > 0; len--)
680+			  for (len = max_long_doc_len; len > 0; len--)
681 			    if (doc[len - 1] == ' ')
682 			      break;
683 			}
684@@ -4085,7 +4357,7 @@
685 };
686
687
688-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
689+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
690 /* terminal */
691 static int
692 terminal_func (char *arg, int flags)
693@@ -4244,17 +4516,29 @@
694  end:
695   current_term = term_table + default_term;
696   current_term->flags = term_flags;
697-
698+
699   if (lines)
700     max_lines = lines;
701   else
702-    /* 24 would be a good default value.  */
703-    max_lines = 24;
704-
705+    max_lines = current_term->max_lines;
706+
707   /* If the interface is currently the command-line,
708      restart it to repaint the screen.  */
709-  if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
710+  if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
711+    if (prev_term->shutdown)
712+      prev_term->shutdown();
713+    if (current_term->startup) {
714+      /* If startup fails, return to previous term */
715+      if (current_term->startup() == 0) {
716+        current_term = prev_term;
717+        max_lines = current_term->max_lines;
718+        if (current_term->cls) {
719+          current_term->cls();
720+        }
721+      }
722+    }
723     grub_longjmp (restart_cmdline_env, 0);
724+  }
725
726   return 0;
727 }
728@@ -4264,7 +4548,7 @@
729   "terminal",
730   terminal_func,
731   BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
732-  "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
733+  "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]",
734   "Select a terminal. When multiple terminals are specified, wait until"
735   " you push any key to continue. If both console and serial are specified,"
736   " the terminal to which you input a key first will be selected. If no"
737@@ -4276,7 +4560,7 @@
738   " seconds. The option --lines specifies the maximum number of lines."
739   " The option --silent is used to suppress messages."
740 };
741-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
742+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
743
744
745 #ifdef SUPPORT_SERIAL
746@@ -4795,13 +5079,20 @@
747 /* The table of builtin commands. Sorted in dictionary order.  */
748 struct builtin *builtin_table[] =
749 {
750+#ifdef SUPPORT_GRAPHICS
751+  &builtin_background,
752+#endif
753   &builtin_blocklist,
754   &builtin_boot,
755 #ifdef SUPPORT_NETBOOT
756   &builtin_bootp,
757 #endif /* SUPPORT_NETBOOT */
758+#ifdef SUPPORT_GRAPHICS
759+  &builtin_border,
760+#endif
761   &builtin_cat,
762   &builtin_chainloader,
763+  &builtin_clear,
764   &builtin_cmp,
765   &builtin_color,
766   &builtin_configfile,
767@@ -4821,6 +5112,9 @@
768   &builtin_embed,
769   &builtin_fallback,
770   &builtin_find,
771+#ifdef SUPPORT_GRAPHICS
772+  &builtin_foreground,
773+#endif
774   &builtin_fstest,
775   &builtin_geometry,
776   &builtin_halt,
777@@ -4864,9 +5158,13 @@
778 #endif /* SUPPORT_SERIAL */
779   &builtin_setkey,
780   &builtin_setup,
781-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
782+#ifdef SUPPORT_GRAPHICS
783+  &builtin_shade,
784+  &builtin_splashimage,
785+#endif /* SUPPORT_GRAPHICS */
786+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
787   &builtin_terminal,
788-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
789+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
790 #ifdef SUPPORT_SERIAL
791   &builtin_terminfo,
792 #endif /* SUPPORT_SERIAL */
793@@ -4880,5 +5178,8 @@
794   &builtin_unhide,
795   &builtin_uppermem,
796   &builtin_vbeprobe,
797+#ifdef SUPPORT_GRAPHICS
798+  &builtin_viewport,
799+#endif
800   0
801 };
802diff -Naur grub-0.97.orig/stage2/char_io.c grub-0.97/stage2/char_io.c
803--- grub-0.97.orig/stage2/char_io.c	2005-02-01 18:51:23.000000000 -0200
804+++ grub-0.97/stage2/char_io.c	2005-06-12 20:56:49.000000000 -0300
805@@ -29,12 +29,17 @@
806 # include <serial.h>
807 #endif
808
809+#ifdef SUPPORT_GRAPHICS
810+# include <graphics.h>
811+#endif
812+
813 #ifndef STAGE1_5
814 struct term_entry term_table[] =
815   {
816     {
817       "console",
818       0,
819+      24,
820       console_putchar,
821       console_checkkey,
822       console_getkey,
823@@ -43,13 +48,16 @@
824       console_cls,
825       console_setcolorstate,
826       console_setcolor,
827-      console_setcursor
828+      console_setcursor,
829+      0,
830+      0
831     },
832 #ifdef SUPPORT_SERIAL
833     {
834       "serial",
835       /* A serial device must be initialized.  */
836       TERM_NEED_INIT,
837+      24,
838       serial_putchar,
839       serial_checkkey,
840       serial_getkey,
841@@ -58,6 +66,8 @@
842       serial_cls,
843       serial_setcolorstate,
844       0,
845+      0,
846+      0,
847       0
848     },
849 #endif /* SUPPORT_SERIAL */
850@@ -65,6 +75,7 @@
851     {
852       "hercules",
853       0,
854+      24,
855       hercules_putchar,
856       console_checkkey,
857       console_getkey,
858@@ -73,11 +84,30 @@
859       hercules_cls,
860       hercules_setcolorstate,
861       hercules_setcolor,
862-      hercules_setcursor
863+      hercules_setcursor,
864+      0,
865+      0
866     },
867 #endif /* SUPPORT_HERCULES */
868+#ifdef SUPPORT_GRAPHICS
869+    { "graphics",
870+      TERM_NEED_INIT, /* flags */
871+      30, /* number of lines */
872+      graphics_putchar, /* putchar */
873+      console_checkkey, /* checkkey */
874+      console_getkey, /* getkey */
875+      graphics_getxy, /* getxy */
876+      graphics_gotoxy, /* gotoxy */
877+      graphics_cls, /* cls */
878+      graphics_setcolorstate, /* setcolorstate */
879+      graphics_setcolor, /* setcolor */
880+      graphics_setcursor, /* nocursor */
881+      graphics_init, /* initialize */
882+      graphics_end /* shutdown */
883+    },
884+#endif /* SUPPORT_GRAPHICS */
885     /* This must be the last entry.  */
886-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
887+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
888   };
889
890 /* This must be console.  */
891@@ -305,9 +335,10 @@
892
893   /* XXX: These should be defined in shared.h, but I leave these here,
894      until this code is freezed.  */
895-#define CMDLINE_WIDTH	78
896 #define CMDLINE_MARGIN	10
897-
898+
899+  /* command-line limits */
900+  int cmdline_width = 78, col_start = 0;
901   int xpos, lpos, c, section;
902   /* The length of PROMPT.  */
903   int plen;
904@@ -338,7 +369,7 @@
905
906       /* If the cursor is in the first section, display the first section
907 	 instead of the second.  */
908-      if (section == 1 && plen + lpos < CMDLINE_WIDTH)
909+      if (section == 1 && plen + lpos < cmdline_width)
910 	cl_refresh (1, 0);
911       else if (xpos - count < 1)
912 	cl_refresh (1, 0);
913@@ -354,7 +385,7 @@
914 		grub_putchar ('\b');
915 	    }
916 	  else
917-	    gotoxy (xpos, getxy () & 0xFF);
918+	    gotoxy (xpos + col_start, getxy () & 0xFF);
919 	}
920     }
921
922@@ -364,7 +395,7 @@
923       lpos += count;
924
925       /* If the cursor goes outside, scroll the screen to the right.  */
926-      if (xpos + count >= CMDLINE_WIDTH)
927+      if (xpos + count >= cmdline_width)
928 	cl_refresh (1, 0);
929       else
930 	{
931@@ -383,7 +414,7 @@
932 		}
933 	    }
934 	  else
935-	    gotoxy (xpos, getxy () & 0xFF);
936+	    gotoxy (xpos + col_start, getxy () & 0xFF);
937 	}
938     }
939
940@@ -398,14 +429,14 @@
941       if (full)
942 	{
943 	  /* Recompute the section number.  */
944-	  if (lpos + plen < CMDLINE_WIDTH)
945+	  if (lpos + plen < cmdline_width)
946 	    section = 0;
947 	  else
948-	    section = ((lpos + plen - CMDLINE_WIDTH)
949-		       / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
950+	    section = ((lpos + plen - cmdline_width)
951+		       / (cmdline_width - 1 - CMDLINE_MARGIN) + 1);
952
953 	  /* From the start to the end.  */
954-	  len = CMDLINE_WIDTH;
955+	  len = cmdline_width;
956 	  pos = 0;
957 	  grub_putchar ('\r');
958
959@@ -445,8 +476,8 @@
960 	  if (! full)
961 	    offset = xpos - 1;
962
963-	  start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
964-		   + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
965+	  start = ((section - 1) * (cmdline_width - 1 - CMDLINE_MARGIN)
966+		   + cmdline_width - plen - CMDLINE_MARGIN);
967 	  xpos = lpos + 1 - start;
968 	  start += offset;
969 	}
970@@ -471,7 +502,7 @@
971
972       /* If the cursor is at the last position, put `>' or a space,
973 	 depending on if there are more characters in BUF.  */
974-      if (pos == CMDLINE_WIDTH)
975+      if (pos == cmdline_width)
976 	{
977 	  if (start + len < llen)
978 	    grub_putchar ('>');
979@@ -488,7 +519,7 @@
980 	    grub_putchar ('\b');
981 	}
982       else
983-	gotoxy (xpos, getxy () & 0xFF);
984+	gotoxy (xpos + col_start, getxy () & 0xFF);
985     }
986
987   /* Initialize the command-line.  */
988@@ -518,10 +549,10 @@
989
990 	  llen += l;
991 	  lpos += l;
992-	  if (xpos + l >= CMDLINE_WIDTH)
993+	  if (xpos + l >= cmdline_width)
994 	    cl_refresh (1, 0);
995-	  else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
996-	    cl_refresh (0, CMDLINE_WIDTH - xpos);
997+	  else if (xpos + l + llen - lpos > cmdline_width)
998+	    cl_refresh (0, cmdline_width - xpos);
999 	  else
1000 	    cl_refresh (0, l + llen - lpos);
1001 	}
1002@@ -533,12 +564,22 @@
1003       grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
1004       llen -= count;
1005
1006-      if (xpos + llen + count - lpos > CMDLINE_WIDTH)
1007-	cl_refresh (0, CMDLINE_WIDTH - xpos);
1008+      if (xpos + llen + count - lpos > cmdline_width)
1009+	cl_refresh (0, cmdline_width - xpos);
1010       else
1011 	cl_refresh (0, llen + count - lpos);
1012     }
1013
1014+  max_lines = current_term->max_lines;
1015+#ifdef SUPPORT_GRAPHICS
1016+  if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
1017+    {
1018+      cmdline_width = (view_x1 - view_x0) - 2;
1019+      col_start = view_x0;
1020+      max_lines = view_y1 - view_y0;
1021+    }
1022+#endif
1023+
1024   plen = grub_strlen (prompt);
1025   llen = grub_strlen (cmdline);
1026
1027@@ -1006,6 +1047,48 @@
1028 }
1029 #endif /* ! STAGE1_5 */
1030
1031+#ifndef STAGE1_5
1032+/* Internal pager.  */
1033+int
1034+do_more (void)
1035+{
1036+  if (count_lines >= 0)
1037+    {
1038+      count_lines++;
1039+      if (count_lines >= max_lines - 2)
1040+        {
1041+          int tmp;
1042+
1043+          /* It's important to disable the feature temporarily, because
1044+             the following grub_printf call will print newlines.  */
1045+          count_lines = -1;
1046+
1047+          grub_printf("\n");
1048+          if (current_term->setcolorstate)
1049+            current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
1050+
1051+          grub_printf ("[Hit return to continue]");
1052+
1053+          if (current_term->setcolorstate)
1054+            current_term->setcolorstate (COLOR_STATE_NORMAL);
1055+
1056+
1057+          do
1058+            {
1059+              tmp = ASCII_CHAR (getkey ());
1060+            }
1061+          while (tmp != '\n' && tmp != '\r');
1062+          grub_printf ("\r                        \r");
1063+
1064+          /* Restart to count lines.  */
1065+          count_lines = 0;
1066+          return 1;
1067+        }
1068+    }
1069+  return 0;
1070+}
1071+#endif
1072+
1073 /* Display an ASCII character.  */
1074 void
1075 grub_putchar (int c)
1076@@ -1034,38 +1117,11 @@
1077
1078   if (c == '\n')
1079     {
1080+      int flag;
1081       /* Internal `more'-like feature.  */
1082-      if (count_lines >= 0)
1083-	{
1084-	  count_lines++;
1085-	  if (count_lines >= max_lines - 2)
1086-	    {
1087-	      int tmp;
1088-
1089-	      /* It's important to disable the feature temporarily, because
1090-		 the following grub_printf call will print newlines.  */
1091-	      count_lines = -1;
1092-
1093-	      if (current_term->setcolorstate)
1094-		current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
1095-
1096-	      grub_printf ("\n[Hit return to continue]");
1097-
1098-	      if (current_term->setcolorstate)
1099-		current_term->setcolorstate (COLOR_STATE_NORMAL);
1100-
1101-	      do
1102-		{
1103-		  tmp = ASCII_CHAR (getkey ());
1104-		}
1105-	      while (tmp != '\n' && tmp != '\r');
1106-	      grub_printf ("\r                        \r");
1107-
1108-	      /* Restart to count lines.  */
1109-	      count_lines = 0;
1110-	      return;
1111-	    }
1112-	}
1113+      flag = do_more ();
1114+      if (flag)
1115+        return;
1116     }
1117
1118   current_term->putchar (c);
1119@@ -1090,7 +1146,7 @@
1120 cls (void)
1121 {
1122   /* If the terminal is dumb, there is no way to clean the terminal.  */
1123-  if (current_term->flags & TERM_DUMB)
1124+  if (current_term->flags & TERM_DUMB)
1125     grub_putchar ('\n');
1126   else
1127     current_term->cls ();
1128@@ -1217,6 +1273,16 @@
1129   return ! errnum;
1130 }
1131
1132+void
1133+grub_memcpy(void *dest, const void *src, int len)
1134+{
1135+  int i;
1136+  register char *d = (char*)dest, *s = (char*)src;
1137+
1138+  for (i = 0; i < len; i++)
1139+    d[i] = s[i];
1140+}
1141+
1142 void *
1143 grub_memmove (void *to, const void *from, int len)
1144 {
1145diff -Naur grub-0.97.orig/stage2/cmdline.c grub-0.97/stage2/cmdline.c
1146--- grub-0.97.orig/stage2/cmdline.c	2004-08-16 20:23:01.000000000 -0300
1147+++ grub-0.97/stage2/cmdline.c	2005-06-12 20:56:49.000000000 -0300
1148@@ -50,10 +50,11 @@
1149 void
1150 print_cmdline_message (int forever)
1151 {
1152-  printf (" [ Minimal BASH-like line editing is supported.  For the first word, TAB\n"
1153-	  "   lists possible command completions.  Anywhere else TAB lists the possible\n"
1154-	  "   completions of a device/filename.%s ]\n",
1155-	  (forever ? "" : "  ESC at any time exits."));
1156+  grub_printf("       [ Minimal BASH-like line editing is supported.   For\n"
1157+              "         the   first   word,  TAB  lists  possible  command\n"
1158+              "         completions.  Anywhere else TAB lists the possible\n"
1159+              "         completions of a device/filename.%s ]\n",
1160+              (forever ? "" : "  ESC at any time\n         exits."));
1161 }
1162
1163 /* Find the builtin whose command name is COMMAND and return the
1164diff -Naur grub-0.97.orig/stage2/graphics.c grub-0.97/stage2/graphics.c
1165--- grub-0.97.orig/stage2/graphics.c	1969-12-31 21:00:00.000000000 -0300
1166+++ grub-0.97/stage2/graphics.c	2005-06-13 19:13:31.000000000 -0300
1167@@ -0,0 +1,584 @@
1168+/*
1169+ * graphics.c - graphics mode support for GRUB
1170+ * Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
1171+ * on a patch by Paulo C�sar Pereira de Andrade <pcpa@conectiva.com.br>
1172+ * Options and enhancements made by Herton Ronaldo Krzesinski
1173+ * <herton@mandriva.com>
1174+ *
1175+ *  GRUB  --  GRand Unified Bootloader
1176+ *  Copyright (C) 2001,2002  Red Hat, Inc.
1177+ *  Portions copyright (C) 2000  Conectiva, Inc.
1178+ *
1179+ *  This program is free software; you can redistribute it and/or modify
1180+ *  it under the terms of the GNU General Public License as published by
1181+ *  the Free Software Foundation; either version 2 of the License, or
1182+ *  (at your option) any later version.
1183+ *
1184+ *  This program is distributed in the hope that it will be useful,
1185+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1186+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1187+ *  GNU General Public License for more details.
1188+ *
1189+ *  You should have received a copy of the GNU General Public License
1190+ *  along with this program; If not, see <http://www.gnu.org/licenses/>
1191+ */
1192+
1193+#ifdef SUPPORT_GRAPHICS
1194+
1195+#include <term.h>
1196+#include <shared.h>
1197+#include <graphics.h>
1198+
1199+int saved_videomode;
1200+unsigned char *font8x16;
1201+
1202+int graphics_inited = 0;
1203+static char splashimage[256];
1204+
1205+int shade = 1, no_cursor = 0;
1206+
1207+#define VSHADOW VSHADOW1
1208+unsigned char VSHADOW1[38400];
1209+unsigned char VSHADOW2[38400];
1210+unsigned char VSHADOW4[38400];
1211+unsigned char VSHADOW8[38400];
1212+
1213+/* define the default viewable area */
1214+int view_x0 = 0;
1215+int view_y0 = 0;
1216+int view_x1 = 80;
1217+int view_y1 = 30;
1218+
1219+/* text buffer has to be kept around so that we can write things as we
1220+ * scroll and the like */
1221+unsigned short text[80 * 30];
1222+
1223+/* graphics options */
1224+int foreground = (63 << 16) | (63 << 8) | (63), background = 0, window_border = 0;
1225+
1226+/* current position */
1227+static int fontx = 0;
1228+static int fonty = 0;
1229+
1230+/* global state so that we don't try to recursively scroll or cursor */
1231+static int no_scroll = 0;
1232+
1233+/* color state */
1234+static int graphics_standard_color = A_NORMAL;
1235+static int graphics_normal_color = A_NORMAL;
1236+static int graphics_highlight_color = A_REVERSE;
1237+static int graphics_current_color = A_NORMAL;
1238+static color_state graphics_color_state = COLOR_STATE_STANDARD;
1239+
1240+static inline void outb(unsigned short port, unsigned char val)
1241+{
1242+    __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
1243+}
1244+
1245+static void MapMask(int value) {
1246+    outb(0x3c4, 2);
1247+    outb(0x3c5, value);
1248+}
1249+
1250+/* bit mask register */
1251+static void BitMask(int value) {
1252+    outb(0x3ce, 8);
1253+    outb(0x3cf, value);
1254+}
1255+
1256+/* move the graphics cursor location to col, row */
1257+static void graphics_setxy(int col, int row) {
1258+    if (col >= view_x0 && col < view_x1) {
1259+        fontx = col;
1260+        cursorX = col << 3;
1261+    }
1262+    if (row >= view_y0 && row < view_y1) {
1263+        fonty = row;
1264+        cursorY = row << 4;
1265+    }
1266+}
1267+
1268+/* scroll the screen */
1269+static void graphics_scroll() {
1270+    int i, j, k;
1271+
1272+    /* we don't want to scroll recursively... that would be bad */
1273+    if (no_scroll)
1274+        return;
1275+    no_scroll = 1;
1276+
1277+    /* disable pager temporarily */
1278+    k = count_lines;
1279+    count_lines = -1;
1280+
1281+    /* move everything up a line */
1282+    for (j = view_y0 + 1; j < view_y1; j++) {
1283+        graphics_gotoxy(view_x0, j - 1);
1284+        for (i = view_x0; i < view_x1; i++) {
1285+            graphics_putchar(text[j * 80 + i]);
1286+        }
1287+    }
1288+
1289+    /* last line should be blank */
1290+    graphics_gotoxy(view_x0, view_y1 - 1);
1291+    for (i = view_x0; i < view_x1; i++)
1292+        graphics_putchar(' ');
1293+    graphics_setxy(view_x0, view_y1 - 1);
1294+
1295+    count_lines = k;
1296+
1297+    no_scroll = 0;
1298+}
1299+
1300+/* Set the splash image */
1301+void graphics_set_splash(char *splashfile) {
1302+    grub_strcpy(splashimage, splashfile);
1303+}
1304+
1305+/* Get the current splash image */
1306+char *graphics_get_splash(void) {
1307+    return splashimage;
1308+}
1309+
1310+/*
1311+ * Initialize a vga16 graphics display with the palette based off of
1312+ * the image in splashimage.  If the image doesn't exist, leave graphics
1313+ * mode. The mode initiated is 12h. From "Ralf Brown's Interrupt List":
1314+ *      text/ text pixel   pixel   colors disply scrn  system
1315+ *      grph resol  box  resolution       pages  addr
1316+ * 12h   G   80x30  8x16  640x480  16/256K  .    A000  VGA,ATI VIP
1317+ *       G   80x30  8x16  640x480  16/64    .    A000  ATI EGA Wonder
1318+ *       G     .     .    640x480  16       .      .   UltraVision+256K EGA
1319+ */
1320+int graphics_init()
1321+{
1322+    if (!graphics_inited) {
1323+        saved_videomode = set_videomode(0x12);
1324+        if (get_videomode() != 0x12) {
1325+            set_videomode(saved_videomode);
1326+            return 0;
1327+        }
1328+        graphics_inited = 1;
1329+    }
1330+    else
1331+        return 1;
1332+
1333+    font8x16 = (unsigned char*)graphics_get_font();
1334+
1335+    /* make sure that the highlight color is set correctly */
1336+    graphics_highlight_color = ((graphics_normal_color >> 4) |
1337+                                ((graphics_normal_color & 0xf) << 4));
1338+
1339+    graphics_cls();
1340+
1341+    if (!read_image(splashimage)) {
1342+        grub_printf("Failed to read splash image (%s)\n", splashimage);
1343+        grub_printf("Press any key to continue...");
1344+        getkey();
1345+        set_videomode(saved_videomode);
1346+        graphics_inited = 0;
1347+        return 0;
1348+    }
1349+
1350+    set_int1c_handler();
1351+
1352+    return 1;
1353+}
1354+
1355+/* Leave graphics mode */
1356+void graphics_end(void)
1357+{
1358+    if (graphics_inited) {
1359+        unset_int1c_handler();
1360+        set_videomode(saved_videomode);
1361+        graphics_inited = 0;
1362+        no_cursor = 0;
1363+    }
1364+}
1365+
1366+/* Print ch on the screen.  Handle any needed scrolling or the like */
1367+void graphics_putchar(int ch) {
1368+    ch &= 0xff;
1369+
1370+    graphics_cursor(0);
1371+
1372+    if (ch == '\n') {
1373+        if (fonty + 1 < view_y1)
1374+            graphics_setxy(fontx, fonty + 1);
1375+        else
1376+            graphics_scroll();
1377+        graphics_cursor(1);
1378+        return;
1379+    } else if (ch == '\r') {
1380+        graphics_setxy(view_x0, fonty);
1381+        graphics_cursor(1);
1382+        return;
1383+    }
1384+
1385+    graphics_cursor(0);
1386+
1387+    text[fonty * 80 + fontx] = ch;
1388+    text[fonty * 80 + fontx] &= 0x00ff;
1389+    if (graphics_current_color & 0xf0)
1390+        text[fonty * 80 + fontx] |= 0x100;
1391+
1392+    graphics_cursor(0);
1393+
1394+    if ((fontx + 1) >= view_x1) {
1395+        graphics_setxy(view_x0, fonty);
1396+        if (fonty + 1 < view_y1)
1397+            graphics_setxy(view_x0, fonty + 1);
1398+        else
1399+            graphics_scroll();
1400+        graphics_cursor(1);
1401+        do_more ();
1402+        graphics_cursor(0);
1403+    } else {
1404+        graphics_setxy(fontx + 1, fonty);
1405+    }
1406+
1407+    graphics_cursor(1);
1408+}
1409+
1410+/* get the current location of the cursor */
1411+int graphics_getxy(void) {
1412+    return (fontx << 8) | fonty;
1413+}
1414+
1415+void graphics_gotoxy(int x, int y) {
1416+    graphics_cursor(0);
1417+
1418+    graphics_setxy(x, y);
1419+
1420+    graphics_cursor(1);
1421+}
1422+
1423+void graphics_cls(void) {
1424+    int i;
1425+    unsigned char *mem, *s1, *s2, *s4, *s8;
1426+
1427+    graphics_cursor(0);
1428+    graphics_gotoxy(view_x0, view_y0);
1429+
1430+    mem = (unsigned char*)VIDEOMEM;
1431+    s1 = (unsigned char*)VSHADOW1;
1432+    s2 = (unsigned char*)VSHADOW2;
1433+    s4 = (unsigned char*)VSHADOW4;
1434+    s8 = (unsigned char*)VSHADOW8;
1435+
1436+    for (i = 0; i < 80 * 30; i++)
1437+        text[i] = ' ';
1438+    graphics_cursor(1);
1439+
1440+    BitMask(0xff);
1441+
1442+    /* plane 1 */
1443+    MapMask(1);
1444+    grub_memcpy(mem, s1, 38400);
1445+
1446+    /* plane 2 */
1447+    MapMask(2);
1448+    grub_memcpy(mem, s2, 38400);
1449+
1450+    /* plane 3 */
1451+    MapMask(4);
1452+    grub_memcpy(mem, s4, 38400);
1453+
1454+    /* plane 4 */
1455+    MapMask(8);
1456+    grub_memcpy(mem, s8, 38400);
1457+
1458+    MapMask(15);
1459+
1460+    if (no_cursor) {
1461+        no_cursor = 0;
1462+        set_int1c_handler();
1463+    }
1464+}
1465+
1466+void graphics_setcolorstate (color_state state) {
1467+    switch (state) {
1468+    case COLOR_STATE_STANDARD:
1469+        graphics_current_color = graphics_standard_color;
1470+        break;
1471+    case COLOR_STATE_NORMAL:
1472+        graphics_current_color = graphics_normal_color;
1473+        break;
1474+    case COLOR_STATE_HIGHLIGHT:
1475+        graphics_current_color = graphics_highlight_color;
1476+        break;
1477+    default:
1478+        graphics_current_color = graphics_standard_color;
1479+        break;
1480+    }
1481+
1482+    graphics_color_state = state;
1483+}
1484+
1485+void graphics_setcolor (int normal_color, int highlight_color) {
1486+    graphics_normal_color = normal_color;
1487+    graphics_highlight_color = highlight_color;
1488+
1489+    graphics_setcolorstate (graphics_color_state);
1490+}
1491+
1492+int graphics_setcursor (int on) {
1493+    if (!no_cursor && !on) {
1494+        no_cursor = 1;
1495+        unset_int1c_handler();
1496+        graphics_cursor(0);
1497+    }
1498+    else if(no_cursor && on) {
1499+        no_cursor = 0;
1500+        set_int1c_handler();
1501+        graphics_cursor(1);
1502+    }
1503+    return 0;
1504+}
1505+
1506+/* Read in the splashscreen image and set the palette up appropriately.
1507+ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
1508+ * 640x480. */
1509+int read_image(char *s)
1510+{
1511+    char buf[32], pal[16], c;
1512+    unsigned char base, mask, *s1, *s2, *s4, *s8;
1513+    unsigned i, len, idx, colors, x, y, width, height;
1514+
1515+    if (!grub_open(s))
1516+        return 0;
1517+
1518+    /* read header */
1519+    if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
1520+        grub_close();
1521+        return 0;
1522+    }
1523+
1524+    /* parse info */
1525+    while (grub_read(&c, 1)) {
1526+        if (c == '"')
1527+            break;
1528+    }
1529+
1530+    while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
1531+        ;
1532+
1533+    i = 0;
1534+    width = c - '0';
1535+    while (grub_read(&c, 1)) {
1536+        if (c >= '0' && c <= '9')
1537+            width = width * 10 + c - '0';
1538+        else
1539+            break;
1540+    }
1541+    while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
1542+        ;
1543+
1544+    height = c - '0';
1545+    while (grub_read(&c, 1)) {
1546+        if (c >= '0' && c <= '9')
1547+            height = height * 10 + c - '0';
1548+        else
1549+            break;
1550+    }
1551+    while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
1552+        ;
1553+
1554+    colors = c - '0';
1555+    while (grub_read(&c, 1)) {
1556+        if (c >= '0' && c <= '9')
1557+            colors = colors * 10 + c - '0';
1558+        else
1559+            break;
1560+    }
1561+
1562+    base = 0;
1563+    while (grub_read(&c, 1) && c != '"')
1564+        ;
1565+
1566+    /* palette */
1567+    for (i = 0, idx = 1; i < colors; i++) {
1568+        len = 0;
1569+
1570+        while (grub_read(&c, 1) && c != '"')
1571+            ;
1572+        grub_read(&c, 1);       /* char */
1573+        base = c;
1574+        grub_read(buf, 4);      /* \t c # */
1575+
1576+        while (grub_read(&c, 1) && c != '"') {
1577+            if (len < sizeof(buf))
1578+                buf[len++] = c;
1579+        }
1580+
1581+        if (len == 6 && idx < 15) {
1582+            int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
1583+            int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
1584+            int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
1585+
1586+            pal[idx] = base;
1587+            graphics_set_palette(idx, r, g, b);
1588+            ++idx;
1589+        }
1590+    }
1591+
1592+    x = y = len = 0;
1593+
1594+    s1 = (unsigned char*)VSHADOW1;
1595+    s2 = (unsigned char*)VSHADOW2;
1596+    s4 = (unsigned char*)VSHADOW4;
1597+    s8 = (unsigned char*)VSHADOW8;
1598+
1599+    for (i = 0; i < 38400; i++)
1600+        s1[i] = s2[i] = s4[i] = s8[i] = 0;
1601+
1602+    /* parse xpm data */
1603+    while (y < height) {
1604+        while (1) {
1605+            if (!grub_read(&c, 1)) {
1606+                grub_close();
1607+                return 0;
1608+            }
1609+            if (c == '"')
1610+                break;
1611+        }
1612+
1613+        while (grub_read(&c, 1) && c != '"') {
1614+            for (i = 1; i < 15; i++)
1615+                if (pal[i] == c) {
1616+                    c = i;
1617+                    break;
1618+                }
1619+
1620+            mask = 0x80 >> (x & 7);
1621+            if (c & 1)
1622+                s1[len + (x >> 3)] |= mask;
1623+            if (c & 2)
1624+                s2[len + (x >> 3)] |= mask;
1625+            if (c & 4)
1626+                s4[len + (x >> 3)] |= mask;
1627+            if (c & 8)
1628+                s8[len + (x >> 3)] |= mask;
1629+
1630+            if (++x >= 640) {
1631+                x = 0;
1632+
1633+                if (y < 480)
1634+                    len += 80;
1635+                ++y;
1636+            }
1637+        }
1638+    }
1639+
1640+    grub_close();
1641+
1642+    graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
1643+                background & 63);
1644+    graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
1645+                foreground & 63);
1646+    graphics_set_palette(0x11, (window_border >> 16), (window_border >> 8) & 63,
1647+                         window_border & 63);
1648+
1649+    return 1;
1650+}
1651+
1652+/* Convert a character which is a hex digit to the appropriate integer */
1653+int hex(int v)
1654+{
1655+    if (v >= 'A' && v <= 'F')
1656+        return (v - 'A' + 10);
1657+    if (v >= 'a' && v <= 'f')
1658+        return (v - 'a' + 10);
1659+    return (v - '0');
1660+}
1661+
1662+void graphics_cursor(int set) {
1663+    unsigned char *pat, *mem, *ptr, chr[16 << 2];
1664+    int i, ch, invert, offset;
1665+
1666+    if (set && (no_cursor || no_scroll))
1667+        return;
1668+
1669+    offset = cursorY * 80 + fontx;
1670+    ch = text[fonty * 80 + fontx] & 0xff;
1671+    invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
1672+    pat = font8x16 + (ch << 4);
1673+
1674+    mem = (unsigned char*)VIDEOMEM + offset;
1675+
1676+    if (!set) {
1677+        for (i = 0; i < 16; i++) {
1678+            unsigned char mask = pat[i];
1679+
1680+            if (!invert) {
1681+                chr[i     ] = ((unsigned char*)VSHADOW1)[offset];
1682+                chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
1683+                chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
1684+                chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
1685+
1686+                if (shade) {
1687+                    if (ch == DISP_VERT || ch == DISP_LL ||
1688+                        ch == DISP_UR || ch == DISP_LR) {
1689+                        unsigned char pmask = ~(pat[i] >> 1);
1690+
1691+                        chr[i     ] &= pmask;
1692+                        chr[16 + i] &= pmask;
1693+                        chr[32 + i] &= pmask;
1694+                        chr[48 + i] &= pmask;
1695+                    }
1696+                    if (i > 0 && ch != DISP_VERT) {
1697+                        unsigned char pmask = ~(pat[i - 1] >> 1);
1698+
1699+                        chr[i     ] &= pmask;
1700+                        chr[16 + i] &= pmask;
1701+                        chr[32 + i] &= pmask;
1702+                        chr[48 + i] &= pmask;
1703+                        if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
1704+                            pmask = ~pat[i - 1];
1705+
1706+                            chr[i     ] &= pmask;
1707+                            chr[16 + i] &= pmask;
1708+                            chr[32 + i] &= pmask;
1709+                            chr[48 + i] &= pmask;
1710+                        }
1711+                    }
1712+                }
1713+                chr[i     ] |= mask;
1714+                chr[16 + i] |= mask;
1715+                chr[32 + i] |= mask;
1716+                chr[48 + i] |= mask;
1717+
1718+                offset += 80;
1719+            }
1720+            else {
1721+                chr[i     ] = mask;
1722+                chr[16 + i] = mask;
1723+                chr[32 + i] = mask;
1724+                chr[48 + i] = mask;
1725+            }
1726+        }
1727+    }
1728+    else {
1729+        MapMask(15);
1730+        ptr = mem;
1731+        for (i = 0; i < 16; i++, ptr += 80) {
1732+            cursorBuf[i] = pat[i];
1733+            *ptr = ~pat[i];
1734+        }
1735+        return;
1736+    }
1737+
1738+    offset = 0;
1739+    for (i = 1; i < 16; i <<= 1, offset += 16) {
1740+        int j;
1741+
1742+        MapMask(i);
1743+        ptr = mem;
1744+        for (j = 0; j < 16; j++, ptr += 80)
1745+            *ptr = chr[j + offset];
1746+    }
1747+
1748+    MapMask(15);
1749+}
1750+
1751+#endif /* SUPPORT_GRAPHICS */
1752diff -Naur grub-0.97.orig/stage2/graphics.h grub-0.97/stage2/graphics.h
1753--- grub-0.97.orig/stage2/graphics.h	1969-12-31 21:00:00.000000000 -0300
1754+++ grub-0.97/stage2/graphics.h	2005-06-12 20:56:49.000000000 -0300
1755@@ -0,0 +1,43 @@
1756+/* graphics.h - graphics console interface */
1757+/*
1758+ *  GRUB  --  GRand Unified Bootloader
1759+ *  Copyright (C) 2002  Free Software Foundation, Inc.
1760+ *
1761+ *  This program is free software; you can redistribute it and/or modify
1762+ *  it under the terms of the GNU General Public License as published by
1763+ *  the Free Software Foundation; either version 2 of the License, or
1764+ *  (at your option) any later version.
1765+ *
1766+ *  This program is distributed in the hope that it will be useful,
1767+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1768+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1769+ *  GNU General Public License for more details.
1770+ *
1771+ *  You should have received a copy of the GNU General Public License
1772+ *  along with this program; If not, see <http://www.gnu.org/licenses/>
1773+ */
1774+
1775+#ifndef GRAPHICS_H
1776+#define GRAPHICS_H
1777+
1778+/* magic constant */
1779+#define VIDEOMEM 0xA0000
1780+
1781+/* function prototypes */
1782+char *graphics_get_splash(void);
1783+
1784+int read_image(char *s);
1785+void graphics_cursor(int set);
1786+
1787+/* function prototypes for asm functions */
1788+void * graphics_get_font();
1789+void graphics_set_palette(int idx, int red, int green, int blue);
1790+void set_int1c_handler();
1791+void unset_int1c_handler();
1792+
1793+extern short cursorX, cursorY;
1794+extern char cursorBuf[16];
1795+extern int shade;
1796+extern int view_x0, view_y0, view_x1, view_y1;
1797+
1798+#endif /* GRAPHICS_H */
1799diff -Naur grub-0.97.orig/stage2/Makefile.am grub-0.97/stage2/Makefile.am
1800--- grub-0.97.orig/stage2/Makefile.am	2005-02-02 18:37:35.000000000 -0200
1801+++ grub-0.97/stage2/Makefile.am	2005-06-12 20:56:49.000000000 -0300
1802@@ -7,7 +7,7 @@
1803         fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
1804 	imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
1805 	nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
1806-	terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
1807+	terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h
1808 EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
1809
1810 # For <stage1.h>.
1811@@ -19,7 +19,7 @@
1812 	disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
1813 	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
1814 	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
1815-	terminfo.c tparm.c
1816+	terminfo.c tparm.c graphics.c
1817 libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
1818 	-DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
1819 	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
1820@@ -79,8 +79,14 @@
1821 HERCULES_FLAGS =
1822 endif
1823
1824+if GRAPHICS_SUPPORT
1825+GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1
1826+else
1827+GRAPHICS_FLAGS =
1828+endif
1829+
1830 STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
1831-	$(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
1832+	$(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
1833
1834 STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
1835 STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
1836@@ -90,7 +96,8 @@
1837 	cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
1838 	fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
1839 	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
1840-	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
1841+	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
1842+	graphics.c
1843 pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
1844 pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
1845 pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
1846diff -Naur grub-0.97.orig/stage2/shared.h grub-0.97/stage2/shared.h
1847--- grub-0.97.orig/stage2/shared.h	2004-06-19 13:40:09.000000000 -0300
1848+++ grub-0.97/stage2/shared.h	2005-06-12 20:56:49.000000000 -0300
1849@@ -792,6 +792,11 @@
1850 /* Set the cursor position. */
1851 void gotoxy (int x, int y);
1852
1853+/* Internal pager
1854+   Returns 1 = if pager was used
1855+           0 = if pager wasn't used  */
1856+int do_more (void);
1857+
1858 /* Displays an ASCII character.  IBM displays will translate some
1859    characters to special graphical ones (see the DISP_* constants). */
1860 void grub_putchar (int c);
1861@@ -871,6 +876,7 @@
1862 int grub_tolower (int c);
1863 int grub_isspace (int c);
1864 int grub_strncat (char *s1, const char *s2, int n);
1865+void grub_memcpy(void *dest, const void *src, int len);
1866 void *grub_memmove (void *to, const void *from, int len);
1867 void *grub_memset (void *start, int c, int len);
1868 int grub_strncat (char *s1, const char *s2, int n);
1869diff -Naur grub-0.97.orig/stage2/stage2.c grub-0.97/stage2/stage2.c
1870--- grub-0.97.orig/stage2/stage2.c	2005-03-19 14:51:57.000000000 -0300
1871+++ grub-0.97/stage2/stage2.c	2005-06-13 22:38:08.000000000 -0300
1872@@ -20,6 +20,12 @@
1873 #include <shared.h>
1874 #include <term.h>
1875
1876+#ifdef SUPPORT_GRAPHICS
1877+# include <graphics.h>
1878+#endif
1879+
1880+int col_start, col_end, row_start, box_size;
1881+
1882 grub_jmp_buf restart_env;
1883
1884 #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
1885@@ -105,13 +111,13 @@
1886   if (highlight && current_term->setcolorstate)
1887     current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
1888
1889-  gotoxy (2, y);
1890+  gotoxy (2 + col_start, y);
1891   grub_putchar (' ');
1892-  for (x = 3; x < 75; x++)
1893+  for (x = 3 + col_start; x < (col_end - 5); x++)
1894     {
1895-      if (*entry && x <= 72)
1896+      if (*entry && x <= (col_end - 8))
1897 	{
1898-	  if (x == 72)
1899+	  if (x == (col_end - 8))
1900 	    grub_putchar (DISP_RIGHT);
1901 	  else
1902 	    grub_putchar (*entry++);
1903@@ -119,7 +125,7 @@
1904       else
1905 	grub_putchar (' ');
1906     }
1907-  gotoxy (74, y);
1908+  gotoxy ((col_end - 6), y);
1909
1910   if (current_term->setcolorstate)
1911     current_term->setcolorstate (COLOR_STATE_STANDARD);
1912@@ -131,7 +137,7 @@
1913 {
1914   int i;
1915
1916-  gotoxy (77, y + 1);
1917+  gotoxy ((col_end - 3), y + 1);
1918
1919   if (first)
1920     grub_putchar (DISP_UP);
1921@@ -151,14 +157,14 @@
1922 	menu_entries++;
1923     }
1924
1925-  gotoxy (77, y + size);
1926+  gotoxy ((col_end - 3), y + size);
1927
1928   if (*menu_entries)
1929     grub_putchar (DISP_DOWN);
1930   else
1931     grub_putchar (' ');
1932
1933-  gotoxy (74, y + entryno + 1);
1934+  gotoxy ((col_end - 6), y + entryno + 1);
1935 }
1936
1937 static void
1938@@ -196,30 +202,30 @@
1939   if (current_term->setcolorstate)
1940     current_term->setcolorstate (COLOR_STATE_NORMAL);
1941
1942-  gotoxy (1, y);
1943+  gotoxy (1 + col_start, y);
1944
1945   grub_putchar (DISP_UL);
1946-  for (i = 0; i < 73; i++)
1947+  for (i = col_start; i < (col_end - 7); i++)
1948     grub_putchar (DISP_HORIZ);
1949   grub_putchar (DISP_UR);
1950
1951   i = 1;
1952   while (1)
1953     {
1954-      gotoxy (1, y + i);
1955+      gotoxy (1 + col_start, y + i);
1956
1957       if (i > size)
1958 	break;
1959
1960       grub_putchar (DISP_VERT);
1961-      gotoxy (75, y + i);
1962+      gotoxy ((col_end - 5), y + i);
1963       grub_putchar (DISP_VERT);
1964
1965       i++;
1966     }
1967
1968   grub_putchar (DISP_LL);
1969-  for (i = 0; i < 73; i++)
1970+  for (i = col_start; i < (col_end - 7); i++)
1971     grub_putchar (DISP_HORIZ);
1972   grub_putchar (DISP_LR);
1973
1974@@ -233,6 +239,7 @@
1975 {
1976   int c, time1, time2 = -1, first_entry = 0;
1977   char *cur_entry = 0;
1978+  struct term_entry *prev_term = NULL;
1979
1980   /*
1981    *  Main loop for menu UI.
1982@@ -250,6 +257,22 @@
1983 	}
1984     }
1985
1986+  col_start = 0;
1987+  col_end = 80;
1988+  row_start = 0;
1989+  box_size = 12;
1990+  /* if we're using viewport we need to make sure to setup
1991+     coordinates correctly.  */
1992+#ifdef SUPPORT_GRAPHICS
1993+  if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
1994+    {
1995+      col_start = view_x0;
1996+      col_end = view_x1;
1997+      row_start = view_y0;
1998+      box_size = (view_y1 - view_y0) - 13;
1999+    }
2000+#endif
2001+
2002   /* If the timeout was expired or wasn't set, force to show the menu
2003      interface. */
2004   if (grub_timeout < 0)
2005@@ -302,36 +325,36 @@
2006       if (current_term->flags & TERM_DUMB)
2007 	print_entries_raw (num_entries, first_entry, menu_entries);
2008       else
2009-	print_border (3, 12);
2010+	print_border (3 + row_start, box_size);
2011
2012       grub_printf ("\n\
2013-      Use the %c and %c keys to select which entry is highlighted.\n",
2014+    Use the %c and %c keys to select which entry is highlighted.\n",
2015 		   DISP_UP, DISP_DOWN);
2016
2017       if (! auth && password)
2018 	{
2019 	  printf ("\
2020-      Press enter to boot the selected OS or \'p\' to enter a\n\
2021-      password to unlock the next set of features.");
2022+    Press enter to boot the selected OS or \'p\' to enter a\n\
2023+    password to unlock the next set of features.");
2024 	}
2025       else
2026 	{
2027 	  if (config_entries)
2028 	    printf ("\
2029-      Press enter to boot the selected OS, \'e\' to edit the\n\
2030-      commands before booting, or \'c\' for a command-line.");
2031+    Press enter to boot the selected OS, \'e\' to edit the\n\
2032+    commands before booting, or \'c\' for a command-line.");
2033 	  else
2034 	    printf ("\
2035-      Press \'b\' to boot, \'e\' to edit the selected command in the\n\
2036-      boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
2037-      after (\'O\' for before) the selected line, \'d\' to remove the\n\
2038-      selected line, or escape to go back to the main menu.");
2039+    Press \'b\' to boot, \'e\' to edit the selected command in the\n\
2040+    boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
2041+    after (\'O\' for before) the selected line, \'d\' to remove the\n\
2042+    selected line, or escape to go back to the main menu.");
2043 	}
2044
2045       if (current_term->flags & TERM_DUMB)
2046 	grub_printf ("\n\nThe selected entry is %d ", entryno);
2047       else
2048-	print_entries (3, 12, first_entry, entryno, menu_entries);
2049+	print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
2050     }
2051
2052   /* XX using RT clock now, need to initialize value */
2053@@ -358,10 +381,10 @@
2054 			   entryno, grub_timeout);
2055 	  else
2056 	    {
2057-	      gotoxy (3, 22);
2058-	      grub_printf ("The highlighted entry will be booted automatically in %d seconds.    ",
2059+	      gotoxy (3 + col_start, 10 + box_size + row_start);
2060+	      grub_printf (" The highlighted entry will be booted automatically in %d seconds.   ",
2061 			   grub_timeout);
2062-	      gotoxy (74, 4 + entryno);
2063+	      gotoxy ((col_end - 6), 4 + entryno + row_start);
2064 	  }
2065
2066 	  grub_timeout--;
2067@@ -387,12 +410,12 @@
2068 	      if (current_term->flags & TERM_DUMB)
2069 		grub_putchar ('\r');
2070 	      else
2071-		gotoxy (3, 22);
2072+		gotoxy (3 + col_start, 10 + box_size + row_start);
2073 	      printf ("                                                                    ");
2074 	      grub_timeout = -1;
2075 	      fallback_entryno = -1;
2076 	      if (! (current_term->flags & TERM_DUMB))
2077-		gotoxy (74, 4 + entryno);
2078+		gotoxy ((col_end - 6), 4 + entryno + row_start);
2079 	    }
2080
2081 	  /* We told them above (at least in SUPPORT_SERIAL) to use
2082@@ -408,12 +431,12 @@
2083 		{
2084 		  if (entryno > 0)
2085 		    {
2086-		      print_entry (4 + entryno, 0,
2087+		      print_entry (4 + entryno + row_start, 0,
2088 				   get_entry (menu_entries,
2089 					      first_entry + entryno,
2090 					      0));
2091 		      entryno--;
2092-		      print_entry (4 + entryno, 1,
2093+		      print_entry (4 + entryno + row_start, 1,
2094 				   get_entry (menu_entries,
2095 					      first_entry + entryno,
2096 					      0));
2097@@ -421,7 +444,7 @@
2098 		  else if (first_entry > 0)
2099 		    {
2100 		      first_entry--;
2101-		      print_entries (3, 12, first_entry, entryno,
2102+		      print_entries (3 + row_start, box_size, first_entry, entryno,
2103 				     menu_entries);
2104 		    }
2105 		}
2106@@ -433,29 +456,29 @@
2107 		entryno++;
2108 	      else
2109 		{
2110-		  if (entryno < 11)
2111+		  if (entryno < (box_size - 1))
2112 		    {
2113-		      print_entry (4 + entryno, 0,
2114+		      print_entry (4 + entryno + row_start, 0,
2115 				   get_entry (menu_entries,
2116 					      first_entry + entryno,
2117 					      0));
2118 		      entryno++;
2119-		      print_entry (4 + entryno, 1,
2120+		      print_entry (4 + entryno + row_start, 1,
2121 				   get_entry (menu_entries,
2122 					      first_entry + entryno,
2123 					      0));
2124 		  }
2125-		else if (num_entries > 12 + first_entry)
2126+		else if (num_entries > box_size + first_entry)
2127 		  {
2128 		    first_entry++;
2129-		    print_entries (3, 12, first_entry, entryno, menu_entries);
2130+		    print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
2131 		  }
2132 		}
2133 	    }
2134 	  else if (c == 7)
2135 	    {
2136 	      /* Page Up */
2137-	      first_entry -= 12;
2138+	      first_entry -= box_size;
2139 	      if (first_entry < 0)
2140 		{
2141 		  entryno += first_entry;
2142@@ -463,20 +486,20 @@
2143 		  if (entryno < 0)
2144 		    entryno = 0;
2145 		}
2146-	      print_entries (3, 12, first_entry, entryno, menu_entries);
2147+	      print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
2148 	    }
2149 	  else if (c == 3)
2150 	    {
2151 	      /* Page Down */
2152-	      first_entry += 12;
2153+	      first_entry += box_size;
2154 	      if (first_entry + entryno + 1 >= num_entries)
2155 		{
2156-		  first_entry = num_entries - 12;
2157+		  first_entry = num_entries - box_size;
2158 		  if (first_entry < 0)
2159 		    first_entry = 0;
2160 		  entryno = num_entries - first_entry - 1;
2161 		}
2162-	      print_entries (3, 12, first_entry, entryno, menu_entries);
2163+	      print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
2164 	    }
2165
2166 	  if (config_entries)
2167@@ -489,7 +512,7 @@
2168 	      if ((c == 'd') || (c == 'o') || (c == 'O'))
2169 		{
2170 		  if (! (current_term->flags & TERM_DUMB))
2171-		    print_entry (4 + entryno, 0,
2172+		    print_entry (4 + entryno + row_start, 0,
2173 				 get_entry (menu_entries,
2174 					    first_entry + entryno,
2175 					    0));
2176@@ -537,7 +560,7 @@
2177
2178 		      if (entryno >= num_entries)
2179 			entryno--;
2180-		      if (first_entry && num_entries < 12 + first_entry)
2181+		      if (first_entry && num_entries < box_size + first_entry)
2182 			first_entry--;
2183 		    }
2184
2185@@ -549,7 +572,7 @@
2186 		      grub_printf ("\n");
2187 		    }
2188 		  else
2189-		    print_entries (3, 12, first_entry, entryno, menu_entries);
2190+		    print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
2191 		}
2192
2193 	      cur_entry = menu_entries;
2194@@ -570,7 +593,7 @@
2195 		  if (current_term->flags & TERM_DUMB)
2196 		    grub_printf ("\r                                    ");
2197 		  else
2198-		    gotoxy (1, 21);
2199+		    gotoxy (1 + col_start, 9 + box_size + row_start);
2200
2201 		  /* Wipe out the previously entered password */
2202 		  grub_memset (entered, 0, sizeof (entered));
2203@@ -714,6 +737,15 @@
2204
2205   cls ();
2206   setcursor (1);
2207+  /* if our terminal needed initialization, we should shut it down
2208+   * before booting the kernel, but we want to save what it was so
2209+   * we can come back if needed */
2210+  prev_term = current_term;
2211+  if (current_term->shutdown)
2212+    {
2213+      current_term->shutdown();
2214+      current_term = term_table; /* assumption: console is first */
2215+    }
2216
2217   while (1)
2218     {
2219@@ -748,6 +780,13 @@
2220 	break;
2221     }
2222
2223+  /* if we get back here, we should go back to what our term was before */
2224+  current_term = prev_term;
2225+  if (current_term->startup)
2226+      /* if our terminal fails to initialize, fall back to console since
2227+       * it should always work */
2228+      if (current_term->startup() == 0)
2229+          current_term = term_table; /* we know that console is first */
2230   show_menu = 1;
2231   goto restart;
2232 }
2233@@ -1050,6 +1089,16 @@
2234 	  while (is_preset);
2235 	}
2236
2237+      /* go ahead and make sure the terminal is setup */
2238+      if (current_term->startup)
2239+	{
2240+	  /* If initialization fails, go back to default terminal */
2241+	  if (current_term->startup() == 0)
2242+		  {
2243+		      current_term = term_table;
2244+		  }
2245+	}
2246+
2247       if (! num_entries)
2248 	{
2249 	  /* If no acceptable config file, goto command-line, starting
2250diff -Naur grub-0.97.orig/stage2/term.h grub-0.97/stage2/term.h
2251--- grub-0.97.orig/stage2/term.h	2003-07-09 08:45:53.000000000 -0300
2252+++ grub-0.97/stage2/term.h	2005-06-13 14:07:40.000000000 -0300
2253@@ -60,6 +60,8 @@
2254   const char *name;
2255   /* The feature flags defined above.  */
2256   unsigned long flags;
2257+  /* Default for maximum number of lines if not specified */
2258+  unsigned short max_lines;
2259   /* Put a character.  */
2260   void (*putchar) (int c);
2261   /* Check if any input character is available.  */
2262@@ -79,6 +81,10 @@
2263   void (*setcolor) (int normal_color, int highlight_color);
2264   /* Turn on/off the cursor.  */
2265   int (*setcursor) (int on);
2266+  /* function to start a terminal */
2267+  int (*startup) (void);
2268+  /* function to use to shutdown a terminal */
2269+  void (*shutdown) (void);
2270 };
2271
2272 /* This lists up available terminals.  */
2273@@ -124,4 +130,24 @@
2274 int hercules_setcursor (int on);
2275 #endif
2276
2277+#ifdef SUPPORT_GRAPHICS
2278+extern int foreground, background, window_border, graphics_inited, saved_videomode;
2279+
2280+void graphics_set_splash(char *splashfile);
2281+int set_videomode(int mode);
2282+int get_videomode(void);
2283+void graphics_putchar (int c);
2284+int graphics_getxy(void);
2285+void graphics_gotoxy(int x, int y);
2286+void graphics_cls(void);
2287+void graphics_setcolorstate (color_state state);
2288+void graphics_setcolor (int normal_color, int highlight_color);
2289+int graphics_setcursor (int on);
2290+int graphics_init(void);
2291+void graphics_end(void);
2292+
2293+int hex(int v);
2294+void graphics_set_palette(int idx, int red, int green, int blue);
2295+#endif /* SUPPORT_GRAPHICS */
2296+
2297 #endif /* ! GRUB_TERM_HEADER */
2298