summaryrefslogtreecommitdiffstats
path: root/abs/core-testing/grub-gfx/grub-0.97-graphics.patch
diff options
context:
space:
mode:
Diffstat (limited to 'abs/core-testing/grub-gfx/grub-0.97-graphics.patch')
-rw-r--r--abs/core-testing/grub-gfx/grub-0.97-graphics.patch1293
1 files changed, 1293 insertions, 0 deletions
diff --git a/abs/core-testing/grub-gfx/grub-0.97-graphics.patch b/abs/core-testing/grub-gfx/grub-0.97-graphics.patch
new file mode 100644
index 0000000..e0baa90
--- /dev/null
+++ b/abs/core-testing/grub-gfx/grub-0.97-graphics.patch
@@ -0,0 +1,1293 @@
+diff -urpN grub-0.97/configure.ac grub-0.97-gfx/configure.ac
+--- grub-0.97/configure.ac 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/configure.ac 2005-10-13 16:27:35.000000000 -0400
+@@ -595,6 +595,11 @@ AC_ARG_ENABLE(diskless,
+ [ --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 -urpN grub-0.97/stage2/Makefile.am grub-0.97-gfx/stage2/Makefile.am
+--- grub-0.97/stage2/Makefile.am 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/Makefile.am 2005-10-13 16:27:35.000000000 -0400
+@@ -7,7 +7,7 @@ noinst_HEADERS = apic.h defs.h dir.h dis
+ 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 @@ libgrub_a_SOURCES = boot.c builtins.c ch
+ 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 @@ else
+ 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 @@ pre_stage2_exec_SOURCES = asm.S bios.c b
+ 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 -urpN grub-0.97/stage2/asm.S grub-0.97-gfx/stage2/asm.S
+--- grub-0.97/stage2/asm.S 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/asm.S 2005-10-13 16:27:35.000000000 -0400
+@@ -2216,6 +2216,156 @@ ENTRY(console_setcursor)
+ pop %ebx
+ pop %ebp
+ ret
++
++/* graphics mode functions */
++#ifdef SUPPORT_GRAPHICS
++VARIABLE(cursorX)
++.word 0
++VARIABLE(cursorY)
++.word 0
++VARIABLE(cursorCount)
++.word 0
++VARIABLE(cursorBuf)
++.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++
++
++/*
++ * int set_videomode(mode)
++ * BIOS call "INT 10H Function 0h" to set video mode
++ * Call with %ah = 0x0
++ * %al = video mode
++ * Returns old videomode.
++ */
++ENTRY(set_videomode)
++ push %ebp
++ push %ebx
++ push %ecx
++
++ movb 0x10(%esp), %cl
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ xorw %bx, %bx
++ movb $0xf, %ah
++ int $0x10 /* Get Current Video mode */
++ movb %al, %ch
++ xorb %ah, %ah
++ movb %cl, %al
++ int $0x10 /* Set Video mode */
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorb %ah, %ah
++ movb %ch, %al
++
++ pop %ecx
++ pop %ebx
++ pop %ebp
++ ret
++
++
++/*
++ * unsigned char * graphics_get_font()
++ * BIOS call "INT 10H Function 11h" to set font
++ * Call with %ah = 0x11
++ */
++ENTRY(graphics_get_font)
++ push %ebp
++ push %ebx
++ push %ecx
++ push %edx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ movw $0x1130, %ax
++ movb $6, %bh /* font 8x16 */
++ int $0x10
++ movw %bp, %dx
++ movw %es, %cx
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movw %cx, %ax
++ shll $4, %eax
++ movw %dx, %ax
++
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %ebp
++ ret
++
++
++
++/*
++ * graphics_set_palette(index, red, green, blue)
++ * BIOS call "INT 10H Function 10h" to set individual dac register
++ * Call with %ah = 0x10
++ * %bx = register number
++ * %ch = new value for green (0-63)
++ * %cl = new value for blue (0-63)
++ * %dh = new value for red (0-63)
++ */
++
++ENTRY(graphics_set_palette)
++ push %ebp
++ push %eax
++ push %ebx
++ push %ecx
++ push %edx
++
++ movw $0x3c8, %bx /* address write mode register */
++
++ /* wait vertical retrace */
++
++ movw $0x3da, %dx
++l1b: inb %dx, %al /* wait vertical active display */
++ test $8, %al
++ jnz l1b
++
++l2b: inb %dx, %al /* wait vertical retrace */
++ test $8, %al
++ jnz l2b
++
++ mov %bx, %dx
++ movb 0x18(%esp), %al /* index */
++ outb %al, %dx
++ inc %dx
++
++ movb 0x1c(%esp), %al /* red */
++ outb %al, %dx
++
++ movb 0x20(%esp), %al /* green */
++ outb %al, %dx
++
++ movb 0x24(%esp), %al /* blue */
++ outb %al, %dx
++
++ movw 0x18(%esp), %bx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ movb %bl, %bh
++ movw $0x1000, %ax
++ int $0x10
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %eax
++ pop %ebp
++ ret
++
++#endif /* SUPPORT_GRAPHICS */
+
+ /*
+ * getrtsecs()
+diff -urpN grub-0.97/stage2/builtins.c grub-0.97-gfx/stage2/builtins.c
+--- grub-0.97/stage2/builtins.c 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/builtins.c 2005-10-13 16:27:35.000000000 -0400
+@@ -852,6 +852,138 @@ static struct builtin builtin_dhcp =
+ };
+ #endif /* SUPPORT_NETBOOT */
+
++static int terminal_func (char *arg, int flags);
++
++#ifdef SUPPORT_GRAPHICS
++
++static int splashimage_func(char *arg, int flags) {
++ char splashimage[64];
++ int i;
++
++ /* filename can only be 64 characters due to our buffer size */
++ if (strlen(arg) > 63)
++ return 1;
++ if (flags == BUILTIN_CMDLINE) {
++ if (!grub_open(arg))
++ return 1;
++ grub_close();
++ }
++
++ strcpy(splashimage, arg);
++
++ /* get rid of TERM_NEED_INIT from the graphics terminal. */
++ for (i = 0; term_table[i].name; i++) {
++ if (grub_strcmp (term_table[i].name, "graphics") == 0) {
++ term_table[i].flags &= ~TERM_NEED_INIT;
++ break;
++ }
++ }
++
++ graphics_set_splash(splashimage);
++
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ graphics_init();
++ graphics_cls();
++ }
++
++ /* FIXME: should we be explicitly switching the terminal as a
++ * side effect here? */
++ terminal_func("graphics", flags);
++
++ return 0;
++}
++
++static struct builtin builtin_splashimage =
++{
++ "splashimage",
++ splashimage_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "splashimage FILE",
++ "Load FILE as the background image when in graphics mode."
++};
++
++
++/* foreground */
++static int
++foreground_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ foreground = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(15, r, g, b);
++
++ return (0);
++ }
++
++ return (1);
++}
++
++static struct builtin builtin_foreground =
++{
++ "foreground",
++ foreground_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "foreground RRGGBB",
++ "Sets the foreground color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* background */
++static int
++background_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ background = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(0, r, g, b);
++ return (0);
++ }
++
++ return (1);
++}
++
++static struct builtin builtin_background =
++{
++ "background",
++ background_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "background RRGGBB",
++ "Sets the background color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++#endif /* SUPPORT_GRAPHICS */
++
++
++/* clear */
++static int
++clear_func()
++{
++ if (current_term->cls)
++ current_term->cls();
++
++ return 0;
++}
++
++static struct builtin builtin_clear =
++{
++ "clear",
++ clear_func,
++ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++ "clear",
++ "Clear the screen"
++};
++
+
+ /* displayapm */
+ static int
+@@ -4085,7 +4217,7 @@ static struct builtin builtin_setup =
+ };
+
+
+-#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 +4376,21 @@ terminal_func (char *arg, int flags)
+ end:
+ current_term = term_table + default_term;
+ current_term->flags = term_flags;
+-
++
+ if (lines)
+ max_lines = lines;
+ else
+- /* 24 would be a good default value. */
+- max_lines = 24;
+-
++ max_lines = current_term->max_lines;
++
+ /* If the interface is currently the command-line,
+ restart it to repaint the screen. */
+- if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
++ if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
++ if (prev_term->shutdown)
++ prev_term->shutdown();
++ if (current_term->startup)
++ current_term->startup();
+ grub_longjmp (restart_cmdline_env, 0);
++ }
+
+ return 0;
+ }
+@@ -4264,7 +4400,7 @@ static struct builtin builtin_terminal =
+ "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 +4412,7 @@ static struct builtin builtin_terminal =
+ " 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,6 +4931,9 @@ static struct builtin builtin_vbeprobe =
+ /* 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
+@@ -4802,6 +4941,7 @@ struct builtin *builtin_table[] =
+ #endif /* SUPPORT_NETBOOT */
+ &builtin_cat,
+ &builtin_chainloader,
++ &builtin_clear,
+ &builtin_cmp,
+ &builtin_color,
+ &builtin_configfile,
+@@ -4821,6 +4961,9 @@ struct builtin *builtin_table[] =
+ &builtin_embed,
+ &builtin_fallback,
+ &builtin_find,
++#ifdef SUPPORT_GRAPHICS
++ &builtin_foreground,
++#endif
+ &builtin_fstest,
+ &builtin_geometry,
+ &builtin_halt,
+@@ -4864,9 +5007,12 @@ struct builtin *builtin_table[] =
+ #endif /* SUPPORT_SERIAL */
+ &builtin_setkey,
+ &builtin_setup,
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++#ifdef SUPPORT_GRAPHICS
++ &builtin_splashimage,
++#endif /* SUPPORT_GRAPHICS */
++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+ &builtin_terminal,
+-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
+ #ifdef SUPPORT_SERIAL
+ &builtin_terminfo,
+ #endif /* SUPPORT_SERIAL */
+diff -urpN grub-0.97/stage2/char_io.c grub-0.97-gfx/stage2/char_io.c
+--- grub-0.97/stage2/char_io.c 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/char_io.c 2005-10-13 16:27:35.000000000 -0400
+@@ -35,6 +35,7 @@ struct term_entry term_table[] =
+ {
+ "console",
+ 0,
++ 24,
+ console_putchar,
+ console_checkkey,
+ console_getkey,
+@@ -43,13 +44,16 @@ struct term_entry term_table[] =
+ console_cls,
+ console_setcolorstate,
+ console_setcolor,
+- console_setcursor
++ console_setcursor,
++ 0,
++ 0
+ },
+ #ifdef SUPPORT_SERIAL
+ {
+ "serial",
+ /* A serial device must be initialized. */
+ TERM_NEED_INIT,
++ 24,
+ serial_putchar,
+ serial_checkkey,
+ serial_getkey,
+@@ -58,6 +62,8 @@ struct term_entry term_table[] =
+ serial_cls,
+ serial_setcolorstate,
+ 0,
++ 0,
++ 0,
+ 0
+ },
+ #endif /* SUPPORT_SERIAL */
+@@ -65,6 +71,7 @@ struct term_entry term_table[] =
+ {
+ "hercules",
+ 0,
++ 24,
+ hercules_putchar,
+ console_checkkey,
+ console_getkey,
+@@ -73,9 +80,28 @@ struct term_entry term_table[] =
+ hercules_cls,
+ hercules_setcolorstate,
+ hercules_setcolor,
+- hercules_setcursor
++ hercules_setcursor,
++ 0,
++ 0
+ },
+ #endif /* SUPPORT_HERCULES */
++#ifdef SUPPORT_GRAPHICS
++ { "graphics",
++ TERM_NEED_INIT, /* flags */
++ 30, /* number of lines */
++ graphics_putchar, /* putchar */
++ console_checkkey, /* checkkey */
++ console_getkey, /* getkey */
++ graphics_getxy, /* getxy */
++ graphics_gotoxy, /* gotoxy */
++ graphics_cls, /* cls */
++ graphics_setcolorstate, /* setcolorstate */
++ graphics_setcolor, /* setcolor */
++ graphics_setcursor, /* nocursor */
++ graphics_init, /* initialize */
++ graphics_end /* shutdown */
++ },
++#endif /* SUPPORT_GRAPHICS */
+ /* This must be the last entry. */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ };
+@@ -1046,13 +1072,15 @@ grub_putchar (int c)
+ the following grub_printf call will print newlines. */
+ count_lines = -1;
+
++ grub_printf("\n");
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+
+- grub_printf ("\n[Hit return to continue]");
++ grub_printf ("[Hit return to continue]");
+
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_NORMAL);
++
+
+ do
+ {
+@@ -1090,7 +1118,7 @@ void
+ 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 +1245,16 @@ memcheck (int addr, int len)
+ 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 -urpN grub-0.97/stage2/graphics.c grub-0.97-gfx/stage2/graphics.c
+--- grub-0.97/stage2/graphics.c 1969-12-31 20:00:00.000000000 -0400
++++ grub-0.97-gfx/stage2/graphics.c 2005-10-13 16:27:35.000000000 -0400
+@@ -0,0 +1,552 @@
++/* graphics.c - graphics mode support for GRUB */
++/* Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
++ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
++ */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2001,2002 Red Hat, Inc.
++ * Portions copyright (C) 2000 Conectiva, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++
++
++#ifdef SUPPORT_GRAPHICS
++
++#include <term.h>
++#include <shared.h>
++#include <graphics.h>
++
++int saved_videomode;
++unsigned char *font8x16;
++
++int graphics_inited = 0;
++static char splashimage[64];
++
++#define VSHADOW VSHADOW1
++unsigned char VSHADOW1[38400];
++unsigned char VSHADOW2[38400];
++unsigned char VSHADOW4[38400];
++unsigned char VSHADOW8[38400];
++
++/* constants to define the viewable area */
++const int x0 = 0;
++const int x1 = 80;
++const int y0 = 0;
++const int y1 = 30;
++
++/* text buffer has to be kept around so that we can write things as we
++ * scroll and the like */
++unsigned short text[80 * 30];
++
++/* why do these have to be kept here? */
++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
++
++/* current position */
++static int fontx = 0;
++static int fonty = 0;
++
++/* global state so that we don't try to recursively scroll or cursor */
++static int no_scroll = 0;
++
++/* color state */
++static int graphics_standard_color = A_NORMAL;
++static int graphics_normal_color = A_NORMAL;
++static int graphics_highlight_color = A_REVERSE;
++static int graphics_current_color = A_NORMAL;
++static color_state graphics_color_state = COLOR_STATE_STANDARD;
++
++
++/* graphics local functions */
++static void graphics_setxy(int col, int row);
++static void graphics_scroll();
++
++/* FIXME: where do these really belong? */
++static inline void outb(unsigned short port, unsigned char val)
++{
++ __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
++}
++
++static void MapMask(int value) {
++ outb(0x3c4, 2);
++ outb(0x3c5, value);
++}
++
++/* bit mask register */
++static void BitMask(int value) {
++ outb(0x3ce, 8);
++ outb(0x3cf, value);
++}
++
++
++
++/* Set the splash image */
++void graphics_set_splash(char *splashfile) {
++ grub_strcpy(splashimage, splashfile);
++}
++
++/* Get the current splash image */
++char *graphics_get_splash(void) {
++ return splashimage;
++}
++
++/* Initialize a vga16 graphics display with the palette based off of
++ * the image in splashimage. If the image doesn't exist, leave graphics
++ * mode. */
++int graphics_init()
++{
++ if (!graphics_inited) {
++ saved_videomode = set_videomode(0x12);
++ }
++
++ if (!read_image(splashimage)) {
++ set_videomode(saved_videomode);
++ grub_printf("failed to read image\n");
++ return 0;
++ }
++
++ font8x16 = (unsigned char*)graphics_get_font();
++
++ graphics_inited = 1;
++
++ /* make sure that the highlight color is set correctly */
++ graphics_highlight_color = ((graphics_normal_color >> 4) |
++ ((graphics_normal_color & 0xf) << 4));
++
++ return 1;
++}
++
++/* Leave graphics mode */
++void graphics_end(void)
++{
++ if (graphics_inited) {
++ set_videomode(saved_videomode);
++ graphics_inited = 0;
++ }
++}
++
++/* Print ch on the screen. Handle any needed scrolling or the like */
++void graphics_putchar(int ch) {
++ ch &= 0xff;
++
++ graphics_cursor(0);
++
++ if (ch == '\n') {
++ if (fonty + 1 < y1)
++ graphics_setxy(fontx, fonty + 1);
++ else
++ graphics_scroll();
++ graphics_cursor(1);
++ return;
++ } else if (ch == '\r') {
++ graphics_setxy(x0, fonty);
++ graphics_cursor(1);
++ return;
++ }
++
++ graphics_cursor(0);
++
++ text[fonty * 80 + fontx] = ch;
++ text[fonty * 80 + fontx] &= 0x00ff;
++ if (graphics_current_color & 0xf0)
++ text[fonty * 80 + fontx] |= 0x100;
++
++ graphics_cursor(0);
++
++ if ((fontx + 1) >= x1) {
++ graphics_setxy(x0, fonty);
++ if (fonty + 1 < y1)
++ graphics_setxy(x0, fonty + 1);
++ else
++ graphics_scroll();
++ } else {
++ graphics_setxy(fontx + 1, fonty);
++ }
++
++ graphics_cursor(1);
++}
++
++/* get the current location of the cursor */
++int graphics_getxy(void) {
++ return (fontx << 8) | fonty;
++}
++
++void graphics_gotoxy(int x, int y) {
++ graphics_cursor(0);
++
++ graphics_setxy(x, y);
++
++ graphics_cursor(1);
++}
++
++void graphics_cls(void) {
++ int i;
++ unsigned char *mem, *s1, *s2, *s4, *s8;
++
++ graphics_cursor(0);
++ graphics_gotoxy(x0, y0);
++
++ mem = (unsigned char*)VIDEOMEM;
++ s1 = (unsigned char*)VSHADOW1;
++ s2 = (unsigned char*)VSHADOW2;
++ s4 = (unsigned char*)VSHADOW4;
++ s8 = (unsigned char*)VSHADOW8;
++
++ for (i = 0; i < 80 * 30; i++)
++ text[i] = ' ';
++ graphics_cursor(1);
++
++ BitMask(0xff);
++
++ /* plano 1 */
++ MapMask(1);
++ grub_memcpy(mem, s1, 38400);
++
++ /* plano 2 */
++ MapMask(2);
++ grub_memcpy(mem, s2, 38400);
++
++ /* plano 3 */
++ MapMask(4);
++ grub_memcpy(mem, s4, 38400);
++
++ /* plano 4 */
++ MapMask(8);
++ grub_memcpy(mem, s8, 38400);
++
++ MapMask(15);
++
++}
++
++void graphics_setcolorstate (color_state state) {
++ switch (state) {
++ case COLOR_STATE_STANDARD:
++ graphics_current_color = graphics_standard_color;
++ break;
++ case COLOR_STATE_NORMAL:
++ graphics_current_color = graphics_normal_color;
++ break;
++ case COLOR_STATE_HIGHLIGHT:
++ graphics_current_color = graphics_highlight_color;
++ break;
++ default:
++ graphics_current_color = graphics_standard_color;
++ break;
++ }
++
++ graphics_color_state = state;
++}
++
++void graphics_setcolor (int normal_color, int highlight_color) {
++ graphics_normal_color = normal_color;
++ graphics_highlight_color = highlight_color;
++
++ graphics_setcolorstate (graphics_color_state);
++}
++
++void graphics_setcursor (int on) {
++ /* FIXME: we don't have a cursor in graphics */
++ return;
++}
++
++/* Read in the splashscreen image and set the palette up appropriately.
++ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
++ * 640x480. */
++int read_image(char *s)
++{
++ char buf[32], pal[16];
++ unsigned char c, base, mask, *s1, *s2, *s4, *s8;
++ unsigned i, len, idx, colors, x, y, width, height;
++
++ if (!grub_open(s))
++ return 0;
++
++ /* read header */
++ if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
++ grub_close();
++ return 0;
++ }
++
++ /* parse info */
++ while (grub_read(&c, 1)) {
++ if (c == '"')
++ break;
++ }
++
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ i = 0;
++ width = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ width = width * 10 + c - '0';
++ else
++ break;
++ }
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ height = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ height = height * 10 + c - '0';
++ else
++ break;
++ }
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ colors = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ colors = colors * 10 + c - '0';
++ else
++ break;
++ }
++
++ base = 0;
++ while (grub_read(&c, 1) && c != '"')
++ ;
++
++ /* palette */
++ for (i = 0, idx = 1; i < colors; i++) {
++ len = 0;
++
++ while (grub_read(&c, 1) && c != '"')
++ ;
++ grub_read(&c, 1); /* char */
++ base = c;
++ grub_read(buf, 4); /* \t c # */
++
++ while (grub_read(&c, 1) && c != '"') {
++ if (len < sizeof(buf))
++ buf[len++] = c;
++ }
++
++ if (len == 6 && idx < 15) {
++ int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
++ int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
++ int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
++
++ pal[idx] = base;
++ graphics_set_palette(idx, r, g, b);
++ ++idx;
++ }
++ }
++
++ x = y = len = 0;
++
++ s1 = (unsigned char*)VSHADOW1;
++ s2 = (unsigned char*)VSHADOW2;
++ s4 = (unsigned char*)VSHADOW4;
++ s8 = (unsigned char*)VSHADOW8;
++
++ for (i = 0; i < 38400; i++)
++ s1[i] = s2[i] = s4[i] = s8[i] = 0;
++
++ /* parse xpm data */
++ while (y < height) {
++ while (1) {
++ if (!grub_read(&c, 1)) {
++ grub_close();
++ return 0;
++ }
++ if (c == '"')
++ break;
++ }
++
++ while (grub_read(&c, 1) && c != '"') {
++ for (i = 1; i < 15; i++)
++ if (pal[i] == c) {
++ c = i;
++ break;
++ }
++
++ mask = 0x80 >> (x & 7);
++ if (c & 1)
++ s1[len + (x >> 3)] |= mask;
++ if (c & 2)
++ s2[len + (x >> 3)] |= mask;
++ if (c & 4)
++ s4[len + (x >> 3)] |= mask;
++ if (c & 8)
++ s8[len + (x >> 3)] |= mask;
++
++ if (++x >= 640) {
++ x = 0;
++
++ if (y < 480)
++ len += 80;
++ ++y;
++ }
++ }
++ }
++
++ grub_close();
++
++ graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
++ background & 63);
++ graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
++ foreground & 63);
++ graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63,
++ border & 63);
++
++ return 1;
++}
++
++
++/* Convert a character which is a hex digit to the appropriate integer */
++int hex(int v)
++{
++ if (v >= 'A' && v <= 'F')
++ return (v - 'A' + 10);
++ if (v >= 'a' && v <= 'f')
++ return (v - 'a' + 10);
++ return (v - '0');
++}
++
++
++/* move the graphics cursor location to col, row */
++static void graphics_setxy(int col, int row) {
++ if (col >= x0 && col < x1) {
++ fontx = col;
++ cursorX = col << 3;
++ }
++ if (row >= y0 && row < y1) {
++ fonty = row;
++ cursorY = row << 4;
++ }
++}
++
++/* scroll the screen */
++static void graphics_scroll() {
++ int i, j;
++
++ /* we don't want to scroll recursively... that would be bad */
++ if (no_scroll)
++ return;
++ no_scroll = 1;
++
++ /* move everything up a line */
++ for (j = y0 + 1; j < y1; j++) {
++ graphics_gotoxy(x0, j - 1);
++ for (i = x0; i < x1; i++) {
++ graphics_putchar(text[j * 80 + i]);
++ }
++ }
++
++ /* last line should be blank */
++ graphics_gotoxy(x0, y1 - 1);
++ for (i = x0; i < x1; i++)
++ graphics_putchar(' ');
++ graphics_setxy(x0, y1 - 1);
++
++ no_scroll = 0;
++}
++
++
++void graphics_cursor(int set) {
++ unsigned char *pat, *mem, *ptr, chr[16 << 2];
++ int i, ch, invert, offset;
++
++ if (set && no_scroll)
++ return;
++
++ offset = cursorY * 80 + fontx;
++ ch = text[fonty * 80 + fontx] & 0xff;
++ invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
++ pat = font8x16 + (ch << 4);
++
++ mem = (unsigned char*)VIDEOMEM + offset;
++
++ if (!set) {
++ for (i = 0; i < 16; i++) {
++ unsigned char mask = pat[i];
++
++ if (!invert) {
++ chr[i ] = ((unsigned char*)VSHADOW1)[offset];
++ chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
++ chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
++ chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
++
++ /* FIXME: if (shade) */
++ if (1) {
++ if (ch == DISP_VERT || ch == DISP_LL ||
++ ch == DISP_UR || ch == DISP_LR) {
++ unsigned char pmask = ~(pat[i] >> 1);
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ }
++ if (i > 0 && ch != DISP_VERT) {
++ unsigned char pmask = ~(pat[i - 1] >> 1);
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
++ pmask = ~pat[i - 1];
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ }
++ }
++ }
++ chr[i ] |= mask;
++ chr[16 + i] |= mask;
++ chr[32 + i] |= mask;
++ chr[48 + i] |= mask;
++
++ offset += 80;
++ }
++ else {
++ chr[i ] = mask;
++ chr[16 + i] = mask;
++ chr[32 + i] = mask;
++ chr[48 + i] = mask;
++ }
++ }
++ }
++ else {
++ MapMask(15);
++ ptr = mem;
++ for (i = 0; i < 16; i++, ptr += 80) {
++ cursorBuf[i] = pat[i];
++ *ptr = ~pat[i];
++ }
++ return;
++ }
++
++ offset = 0;
++ for (i = 1; i < 16; i <<= 1, offset += 16) {
++ int j;
++
++ MapMask(i);
++ ptr = mem;
++ for (j = 0; j < 16; j++, ptr += 80)
++ *ptr = chr[j + offset];
++ }
++
++ MapMask(15);
++}
++
++#endif /* SUPPORT_GRAPHICS */
+diff -urpN grub-0.97/stage2/graphics.h grub-0.97-gfx/stage2/graphics.h
+--- grub-0.97/stage2/graphics.h 1969-12-31 20:00:00.000000000 -0400
++++ grub-0.97-gfx/stage2/graphics.h 2005-10-13 16:27:35.000000000 -0400
+@@ -0,0 +1,42 @@
++/* graphics.h - graphics console interface */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2002 Free Software Foundation, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef GRAPHICS_H
++#define GRAPHICS_H
++
++/* magic constant */
++#define VIDEOMEM 0xA0000
++
++/* function prototypes */
++char *graphics_get_splash(void);
++
++int read_image(char *s);
++void graphics_cursor(int set);
++
++/* function prototypes for asm functions */
++void * graphics_get_font();
++void graphics_set_palette(int idx, int red, int green, int blue);
++void set_int1c_handler();
++void unset_int1c_handler();
++
++extern short cursorX, cursorY;
++extern char cursorBuf[16];
++
++#endif /* GRAPHICS_H */
+diff -urpN grub-0.97/stage2/shared.h grub-0.97-gfx/stage2/shared.h
+--- grub-0.97/stage2/shared.h 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/shared.h 2005-10-13 16:27:35.000000000 -0400
+@@ -871,6 +871,7 @@ int grub_sprintf (char *buffer, const ch
+ 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 -urpN grub-0.97/stage2/stage2.c grub-0.97-gfx/stage2/stage2.c
+--- grub-0.97/stage2/stage2.c 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/stage2.c 2005-10-13 16:27:35.000000000 -0400
+@@ -233,6 +233,7 @@ run_menu (char *menu_entries, char *conf
+ {
+ int c, time1, time2 = -1, first_entry = 0;
+ char *cur_entry = 0;
++ struct term_entry *prev_term = NULL;
+
+ /*
+ * Main loop for menu UI.
+@@ -714,6 +715,15 @@ restart:
+
+ 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 +758,13 @@ restart:
+ 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 +1067,10 @@ cmain (void)
+ while (is_preset);
+ }
+
++ /* go ahead and make sure the terminal is setup */
++ if (current_term->startup)
++ (*current_term->startup)();
++
+ if (! num_entries)
+ {
+ /* If no acceptable config file, goto command-line, starting
+diff -urpN grub-0.97/stage2/term.h grub-0.97-gfx/stage2/term.h
+--- grub-0.97/stage2/term.h 2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/term.h 2005-10-13 16:27:35.000000000 -0400
+@@ -60,6 +60,8 @@ struct term_entry
+ const char *name;
+ /* The feature flags defined above. */
+ unsigned long flags;
++ /* Default for maximum number of lines if not specified */
++ unsigned short max_lines;
+ /* Put a character. */
+ void (*putchar) (int c);
+ /* Check if any input character is available. */
+@@ -79,6 +81,11 @@ struct term_entry
+ void (*setcolor) (int normal_color, int highlight_color);
+ /* Turn on/off the cursor. */
+ int (*setcursor) (int on);
++
++ /* function to start a terminal */
++ int (*startup) (void);
++ /* function to use to shutdown a terminal */
++ void (*shutdown) (void);
+ };
+
+ /* This lists up available terminals. */
+@@ -124,4 +131,23 @@ void hercules_setcolor (int normal_color
+ int hercules_setcursor (int on);
+ #endif
+
++#ifdef SUPPORT_GRAPHICS
++extern int foreground, background, border, graphics_inited;
++
++void graphics_set_splash(char *splashfile);
++int set_videomode (int mode);
++void graphics_putchar (int c);
++int graphics_getxy(void);
++void graphics_gotoxy(int x, int y);
++void graphics_cls(void);
++void graphics_setcolorstate (color_state state);
++void graphics_setcolor (int normal_color, int highlight_color);
++void graphics_setcursor (int on);
++int graphics_init(void);
++void graphics_end(void);
++
++int hex(int v);
++void graphics_set_palette(int idx, int red, int green, int blue);
++#endif /* SUPPORT_GRAPHICS */
++
+ #endif /* ! GRUB_TERM_HEADER */