On Tue, 2002-12-31 at 11:44, Jason Thomas wrote:
> actually the copyright thing is so it can be included upstream. I'd
> prefer if it was not a debian thing. 
> 
> okuji do you think its possible to include the splashimage stuff if the
> author supports it?

For more information on the current status of the splashimage stuff as
far as I'm concerned --

I've updated it a bit for 0.93 so that instead of adding the concept of
a display, it's instead just another terminal type (the terminal
framework made this the obvious thing to do).  I also dropped out some
of the functionality which touched lots of code but which we don't use
at Red Hat just to ease the maintenance for me.  

As far as support is concerned, at this point, I'm pretty much tied to
supporting it whether it goes in mainline or not, so if Okuji is willing
to include it, I can probably be easily convinced to support it.

Attached is the current diff (well, this doesn't have the help and there
might have been one other support patch that was related to the graphics
stuff, but I'm about to head out the door so can't check right now) to
show the state of things.  A few things to keep in mind: 1) I know all
of the indentation doesn't match the rest of GRUB, easy to fix if it's
to be included, I was just kind of going on autopilot :)  2) there are
definitely some enhancements that could be made to this if someone were
sufficiently enterprising 

Jeremy

--- grub-0.93/stage2/Makefile.am.graphics       2002-12-28 23:37:03.000000000 -0500
+++ grub-0.93/stage2/Makefile.am        2002-12-28 23:37:03.000000000 -0500
@@ -7,7 +7,7 @@
         fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
        imgact_aout.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 vstafs.h xfs.h
+       tparm.h nbi.h vstafs.h xfs.h graphics.h
 EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
 
 # For <stage1.h>.
@@ -18,7 +18,7 @@
 libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \
        disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_jfs.c \
        fsys_minix.c fsys_reiserfs.c fsys_vstafs.c fsys_xfs.c gunzip.c \
-       md5.c serial.c stage2.c terminfo.c tparm.c
+       md5.c serial.c stage2.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_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 -DFSYS_VSTAFS=1 \
@@ -75,8 +75,14 @@
 HERCULES_FLAGS =
 endif
 
+if GRAPHICS_SUPPORT
+GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1
+else
+GRAPHICS_FLAGS =
+endif
+
 STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-       $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
+       $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
 
 STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
 STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
@@ -86,7 +92,7 @@
        cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
        fsys_fat.c fsys_ffs.c fsys_jfs.c fsys_minix.c fsys_reiserfs.c \
        fsys_vstafs.c fsys_xfs.c gunzip.c hercules.c md5.c serial.c \
-       smp-imps.c stage2.c terminfo.c tparm.c
+       smp-imps.c stage2.c terminfo.c tparm.c graphics.c
 pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
 pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
 pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
--- grub-0.93/stage2/asm.S.graphics     2002-12-28 23:37:03.000000000 -0500
+++ grub-0.93/stage2/asm.S      2002-12-28 23:37:03.000000000 -0500
@@ -2224,6 +2224,156 @@
        pop     %ebx
        pop     %ebp
        ret
+
+/* graphics mode functions */
+#ifdef SUPPORT_GRAPHICS
+VARIABLE(cursorX)
+.word  0
+VARIABLE(cursorY)
+.word  0
+VARIABLE(cursorCount)
+.word 0
+VARIABLE(cursorBuf)
+.byte  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+       
+/*
+ * int set_videomode(mode)
+ * BIOS call "INT 10H Function 0h" to set video mode
+ *     Call with       %ah = 0x0
+ *                     %al = video mode
+ *      Returns old videomode.
+ */
+ENTRY(set_videomode)
+       push    %ebp
+       push    %ebx
+       push    %ecx
+
+       movb    0x10(%esp), %cl
+
+       call    EXT_C(prot_to_real)
+       .code16
+
+       xorw    %bx, %bx
+       movb    $0xf, %ah
+       int     $0x10                   /* Get Current Video mode */
+       movb    %al, %ch
+       xorb    %ah, %ah
+       movb    %cl, %al
+        int    $0x10                   /* Set Video mode */
+
+       DATA32  call    EXT_C(real_to_prot)
+       .code32
+
+       xorb    %ah, %ah
+       movb    %ch, %al
+
+       pop     %ecx
+       pop     %ebx
+       pop     %ebp
+       ret
+
+
+/*
+ * unsigned char * graphics_get_font()
+ * BIOS call "INT 10H Function 11h" to set font
+ *      Call with       %ah = 0x11
+ */
+ENTRY(graphics_get_font)
+       push    %ebp
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       call    EXT_C(prot_to_real)
+       .code16
+
+       movw    $0x1130, %ax
+       movb    $6, %bh         /* font 8x16 */
+       int     $0x10
+       movw    %bp, %dx
+       movw    %es, %cx
+
+       DATA32  call    EXT_C(real_to_prot)
+       .code32
+
+       xorl    %eax, %eax
+       movw    %cx, %ax
+       shll    $4, %eax
+       movw    %dx, %ax
+
+       pop     %edx
+       pop     %ecx
+       pop     %ebx
+       pop     %ebp
+       ret
+       
+
+       
+/*
+ * graphics_set_palette(index, red, green, blue)
+ * BIOS call "INT 10H Function 10h" to set individual dac register
+ *     Call with       %ah = 0x10
+ *                     %bx = register number
+ *                     %ch = new value for green (0-63)
+ *                     %cl = new value for blue (0-63)
+ *                     %dh = new value for red (0-63)
+ */
+
+ENTRY(graphics_set_palette)
+       push    %ebp
+       push    %eax
+       push    %ebx
+       push    %ecx
+       push    %edx
+
+       movw    $0x3c8, %bx             /* address write mode register */
+
+       /* wait vertical retrace */
+
+       movw    $0x3da, %dx
+l1b:   inb     %dx, %al        /* wait vertical active display */
+       test    $8, %al
+       jnz     l1b
+
+l2b:   inb     %dx, %al        /* wait vertical retrace */
+       test    $8, %al
+       jnz     l2b
+
+       mov     %bx, %dx
+       movb    0x18(%esp), %al         /* index */
+       outb    %al, %dx
+       inc     %dx
+
+       movb    0x1c(%esp), %al         /* red */
+       outb    %al, %dx
+
+       movb    0x20(%esp), %al         /* green */
+       outb    %al, %dx
+
+       movb    0x24(%esp), %al         /* blue */
+       outb    %al, %dx
+
+       movw    0x18(%esp), %bx
+
+       call    EXT_C(prot_to_real)
+       .code16
+
+       movb    %bl, %bh
+       movw    $0x1000, %ax
+       int     $0x10
+
+       DATA32  call    EXT_C(real_to_prot)
+       .code32 
+
+       pop     %edx
+       pop     %ecx
+       pop     %ebx
+       pop     %eax
+       pop     %ebp
+       ret
+
+#endif /* SUPPORT_GRAPHICS */
                
 /*
  * getrtsecs()
--- grub-0.93/stage2/builtins.c.graphics        2002-12-28 23:37:03.000000000 -0500
+++ grub-0.93/stage2/builtins.c 2002-12-28 23:37:03.000000000 -0500
@@ -857,6 +857,138 @@
 };
 #endif /* SUPPORT_NETBOOT */
 
+static int terminal_func (char *arg, int flags);
+
+#ifdef SUPPORT_GRAPHICS
+
+static int splashimage_func(char *arg, int flags) {
+    char splashimage[64];
+    int i;
+    
+    /* filename can only be 64 characters due to our buffer size */
+    if (strlen(arg) > 63)
+       return 1;
+    if (flags == BUILTIN_CMDLINE) {
+       if (!grub_open(arg))
+           return 1;
+       grub_close();
+    }
+
+    strcpy(splashimage, arg);
+
+    /* get rid of TERM_NEED_INIT from the graphics terminal. */
+    for (i = 0; term_table[i].name; i++) {
+       if (grub_strcmp (term_table[i].name, "graphics") == 0) {
+           term_table[i].flags &= ~TERM_NEED_INIT;
+           break;
+       }
+    }
+    
+    graphics_set_splash(splashimage);
+
+    if (flags == BUILTIN_CMDLINE && graphics_inited) {
+       graphics_end();
+       graphics_init();
+       graphics_cls();
+    }
+
+    /* FIXME: should we be explicitly switching the terminal as a 
+     * side effect here? */
+    terminal_func("graphics", flags);
+
+    return 0;
+}
+
+static struct builtin builtin_splashimage =
+{
+  "splashimage",
+  splashimage_func,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "splashimage FILE",
+  "Load FILE as the background image when in graphics mode."
+};
+
+
+/* foreground */
+static int
+foreground_func(char *arg, int flags)
+{
+    if (grub_strlen(arg) == 6) {
+       int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
+       int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
+       int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
+
+       foreground = (r << 16) | (g << 8) | b;
+       if (graphics_inited)
+           graphics_set_palette(15, r, g, b);
+
+       return (0);
+    }
+
+    return (1);
+}
+
+static struct builtin builtin_foreground =
+{
+  "foreground",
+  foreground_func,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "foreground RRGGBB",
+  "Sets the foreground color when in graphics mode."
+  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
+};
+
+
+/* background */
+static int
+background_func(char *arg, int flags)
+{
+    if (grub_strlen(arg) == 6) {
+       int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
+       int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
+       int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
+
+       background = (r << 16) | (g << 8) | b;
+       if (graphics_inited)
+           graphics_set_palette(0, r, g, b);
+       return (0);
+    }
+
+    return (1);
+}
+
+static struct builtin builtin_background =
+{
+  "background",
+  background_func,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "background RRGGBB",
+  "Sets the background color when in graphics mode."
+  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
+};
+
+#endif /* SUPPORT_GRAPHICS */
+
+
+/* clear */
+static int 
+clear_func() 
+{
+  if (current_term->cls)
+    current_term->cls();
+
+  return 0;
+}
+
+static struct builtin builtin_clear =
+{
+  "clear",
+  clear_func,
+  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+  "clear",
+  "Clear the screen"
+};
+
 
 /* displayapm */
 static int
@@ -4071,7 +4203,7 @@
 };
 
 
-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
 /* terminal */
 static int
 terminal_func (char *arg, int flags)
@@ -4230,17 +4362,21 @@
  end:
   current_term = term_table + default_term;
   current_term->flags = term_flags;
-  
+
   if (lines)
     max_lines = lines;
   else
-    /* 24 would be a good default value.  */
-    max_lines = 24;
-  
+    max_lines = current_term->max_lines;
+
   /* If the interface is currently the command-line,
      restart it to repaint the screen.  */
-  if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
+  if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
+    if (prev_term->shutdown)
+      prev_term->shutdown();
+    if (current_term->startup)
+      current_term->startup();
     grub_longjmp (restart_cmdline_env, 0);
+  }
   
   return 0;
 }
@@ -4250,7 +4386,7 @@
   "terminal",
   terminal_func,
   BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-  "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] 
[--silent] [console] [serial] [hercules]",
+  "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] 
+[--silent] [console] [serial] [hercules] [graphics]",
   "Select a terminal. When multiple terminals are specified, wait until"
   " you push any key to continue. If both console and serial are specified,"
   " the terminal to which you input a key first will be selected. If no"
@@ -4262,7 +4398,7 @@
   " seconds. The option --lines specifies the maximum number of lines."
   " The option --silent is used to suppress messages."
 };
-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
 
 
 #ifdef SUPPORT_SERIAL
@@ -4785,6 +4921,9 @@
 /* The table of builtin commands. Sorted in dictionary order.  */
 struct builtin *builtin_table[] =
 {
+#ifdef SUPPORT_GRAPHICS
+  &builtin_background,
+#endif
   &builtin_blocklist,
   &builtin_boot,
 #ifdef SUPPORT_NETBOOT
@@ -4792,6 +4931,7 @@
 #endif /* SUPPORT_NETBOOT */
   &builtin_cat,
   &builtin_chainloader,
+  &builtin_clear,
   &builtin_cmp,
   &builtin_color,
   &builtin_configfile,
@@ -4811,6 +4951,9 @@
   &builtin_embed,
   &builtin_fallback,
   &builtin_find,
+#ifdef SUPPORT_GRAPHICS
+  &builtin_foreground,
+#endif
   &builtin_fstest,
   &builtin_geometry,
   &builtin_halt,
@@ -4854,9 +4997,12 @@
 #endif /* SUPPORT_SERIAL */
   &builtin_setkey,
   &builtin_setup,
-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
+#ifdef SUPPORT_GRAPHICS
+  &builtin_splashimage,
+#endif /* SUPPORT_GRAPHICS */
+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
   &builtin_terminal,
-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
 #ifdef SUPPORT_SERIAL
   &builtin_terminfo,
 #endif /* SUPPORT_SERIAL */
--- grub-0.93/stage2/char_io.c.graphics 2002-12-02 18:49:07.000000000 -0500
+++ grub-0.93/stage2/char_io.c  2002-12-28 23:37:03.000000000 -0500
@@ -35,6 +35,7 @@
     {
       "console",
       0,
+      24,
       console_putchar,
       console_checkkey,
       console_getkey,
@@ -43,13 +44,16 @@
       console_cls,
       console_setcolorstate,
       console_setcolor,
-      console_setcursor
+      console_setcursor,
+      0, 
+      0
     },
 #ifdef SUPPORT_SERIAL
     {
       "serial",
       /* A serial device must be initialized.  */
       TERM_NEED_INIT,
+      24,
       serial_putchar,
       serial_checkkey,
       serial_getkey,
@@ -58,6 +62,8 @@
       serial_cls,
       serial_setcolorstate,
       0,
+      0,
+      0, 
       0
     },
 #endif /* SUPPORT_SERIAL */
@@ -65,6 +71,7 @@
     {
       "hercules",
       0,
+      24,
       hercules_putchar,
       console_checkkey,
       console_getkey,
@@ -73,9 +80,28 @@
       hercules_cls,
       hercules_setcolorstate,
       hercules_setcolor,
-      hercules_setcursor
+      hercules_setcursor,
+      0,
+      0
     },      
 #endif /* SUPPORT_HERCULES */
+#ifdef SUPPORT_GRAPHICS
+    { "graphics",
+      TERM_NEED_INIT, /* flags */
+      30, /* number of lines */
+      graphics_putchar, /* putchar */
+      console_checkkey, /* checkkey */
+      console_getkey, /* getkey */
+      graphics_getxy, /* getxy */
+      graphics_gotoxy, /* gotoxy */
+      graphics_cls, /* cls */
+      graphics_setcolorstate, /* setcolorstate */
+      graphics_setcolor, /* setcolor */
+      graphics_setcursor, /* nocursor */
+      graphics_init, /* initialize */
+      graphics_end /* shutdown */
+    },
+#endif /* SUPPORT_GRAPHICS */
     /* This must be the last entry.  */
     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
   };
@@ -1039,13 +1065,15 @@
                 the following grub_printf call will print newlines.  */
              count_lines = -1;
 
+             grub_printf("\n");
              if (current_term->setcolorstate)
                current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
              
-             grub_printf ("\n[Hit return to continue]");
+             grub_printf ("[Hit return to continue]");
 
              if (current_term->setcolorstate)
                current_term->setcolorstate (COLOR_STATE_NORMAL);
+               
              
              do
                {
@@ -1083,7 +1111,7 @@
 cls (void)
 {
   /* If the terminal is dumb, there is no way to clean the terminal.  */
-  if (current_term->flags & TERM_DUMB)
+  if (current_term->flags & TERM_DUMB) 
     grub_putchar ('\n');
   else
     current_term->cls ();
@@ -1207,6 +1235,16 @@
   return ! errnum;
 }
 
+void
+grub_memcpy(void *dest, const void *src, int len)
+{
+  int i;
+  register char *d = (char*)dest, *s = (char*)src;
+
+  for (i = 0; i < len; i++)
+    d[i] = s[i];
+}
+
 void *
 grub_memmove (void *to, const void *from, int len)
 {
--- /dev/null   2002-10-04 14:48:04.000000000 -0400
+++ grub-0.93/stage2/graphics.c 2002-12-28 23:37:03.000000000 -0500
@@ -0,0 +1,552 @@
+/* graphics.c - graphics mode support for GRUB */
+/* Implemented as a terminal type by Jeremy Katz <[EMAIL PROTECTED]> based
+ * on a patch by Paulo César Pereira de Andrade <[EMAIL PROTECTED]>
+ */
+/*
+ *  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 */
--- /dev/null   2002-10-04 14:48:04.000000000 -0400
+++ grub-0.93/stage2/graphics.h 2002-12-28 23:37:03.000000000 -0500
@@ -0,0 +1,42 @@
+/* graphics.h - graphics console interface */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRAPHICS_H
+#define GRAPHICS_H
+
+/* magic constant */
+#define VIDEOMEM 0xA0000
+
+/* function prototypes */
+char *graphics_get_splash(void);
+
+int read_image(char *s);
+void graphics_cursor(int set);
+
+/* function prototypes for asm functions */
+void * graphics_get_font();
+void graphics_set_palette(int idx, int red, int green, int blue);
+void set_int1c_handler();
+void unset_int1c_handler();
+
+extern short cursorX, cursorY;
+extern char cursorBuf[16];
+
+#endif /* GRAPHICS_H */
--- grub-0.93/stage2/shared.h.graphics  2002-12-28 23:37:03.000000000 -0500
+++ grub-0.93/stage2/shared.h   2002-12-28 23:37:03.000000000 -0500
@@ -856,6 +856,7 @@
 int grub_tolower (int c);
 int grub_isspace (int c);
 int grub_strncat (char *s1, const char *s2, int n);
+void grub_memcpy(void *dest, const void *src, int len);
 void *grub_memmove (void *to, const void *from, int len);
 void *grub_memset (void *start, int c, int len);
 int grub_strncat (char *s1, const char *s2, int n);
--- grub-0.93/stage2/stage2.c.graphics  2002-12-28 23:37:03.000000000 -0500
+++ grub-0.93/stage2/stage2.c   2002-12-28 23:37:03.000000000 -0500
@@ -233,6 +233,7 @@
 {
   int c, time1, time2 = -1, first_entry = 0;
   char *cur_entry = 0;
+  struct term_entry *prev_term = NULL;
 
   /*
    *  Main loop for menu UI.
@@ -807,6 +808,15 @@
   
   cls ();
   setcursor (1);
+  /* if our terminal needed initialization, we should shut it down
+   * before booting the kernel, but we want to save what it was so
+   * we can come back if needed */
+  prev_term = current_term;
+  if (current_term->shutdown) 
+    {
+      (*current_term->shutdown)();
+      current_term = term_table; /* assumption: console is first */
+    }
   
   while (1)
     {
@@ -838,6 +848,13 @@
        break;
     }
 
+  /* if we get back here, we should go back to what our term was before */
+  current_term = prev_term;
+  if (current_term->startup)
+      /* if our terminal fails to initialize, fall back to console since
+       * it should always work */
+      if ((*current_term->startup)() == 0)
+          current_term = term_table; /* we know that console is first */
   show_menu = 1;
   goto restart;
 }
@@ -1082,6 +1099,10 @@
          while (is_preset);
        }
 
+      /* go ahead and make sure the terminal is setup */
+      if (current_term->startup)
+        (*current_term->startup)();
+
       if (! num_entries)
        {
          /* If no acceptable config file, goto command-line, starting
--- grub-0.93/stage2/term.h.graphics    2002-12-02 17:55:13.000000000 -0500
+++ grub-0.93/stage2/term.h     2002-12-28 23:37:03.000000000 -0500
@@ -60,6 +60,8 @@
   const char *name;
   /* The feature flags defined above.  */
   unsigned long flags;
+  /* Default for maximum number of lines if not specified */
+  unsigned short max_lines;
   /* Put a character.  */
   void (*putchar) (int c);
   /* Check if any input character is available.  */
@@ -79,6 +81,11 @@
   void (*setcolor) (int normal_color, int highlight_color);
   /* Turn on/off the cursor.  */
   int (*setcursor) (int on);
+
+  /* function to start a terminal */
+  int (*startup) (void);
+  /* function to use to shutdown a terminal */
+  void (*shutdown) (void);
 };
 
 /* This lists up available terminals.  */
@@ -124,4 +131,23 @@
 int hercules_setcursor (int on);
 #endif
 
+#ifdef SUPPORT_GRAPHICS
+extern int foreground, background, border, graphics_inited;
+
+void graphics_set_splash(char *splashfile);
+int set_videomode (int mode);
+void graphics_putchar (int c);
+int graphics_getxy(void);
+void graphics_gotoxy(int x, int y);
+void graphics_cls(void);
+void graphics_setcolorstate (color_state state);
+void graphics_setcolor (int normal_color, int highlight_color);
+void graphics_setcursor (int on);
+int graphics_init(void);
+void graphics_end(void);
+
+int hex(int v);
+void graphics_set_palette(int idx, int red, int green, int blue);
+#endif /* SUPPORT_GRAPHICS */
+
 #endif /* ! GRUB_TERM_HEADER */
--- grub-0.93/configure.in.graphics     2002-12-28 23:37:03.000000000 -0500
+++ grub-0.93/configure.in      2002-12-28 23:37:03.000000000 -0500
@@ -559,6 +559,11 @@
   [  --enable-diskless       enable diskless support])
 AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
 
+dnl Graphical splashscreen support
+AC_ARG_ENABLE(graphics,
+  [  --disable-graphics      disable graphics terminal support])
+AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
+
 dnl Hercules terminal
 AC_ARG_ENABLE(hercules,
   [  --disable-hercules      disable hercules terminal support])
_______________________________________________
Bug-grub mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/bug-grub

Reply via email to