grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

New patch for video subsystem...


From: Vesa Jääskeläinen
Subject: New patch for video subsystem...
Date: Thu, 02 Mar 2006 21:28:14 +0200
User-agent: Thunderbird 1.5 (Windows/20051201)

Hi,

Here is the newest modifications to video subsystem.

In short:
This patch adds support for video driver interface, example driver for
VBE, new video terminal (framebuffer terminal) using this video subsystem.

Longer description:
This patch implements most of the functionality described in grub's wiki
(http://grub.enbug.org/VideoSubsystem). There are still some issues left
to be implemented, but in my opinion it would be more important in this
point to get feedback about it and test how well it works on other
systems. Currently speed has not been target, only the functionality, so
some operations will take more time than would be nice. There is support
for index color and RGB modes. Video driver interface consist of video
module (video/video.c) that will forward all queries to active driver
and then interface definition (include/grub/video.h).

There is an example driver that implements VESA Bios Extension 2.0
support, only to framebuffer modes (video/i386/pc/vbe.c). It also
contains some support functionality for MultiBoot standard as it needs
some VBE fields.

There is implementaion for video terminal (term/videoterm.c) that has
basic support for rendering graphical terminal with two layers (actually
background layer is just a plain color, but other source could also be
used). Enhancing functionality the videoterm at this point is quite
easy, we just need to know what we want.

At this stage I think it would be Ok, to start to write drivers for
other architectures so we can have common video terminal.

How to use it:
In order to have graphical console, you need to first load video driver
(that would be vbe module) and then load videoterm module. After that
you will need to tell what video mode you would like to use. And last
you just initialize it with "terminal videoterm".

Example command sequence:
insmod font
font /boot/grub/unifont.pff
insmod terminal
insmod vbe
insmod videoterm
set video_mode=1024x768
terminal videoterm

How to fine tune video mode:
Handling of video_mode environment variable is a flexible one. You can
specify multiple settings at one line. If video_mode is not set, it will
use 1024x768 as a default resolution and will use highes number of
colors available. Supported options are following:

width=<value>
height=<value>
index
rgb
<width>x<height>x<depth>

And you can make combo's of those like:

set video_mode="width=1024 height=768 rgb"

It would tell driver to only look for RGB modes in that size.

Thanks,
Vesa Jääskeläinen
diff -ruN -x '*CVS*' grub2/ChangeLog grub2.new/ChangeLog
--- grub2/ChangeLog     2006-02-09 00:42:47.000000000 +0200
+++ grub2.new/ChangeLog 2006-03-02 20:40:51.346248120 +0200
@@ -1,3 +1,102 @@
+2006-02-25  Vesa Jaaskelainen  <address@hidden>
+
+       * DISTLIST: Added include/grub/video.h, term/videoterm.c,
+       video/video.c.
+       Removed term/i386/pc/vesafb.c.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
+       videoterm.mod.
+       Removed vga.mod, vesafb.mod.
+       (video_mod_SOURCES): Added.
+       (video_mod_CFLAGS): Added.
+       (video_mod_LDFLAGS): Added.
+       (videoterm_mod_SOURCES): Added.
+       (videoterm_mod_CFLAGS): Added.
+       (videoterm_mod_LDFLAGS): Added.
+       (vesafb_mod_SOURCES): Removed.
+       (vesafb_mod_CFLAGS): Removed.
+       (vesafb_mod_LDFLAGS): Removed.
+       (vga_mod_SOURCES): Removed.
+       (vga_mod_CFLAGS): Removed.
+       (vga_mod_LDFLAGS): Removed.
+
+       * font/manager.c (fill_with_default_glyph): Modified to use
+       grub_font_glyph.
+       (grub_font_get_glyph): Modified to use grub_font_glyph.
+       (fontmanager): Renamed to font_manager.
+
+       * include/grub/font.h (grub_font_glyph): Added.
+       (grub_font_get_glyph) Modified to use grub_font_glyph.
+
+       * include/grub/misc.h (grub_abs): Added as inline function.
+
+       * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): Added.
+       (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
+       (grub_vbe_get_controller_info): Renamed to
+       grub_vbe_bios_get_controller_info.
+       (grub_vbe_get_mode_info): Renamed to grub_vbe_bios_get_mode_info.
+       (grub_vbe_set_mode): Renamed to grub_vbe_bios_set_mode.
+       (grub_vbe_get_mode): Renamed to grub_vbe_bios_get_mode.
+       (grub_vbe_set_memory_window): Renamed to
+       grub_vbe_bios_set_memory_window.
+       (grub_vbe_get_memory_window): Renamed to
+       grub_vbe_bios_get_memory_window.
+       (grub_vbe_set_scanline_length): Renamed to
+       grub_vbe_set_scanline_length.
+       (grub_vbe_get_scanline_length): Renamed to
+       grub_vbe_bios_get_scanline_length.
+       (grub_vbe_set_display_start): Renamed to
+       grub_vbe_bios_set_display_start.
+       (grub_vbe_get_display_start): Renamed to
+       grub_vbe_bios_get_display_start.
+       (grub_vbe_set_palette_data): Renamed to
+       grub_vbe_bios_set_palette_data.
+       (grub_vbe_set_pixel_rgb): Removed.
+       (grub_vbe_set_pixel_index): Likewise.
+
+       * include/grub/video.h: Added.
+
+       * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed to
+       grub_vbe_bios_get_controller_info.
+       (grub_vbe_get_mode_info): Renamed to grub_vbe_bios_get_mode_info.
+       (grub_vbe_set_mode): Renamed to grub_vbe_bios_set_mode.
+       (grub_vbe_get_mode): Renamed to grub_vbe_bios_get_mode.
+       (grub_vbe_set_memory_window): Renamed to
+       grub_vbe_bios_set_memory_window.
+       (grub_vbe_get_memory_window): Renamed to
+       grub_vbe_bios_get_memory_window.
+       (grub_vbe_set_scanline_length): Renamed to
+       grub_vbe_set_scanline_length.
+       (grub_vbe_get_scanline_length): Renamed to
+       grub_vbe_bios_get_scanline_length.
+       (grub_vbe_set_display_start): Renamed to
+       grub_vbe_bios_set_display_start.
+       (grub_vbe_get_display_start): Renamed to
+       grub_vbe_bios_get_display_start.
+       (grub_vbe_set_palette_data): Renamed to
+       grub_vbe_bios_set_palette_data.
+       (grub_vbe_bios_get_controller_info): Fixed problem with registers
+       getting corrupted after calling it. Added more pushes and pops.
+       (grub_vbe_bios_set_mode): Likewise.
+       (grub_vbe_bios_get_mode): Likewise.
+       (grub_vbe_bios_get_memory_window): Likewise.
+       (grub_vbe_bios_set_scanline_length): Likewise.
+       (grub_vbe_bios_get_scanline_length): Likewise.
+       (grub_vbe_bios_get_display_start): Likewise.
+       (grub_vbe_bios_set_palette_data): Likewise.
+
+       * normal/cmdline.c (cl_set_pos): Made it refresh screen, to enable
+       better visual experience to video drivers.
+       (cl_insert): Likewise.
+       (cl_delete): Likewise.
+
+       * term/videoterm.c: Added.
+
+       * video/video.c: Added
+
+       * video/i386/pc/vbe.c: Refactored to new video subsystem.
+
 2006-02-01  Yoshinori K. Okuji  <address@hidden>
 
        * boot/i386/pc/boot.S (general_error): Before looping, try INT
diff -ruN -x '*CVS*' grub2/DISTLIST grub2.new/DISTLIST
--- grub2/DISTLIST      2005-12-26 01:04:28.000000000 +0200
+++ grub2.new/DISTLIST  2006-02-25 13:29:16.000000000 +0200
@@ -106,6 +106,7 @@
 include/grub/terminfo.h
 include/grub/tparm.h
 include/grub/types.h
+include/grub/video.h
 include/grub/i386/setjmp.h
 include/grub/i386/types.h
 include/grub/i386/pc/biosdisk.h
@@ -208,6 +209,7 @@
 partmap/sun.c
 term/terminfo.c
 term/tparm.c
+term/videoterm.c
 term/i386/pc/console.c
 term/i386/pc/serial.c
 term/i386/pc/vesafb.c
@@ -229,4 +231,5 @@
 util/i386/pc/misc.c
 util/powerpc/ieee1275/grub-mkimage.c
 util/powerpc/ieee1275/misc.c
+video/video.c
 video/i386/pc/vbe.c
diff -ruN -x '*CVS*' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk      2005-12-26 01:04:29.000000000 +0200
+++ grub2.new/conf/i386-pc.rmk  2006-02-25 14:23:10.000000000 +0200
@@ -113,9 +113,9 @@
 grub_install_SOURCES = util/i386/pc/grub-install.in
 
 # Modules.
-pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod   \
+pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
-       vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
+       vbe.mod vbetest.mod vbeinfo.mod video.mod videoterm.mod play.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -157,11 +157,6 @@
 halt_mod_CFLAGS = $(COMMON_CFLAGS)
 halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For vga.mod.
-vga_mod_SOURCES = term/i386/pc/vga.c
-vga_mod_CFLAGS = $(COMMON_CFLAGS)
-vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
 # For serial.mod.
 serial_mod_SOURCES = term/i386/pc/serial.c
 serial_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -182,11 +177,6 @@
 vbe_mod_CFLAGS = $(COMMON_CFLAGS)
 vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For vesafb.mod.
-vesafb_mod_SOURCES = term/i386/pc/vesafb.c
-vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
-vesafb_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
 # For vbeinfo.mod.
 vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
 vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -202,4 +192,14 @@
 play_mod_CFLAGS = $(COMMON_CFLAGS)
 play_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For video.mod.
+video_mod_SOURCES = video/video.c
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videoterm.mod.
+videoterm_mod_SOURCES = term/videoterm.c
+videoterm_mod_CFLAGS = $(COMMON_CFLAGS)
+videoterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
--- grub2/font/manager.c        2005-11-13 17:47:09.000000000 +0200
+++ grub2.new/font/manager.c    2006-02-25 14:16:16.000000000 +0200
@@ -24,6 +24,7 @@
 #include <grub/types.h>
 #include <grub/mm.h>
 #include <grub/font.h>
+//#include <grub/gzio.h>
 
 struct entry
 {
@@ -50,6 +51,7 @@
   struct font *font = 0;
 
   file = grub_file_open (filename);
+  //file = grub_gzfile_open (filename, 1);
   if (! file)
     goto fail;
 
@@ -151,26 +153,27 @@
 
 /* Set the glyph to something stupid.  */
 static void
-fill_with_default_glyph (unsigned char bitmap[32], unsigned *width)
+fill_with_default_glyph (grub_font_glyph_t glyph)
 {
-  if (bitmap)
-    {
-      unsigned i;
+  unsigned i;
 
-      for (i = 0; i < 16; i++)
-       bitmap[i] = (i & 1) ? 0x55 : 0xaa;
-    }
-      
-  *width = 1;
+  for (i = 0; i < 16; i++)
+    glyph->bitmap[i] = (i & 1) ? 0x55 : 0xaa;
+
+  glyph->char_width = 1;
+  glyph->width = glyph->char_width * 8;
+  glyph->height = 16;
+  glyph->baseline = (16*3)/4;
 }
 
 /* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
    and WIDTH with something, even if no glyph is found.  */
 int
 grub_font_get_glyph (grub_uint32_t code,
-                    unsigned char bitmap[32], unsigned *width)
+                    grub_font_glyph_t glyph)
 {
   struct font *font;
+  grub_uint8_t bitmap[32];
 
   /* FIXME: It is necessary to cache glyphs!  */
   
@@ -183,12 +186,19 @@
       if (offset)
        {
          grub_uint32_t w;
+         grub_uint8_t x;
+         grub_uint8_t y;
+         grub_uint32_t len;
+
+          /* Make sure we can find glyphs for error messages. Push active
+             error message to error stack and reset error message.  */
+          grub_error_push ();
          
          grub_file_seek (font->file, offset);
-         if (grub_file_read (font->file, (char *) &w, 4) != 4)
+         if ((len = grub_file_read (font->file, (char *) &w, 4)) != 4)
            {
-             remove_font (font);
-             goto restart;
+              remove_font (font);
+              goto restart;
            }
 
          w = grub_le_to_cpu32 (w);
@@ -206,14 +216,30 @@
              remove_font (font);
              goto restart;
            }
-
-         *width = w;
+           
+          /* Temporary workaround, fix font bitmap.  */
+          for (y = 0; y < 16; y++)
+            {
+              for (x = 0; x < w; x++)
+                {
+                  glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
+                }
+            }
+          
+         glyph->char_width = w;
+         glyph->width = glyph->char_width * 8;
+         glyph->height = 16;
+         glyph->baseline = (16*3)/4;
+         
+         /* Restore old error message.  */
+          grub_error_pop ();
+          
          return 1;
        }
     }
 
   /* Uggh... No font was found.  */
-  fill_with_default_glyph (bitmap, width);
+  fill_with_default_glyph (glyph);
   return 0;
 }
 
@@ -232,7 +258,7 @@
   return 0;
 }
 
-GRUB_MOD_INIT(fontmanager)
+GRUB_MOD_INIT(font_manager)
 {
   (void) mod; /* Stop warning.  */
   grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
@@ -240,7 +266,7 @@
                         "Specify one or more font files to display.", 0);
 }
 
-GRUB_MOD_FINI(fontmanager)
+GRUB_MOD_FINI(font_manager)
 {
   grub_unregister_command ("font");
 }
diff -ruN -x '*CVS*' grub2/include/grub/font.h grub2.new/include/grub/font.h
--- grub2/include/grub/font.h   2004-04-04 16:46:00.000000000 +0300
+++ grub2.new/include/grub/font.h       2006-02-25 13:43:08.000000000 +0200
@@ -24,7 +24,31 @@
 
 #define GRUB_FONT_MAGIC        "PPF\x7f"
 
+struct grub_font_glyph
+{
+  /* Glyph width in pixels.  */
+  grub_uint8_t width;
+  
+  /* Glyph height in pixels.  */
+  grub_uint8_t height;
+  
+  /* Glyph width in characters.  */
+  grub_uint8_t char_width;
+  
+  /* Glyph baseline position in pixels (from up).  */
+  grub_uint8_t baseline;
+  
+  /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
+     Bitmap is formulated by height scanlines, each scanline having
+     width number of pixels. Pixels are coded as bits, value 1 meaning
+     of opaque pixel and 0 is transparent. If width does not fit byte
+     boundary, it will be padded with 0 to make it fit.  */
+  grub_uint8_t bitmap[32];
+};
+
+typedef struct grub_font_glyph *grub_font_glyph_t;
+
 int grub_font_get_glyph (grub_uint32_t code,
-                        unsigned char bitmap[32], unsigned *width);
+                        grub_font_glyph_t glyph);
 
 #endif /* ! GRUB_FONT_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/i386/pc/vbe.h 
grub2.new/include/grub/i386/pc/vbe.h
--- grub2/include/grub/i386/pc/vbe.h    2005-08-16 21:34:17.000000000 +0300
+++ grub2.new/include/grub/i386/pc/vbe.h        2006-03-02 17:42:44.342055256 
+0200
@@ -27,6 +27,13 @@
 /* Default video mode to be used.  */
 #define GRUB_VBE_DEFAULT_VIDEO_MODE     0x101
 
+/* VBE status codes.  */
+#define GRUB_VBE_STATUS_OK             0x004f
+
+/* VBE memory model types.  */
+#define        GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL      0x04
+#define        GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR      0x06
+
 /* Note:
  
    Please refer to VESA BIOS Extension 3.0 Specification for more descriptive
@@ -147,45 +154,45 @@
 /* Prototypes for kernel real mode thunks.  */
 
 /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_controller_info) (struct 
grub_vbe_info_block *controller_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct 
grub_vbe_info_block *controller_info);
 
 /* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode_info) (grub_uint32_t mode,
-                                                       struct 
grub_vbe_mode_info_block *mode_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
+                                                            struct 
grub_vbe_mode_info_block *mode_info);
 
 /* Call VESA BIOS 0x4f02 to set video mode, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_mode) (grub_uint32_t mode,
-                                                  struct 
grub_vbe_crtc_info_block *crtc_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
+                                                       struct 
grub_vbe_crtc_info_block *crtc_info);
 
 /* Call VESA BIOS 0x4f03 to return current VBE Mode, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode) (grub_uint32_t *mode);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode);
 
 /* Call VESA BIOS 0x4f05 to set memory window, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_memory_window) (grub_uint32_t 
window,
-                                                           grub_uint32_t 
position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t 
window,
+                                                                grub_uint32_t 
position);
 
 /* Call VESA BIOS 0x4f05 to return memory window, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_memory_window) (grub_uint32_t 
window,
-                                                           grub_uint32_t 
*position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t 
window,
+                                                                grub_uint32_t 
*position);
 
 /* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_scanline_length) (grub_uint32_t 
length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) 
(grub_uint32_t length);
 
 /* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status.  
*/
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_scanline_length) (grub_uint32_t 
*length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) 
(grub_uint32_t *length);
 
 /* Call VESA BIOS 0x4f07 to set display start, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_display_start) (grub_uint32_t x,
-                                                           grub_uint32_t y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t 
x,
+                                                                grub_uint32_t 
y);
 
 /* Call VESA BIOS 0x4f07 to get display start, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_display_start) (grub_uint32_t *x,
-                                                           grub_uint32_t *y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t 
*x,
+                                                                grub_uint32_t 
*y);
 
 /* Call VESA BIOS 0x4f09 to set palette data, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_palette_data) (grub_uint32_t 
color_count,
-                                                          grub_uint32_t 
start_index,
-                                                          struct 
grub_vbe_palette_data *palette_data);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t 
color_count,
+                                                               grub_uint32_t 
start_index,
+                                                               struct 
grub_vbe_palette_data *palette_data);
 
 /* Prototypes for helper functions.  */
 
@@ -195,13 +202,5 @@
 grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
 grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
                                          struct grub_vbe_mode_info_block 
*mode_info);
-void grub_vbe_set_pixel_rgb (grub_uint32_t x,
-                             grub_uint32_t y,
-                             grub_uint8_t red,
-                             grub_uint8_t green,
-                             grub_uint8_t blue);
-void grub_vbe_set_pixel_index (grub_uint32_t x,
-                               grub_uint32_t y,
-                               grub_uint8_t color);
 
 #endif /* ! GRUB_VBE_MACHINE_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/misc.h grub2.new/include/grub/misc.h
--- grub2/include/grub/misc.h   2005-10-24 13:23:46.000000000 +0300
+++ grub2.new/include/grub/misc.h       2006-03-02 20:40:08.611744752 +0200
@@ -76,4 +76,14 @@
                                             const grub_uint8_t *src,
                                             grub_size_t size);
 
+/* Inline functions.  */
+static inline unsigned int
+grub_abs (int x)
+{
+  if (x < 0)
+    return (unsigned int)(-x);
+  else
+    return (unsigned int)x;
+}
+
 #endif /* ! GRUB_MISC_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/video.h grub2.new/include/grub/video.h
--- grub2/include/grub/video.h  1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/include/grub/video.h      2006-03-02 15:33:32.650225312 +0200
@@ -0,0 +1,300 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 GRUB; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_VIDEO_HEADER
+#define GRUB_VIDEO_HEADER      1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+typedef grub_uint32_t grub_color_t;
+struct grub_video_render_target;
+
+/* Defines used to describe video mode or rendering target.  */
+#define GRUB_VIDEO_MODE_TYPE_ALPHA             0x00000008
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED   0x00000004
+#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR       0x00000002
+#define GRUB_VIDEO_MODE_TYPE_RGB               0x00000001
+
+/* Defines used to mask flags.  */
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK                0x00000003
+
+/* Defined predefined render targets.  */
+#define GRUB_VIDEO_RENDER_TARGET_DISPLAY       ((struct 
grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER  ((struct 
grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER   ((struct 
grub_video_render_target *) 1)
+
+struct grub_video_mode_info {
+  /* Width of the screen.  */
+  grub_uint32_t width;
+  
+  /* Height of the screen.  */
+  grub_uint32_t height;
+
+  /* Mode type bitmask. Contains information like is it Index color or 
+     RGB mode.  */
+  grub_uint32_t mode_type;
+
+  /* Bits per pixel.  */
+  grub_uint32_t bpp;
+  
+  /* Bytes per pixel.  */
+  grub_uint32_t bytes_per_pixel;
+  
+  /* Pitch of one scanline. How many bytes there are for scanline.  */
+  grub_uint32_t pitch;
+
+  /* In index color mode, number of colors. In RGB mode this is 256.  */
+  grub_uint32_t number_of_colors;
+
+  /* How many bits are reserved for red color.  */
+  grub_uint32_t red_mask_size;
+
+  /* What is location of red color bits. In Index Color mode, this is 0.  */
+  grub_uint32_t red_field_pos;
+
+  /* How many bits are reserved for green color.  */
+  grub_uint32_t green_mask_size;
+
+  /* What is location of green color bits. In Index Color mode, this is 0.  */
+  grub_uint32_t green_field_pos;
+
+  /* How many bits are reserved for blue color.  */
+  grub_uint32_t blue_mask_size;
+
+  /* What is location of blue color bits. In Index Color mode, this is 0.  */
+  grub_uint32_t blue_field_pos;
+
+  /* How many bits are reserved in color.  */
+  grub_uint32_t reserved_mask_size;
+
+  /* What is location of reserved color bits. In Index Color mode, 
+     this is 0.  */
+  grub_uint32_t reserved_field_pos;
+};
+
+struct grub_video_render_target {
+  /* Copy of the screen's mode info structure, except that width, height and
+     mode_type has been re-adjusted to requested render target settings.  */
+  struct grub_video_mode_info mode_info;
+
+  struct {
+    unsigned int x;
+    unsigned int y;
+    unsigned int width;
+    unsigned int height;       
+  } viewport;
+
+  /* Indicates wether the data has been allocated by us and must be freed 
+     when render target is destroyed.  */
+  int is_allocated;
+  
+  /* Pointer to data. Can either be in video card memory or in local host's
+     memory.  */
+  void *data;
+};
+
+struct grub_video_palette_data {
+  grub_uint8_t r; /* Red color value (0-255).  */
+  grub_uint8_t g; /* Green color value (0-255).  */
+  grub_uint8_t b; /* Blue color value (0-255).  */
+  grub_uint8_t a; /* Reserved bits value (0-255).  */
+};
+
+struct grub_font_glyph;
+struct grub_video_bitmap;
+
+struct grub_video_adapter
+{
+  /* The video adapter name.  */
+  const char *name;
+
+  /* Initialize the video adapter.  */
+  grub_err_t (*init) (void);
+
+  /* Clean up the video adapter.  */
+  grub_err_t (*fini) (void);
+
+  grub_err_t (*setup) (unsigned int width, 
+                      unsigned int height,
+                      unsigned int mode_type);
+
+  grub_err_t (*get_info) (struct grub_video_mode_info * mode_info);
+  
+  grub_err_t (*set_palette) (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data);
+
+  grub_err_t (*get_palette) (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data);
+
+  grub_err_t (*set_viewport) (unsigned int x,
+                             unsigned int y,
+                             unsigned int width,
+                             unsigned int height);
+
+  grub_err_t (*get_viewport) (unsigned int * x,
+                             unsigned int * y,
+                             unsigned int * width,
+                             unsigned int * height);
+
+  grub_color_t (*map_color) (grub_uint32_t color_name);
+  
+  grub_color_t (*map_rgb) (grub_uint8_t red,
+                          grub_uint8_t green,
+                          grub_uint8_t blue);
+
+  grub_color_t (*map_rgba) (grub_uint8_t red,
+                           grub_uint8_t green,
+                           grub_uint8_t blue,
+                           grub_uint8_t alpha);
+
+  grub_err_t (*fill_rect) (grub_color_t color,
+                          int x,
+                          int y,
+                          unsigned int width,
+                          unsigned int height);
+
+  grub_err_t (*blit_glyph) (struct grub_font_glyph * glyph,
+                           grub_color_t color,
+                           int x,
+                           int y);
+
+  grub_err_t (*blit_bitmap) (struct grub_video_bitmap * bitmap,
+                            int x,
+                            int y,
+                            int offset_x,
+                            int offset_y,
+                            unsigned int width,
+                            unsigned int height);
+
+  grub_err_t (*blit_render_target) (struct grub_video_render_target * source,
+                                   int x,
+                                   int y,
+                                   int offset_x,
+                                   int offset_y,
+                                   unsigned int width,
+                                   unsigned int height);
+
+  grub_err_t (*scroll) (grub_color_t color,
+                       int dx,
+                       int dy);
+
+  grub_err_t (*swap_buffers) (void);
+
+  grub_err_t (*create_render_target) (struct grub_video_render_target * * 
result,
+                                     unsigned int mode_type,
+                                     unsigned int width,
+                                     unsigned int height);
+
+  grub_err_t (*delete_render_target) (struct grub_video_render_target * 
target);
+
+  grub_err_t (*set_active_render_target) (struct grub_video_render_target * 
target);
+
+  /* The next video adapter.  */
+  struct grub_video_adapter *next;
+};
+typedef struct grub_video_adapter *grub_video_adapter_t;
+
+void EXPORT_FUNC(grub_video_register) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_unregister) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_iterate) (int (*hook) (grub_video_adapter_t 
adapter));
+
+grub_err_t EXPORT_FUNC(grub_video_setup) (unsigned int width,
+                                         unsigned int height,
+                                         unsigned int mode_type);
+
+grub_err_t EXPORT_FUNC(grub_video_restore) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_get_info) (struct grub_video_mode_info * 
mode_info);
+
+grub_err_t EXPORT_FUNC(grub_video_set_palette) (unsigned int start,
+                                               unsigned int count,
+                                               struct grub_video_palette_data 
*palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_get_palette) (unsigned int start,
+                                               unsigned int count,
+                                               struct grub_video_palette_data 
*palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_set_viewport) (unsigned int x,
+                                                unsigned int y,
+                                                unsigned int width,
+                                                unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_get_viewport) (unsigned int * x,
+                                                unsigned int * y,
+                                                unsigned int * width,
+                                                unsigned int * height);
+
+grub_color_t EXPORT_FUNC(grub_video_map_color) (grub_uint32_t color_name);
+
+grub_color_t EXPORT_FUNC(grub_video_map_rgb) (grub_uint8_t red,
+                                             grub_uint8_t green,
+                                             grub_uint8_t blue);
+
+grub_color_t EXPORT_FUNC(grub_video_map_rgba) (grub_uint8_t red,
+                                              grub_uint8_t green,
+                                              grub_uint8_t blue,
+                                              grub_uint8_t alpha);
+
+grub_err_t EXPORT_FUNC(grub_video_fill_rect) (grub_color_t color,
+                                             int x,
+                                             int y,
+                                             unsigned int width,
+                                             unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_glyph) (struct grub_font_glyph * glyph,
+                                              grub_color_t color,
+                                              int x,
+                                              int y);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_bitmap) (struct grub_video_bitmap * 
bitmap,
+                                               int x,
+                                               int y,
+                                               int offset_x,
+                                               int offset_y,
+                                               unsigned int width,
+                                               unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_render_target) (struct 
grub_video_render_target * source,
+                                                      int x,
+                                                      int y,
+                                                      int offset_x,
+                                                      int offset_y,
+                                                      unsigned int width,
+                                                      unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_scroll) (grub_color_t color,
+                                          int dx,
+                                          int dy);
+
+grub_err_t EXPORT_FUNC(grub_video_swap_buffers) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_create_render_target) (struct 
grub_video_render_target * * result,
+                                                        unsigned int mode_type,
+                                                        unsigned int width,
+                                                        unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_delete_render_target) (struct 
grub_video_render_target * target);
+
+grub_err_t EXPORT_FUNC(grub_video_set_active_render_target) (struct 
grub_video_render_target * target);
+                                          
+#endif /* ! GRUB_VIDEO_HEADER */
diff -ruN -x '*CVS*' grub2/kern/i386/pc/startup.S 
grub2.new/kern/i386/pc/startup.S
--- grub2/kern/i386/pc/startup.S        2005-10-15 20:28:36.000000000 +0300
+++ grub2.new/kern/i386/pc/startup.S    2006-03-02 14:14:06.760358584 +0200
@@ -1758,14 +1758,15 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block 
*controller_info)
+ * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct 
grub_vbe_info_block *controller_info)
  *
  * Register allocations for parameters:
  * %eax                *controller_info
  */
-FUNCTION(grub_vbe_get_controller_info)
+FUNCTION(grub_vbe_bios_get_controller_info)
        pushl   %ebp
        pushl   %edi
+       pushl   %edx
 
        movw    %ax, %di        /* Store *controller_info to %edx:%di.  */
        xorw    %ax, %ax
@@ -1791,19 +1792,20 @@
        movl    %edx, %eax
        andl    $0x0FFFF, %eax  /* Return value in %eax.  */
        
+       pop     %edx
        popl    %edi
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_mode_info (grub_uint32_t mode,
- *                                          struct grub_vbe_mode_info_block 
*mode_info)
+ * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
+ *                                               struct 
grub_vbe_mode_info_block *mode_info)
  *
  * Register allocations for parameters:
  * %eax                mode
  * %edx                *mode_info
  */
-FUNCTION(grub_vbe_get_mode_info)
+FUNCTION(grub_vbe_bios_get_mode_info)
        pushl   %ebp
        pushl   %edi
 
@@ -1837,16 +1839,17 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_mode (grub_uint32_t mode,
- *                                     struct grub_vbe_crtc_info_block 
*crtc_info)
+ * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
+ *                                          struct grub_vbe_crtc_info_block 
*crtc_info)
  *
  * Register allocations for parameters:
  * %eax                mode
  * %edx                *crtc_info
  */
-FUNCTION(grub_vbe_set_mode)
+FUNCTION(grub_vbe_bios_set_mode)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
 
        movl    %eax, %ebx      /* Store mode in %ebx.  */
 
@@ -1874,19 +1877,22 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_mode (grub_uint32_t *mode)
+ * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
  *
  * Register allocations for parameters:
  * %eax                *mode
  */
-FUNCTION(grub_vbe_get_mode)
+FUNCTION(grub_vbe_bios_get_mode)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
+       pushl   %edx
        pushl   %eax            /* Push *mode to stack.  */
 
        call    prot_to_real
@@ -1907,19 +1913,21 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edx
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_memory_window (grub_uint32_t window,
- *                                              grub_uint32_t position);
+ * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
+ *                                                   grub_uint32_t position);
  *
  * Register allocations for parameters:
  * %eax                window
  * %edx                position
  */
-FUNCTION(grub_vbe_set_memory_window)
+FUNCTION(grub_vbe_bios_set_memory_window)
        pushl   %ebp
        pushl   %ebx
 
@@ -1945,16 +1953,17 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_memory_window (grub_uint32_t window,
- *                                              grub_uint32_t *position);
+ * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
+ *                                                   grub_uint32_t *position);
  *
  * Register allocations for parameters:
  * %eax                window
  * %edx                *position
  */
-FUNCTION(grub_vbe_get_memory_window)
+FUNCTION(grub_vbe_bios_get_memory_window)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
        pushl   %edx            /* Push *position to stack.  */
 
        movl    %eax, %ebx      /* Store window in %ebx.  */
@@ -1979,19 +1988,21 @@
        movw    %bx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_scanline_length (grub_uint32_t length)
+ * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
  *
  * Register allocations for parameters:
  * %eax                length
  */
-FUNCTION(grub_vbe_set_scanline_length)
+FUNCTION(grub_vbe_bios_set_scanline_length)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edx
 
        movl    %eax, %ecx      /* Store length in %ecx.  */
 
@@ -2010,19 +2021,21 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edx
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_scanline_length (grub_uint32_t *length)
+ * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
  *
  * Register allocations for parameters:
  * %eax                *length
  */
-FUNCTION(grub_vbe_get_scanline_length)
+FUNCTION(grub_vbe_bios_get_scanline_length)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
        pushl   %edx            /* Push *length to stack.  */
 
        call    prot_to_real
@@ -2044,19 +2057,20 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_display_start (grub_uint32_t x,
- *                                              grub_uint32_t y)
+ * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
+ *                                                   grub_uint32_t y)
  *
  * Register allocations for parameters:
  * %eax                x
  * %edx                y
  */
-FUNCTION(grub_vbe_set_display_start)
+FUNCTION(grub_vbe_bios_set_display_start)
        pushl   %ebp
        pushl   %ebx
 
@@ -2083,16 +2097,17 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_display_start (grub_uint32_t *x,
- *                                              grub_uint32_t *y)
+ * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
+ *                                                   grub_uint32_t *y)
  *
  * Register allocations for parameters:
  * %eax                *x
  * %edx                *y
  */
-FUNCTION(grub_vbe_get_display_start)
+FUNCTION(grub_vbe_bios_get_display_start)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
        pushl   %eax            /* Push *x to stack.  */
        pushl   %edx            /* Push *y to stack.  */
 
@@ -2119,23 +2134,25 @@
        movw    %bx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_palette_data (grub_uint32_t color_count,
- *                                             grub_uint32_t start_index,
- *                                             struct grub_vbe_palette_data 
*palette_data)
+ * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
+ *                                                  grub_uint32_t start_index,
+ *                                                  struct 
grub_vbe_palette_data *palette_data)
  *
  * Register allocations for parameters:
  * %eax                color_count
  * %edx                start_index
  * %ecx                *palette_data
  */
-FUNCTION(grub_vbe_set_palette_data)
+FUNCTION(grub_vbe_bios_set_palette_data)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
 
        movl    %eax, %ebx      /* Store color_count in %ebx.  */
 
@@ -2165,6 +2182,7 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
diff -ruN -x '*CVS*' grub2/normal/cmdline.c grub2.new/normal/cmdline.c
--- grub2/normal/cmdline.c      2005-08-28 20:01:16.000000000 +0300
+++ grub2.new/normal/cmdline.c  2006-02-25 14:50:44.000000000 +0200
@@ -231,6 +231,8 @@
       xpos = (plen + lpos) % 79;
       ypos = ystart + (plen + lpos) / 79;
       grub_gotoxy (xpos, ypos);
+      
+      grub_refresh ();
     }
   
   void cl_print (int pos, int c)
@@ -271,6 +273,8 @@
          cl_print (lpos - len, echo_char);
          cl_set_pos ();
        }
+      
+      grub_refresh ();
     }
 
   void cl_delete (unsigned len)
@@ -290,6 +294,8 @@
          cl_print (lpos, echo_char);
          cl_set_pos ();
        }
+      
+      grub_refresh ();
     }
   
   plen = grub_strlen (prompt);
diff -ruN -x '*CVS*' grub2/term/videoterm.c grub2.new/term/videoterm.c
--- grub2/term/videoterm.c      1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/term/videoterm.c  2006-03-02 15:32:11.991487304 +0200
@@ -0,0 +1,873 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  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.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/video.h>
+
+#define DEFAULT_CHAR_WIDTH  8
+#define DEFAULT_CHAR_HEIGHT 16
+
+#define DEFAULT_FG_COLOR       0x0a
+#define DEFAULT_BG_COLOR       0x00
+#define DEFAULT_CURSOR_COLOR   0x0f
+
+struct grub_dirty_region
+{
+  int top_left_x;
+  int top_left_y;
+  int bottom_right_x;
+  int bottom_right_y;
+};
+
+struct grub_colored_char
+{
+  /* An Unicode codepoint.  */
+  grub_uint32_t code;
+
+  /* Color values.  */
+  grub_color_t fg_color;
+  grub_color_t bg_color;
+
+  /* The width of this character minus one.  */
+  unsigned char width;
+
+  /* The column index of this character.  */
+  unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+  /* Dimensions of the virual screen.  */
+  grub_uint32_t width;
+  grub_uint32_t height;
+
+  /* Offset in the display.  */
+  grub_uint32_t offset_x;
+  grub_uint32_t offset_y;
+
+  /* TTY Character sizes.  */
+  grub_uint32_t char_width;
+  grub_uint32_t char_height;
+
+  /* Virtual screen TTY size.  */
+  grub_uint32_t columns;
+  grub_uint32_t rows;
+
+  /* Current cursor details.  */
+  grub_uint32_t cursor_x;
+  grub_uint32_t cursor_y;
+  grub_uint8_t cursor_state;
+  grub_color_t fg_color_setting;
+  grub_color_t bg_color_setting;
+  grub_color_t fg_color;
+  grub_color_t bg_color;
+  grub_color_t cursor_color;
+
+  /* Text buffer for virual screen. Contains (columns * rows) number
+     of entries.  */
+  struct grub_colored_char *text_buffer;
+};
+
+/* Make seure text buffer is not marked as allocated.  */
+static struct grub_virtual_screen virtual_screen =
+  {
+    .text_buffer = 0
+  };
+
+static grub_dl_t my_mod;
+static struct grub_video_mode_info mode_info;
+
+static struct grub_video_render_target *text_layer = 0;
+
+static struct grub_dirty_region dirty_region;
+
+static void dirty_region_reset (void);
+
+static int dirty_region_is_empty (void);
+
+static void dirty_region_add (int x, 
+                              int y,
+                              unsigned int width,
+                              unsigned int height);
+
+static void
+grub_virtual_screen_free (void)
+{
+  /* If virtual screen has been allocated, free it.  */
+  if (virtual_screen.text_buffer != 0)
+    grub_free (virtual_screen.text_buffer);
+
+  /* Reset virtual screen data.  */
+  grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+  
+  /* Free render targets.  */
+  grub_video_delete_render_target (text_layer);
+  text_layer = 0;
+}
+
+static grub_err_t
+grub_virtual_screen_setup (grub_uint32_t x,
+                           grub_uint32_t y,
+                           grub_uint32_t width,
+                          grub_uint32_t height)
+{
+  /* Free old virtual screen.  */
+  grub_virtual_screen_free ();
+
+  /* Initialize with default data.  */
+  virtual_screen.width = width;
+  virtual_screen.height = height;
+  virtual_screen.offset_x = x;
+  virtual_screen.offset_y = y;
+  virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
+  virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+  virtual_screen.cursor_x = 0;
+  virtual_screen.cursor_y = 0;
+  virtual_screen.cursor_state = 1;
+
+  /* Calculate size of text buffer.  */
+  virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
+  virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
+
+  /* Allocate memory for text buffer.  */
+  virtual_screen.text_buffer =
+    (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+                                             * virtual_screen.rows
+                                             * sizeof 
(*virtual_screen.text_buffer));
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Cleare new render target for text layer.  */
+  grub_video_create_render_target (&text_layer,
+                                   GRUB_VIDEO_MODE_TYPE_RGB
+                                   | GRUB_VIDEO_MODE_TYPE_ALPHA,
+                                   virtual_screen.width,
+                                   virtual_screen.height);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+  
+  /* As we want to have colors compatible with rendering target,
+     we can only have those after mode is initialized.  */    
+  grub_video_set_active_render_target (text_layer);
+  
+  virtual_screen.fg_color_setting = grub_video_map_color (DEFAULT_FG_COLOR);
+  virtual_screen.bg_color_setting = grub_video_map_color (DEFAULT_BG_COLOR);
+  virtual_screen.fg_color = virtual_screen.fg_color_setting;
+  virtual_screen.bg_color = virtual_screen.bg_color_setting;
+  virtual_screen.cursor_color = grub_video_map_color (DEFAULT_CURSOR_COLOR);
+  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  return grub_errno;
+}
+
+static grub_err_t
+grub_videoterm_init (void)
+{
+  char *modevar;
+  int width = 1024;
+  int height = 768;
+  int flags = 0;
+  grub_color_t color;
+  
+  /* Parse video_mode environment variable if set.  */
+  modevar = grub_env_get ("video_mode");
+  if (modevar)
+    {
+      char *tmp;
+      char *param;
+      char *value;
+      
+      /* Take copy of env.var. as we don't want to modify that.  */
+      tmp = grub_strdup (modevar);
+      modevar = tmp;
+      
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;        
+      
+      /* Skip whitespace.  */
+      while (grub_isspace (*tmp))
+        {
+          tmp++;
+        }
+      
+      /* Initialize token holders.  */
+      param = tmp;
+      value = NULL;
+
+      /* Loop until all characters have been handled.  */
+      while (1)
+        {
+          if (grub_isspace (*tmp) || (*tmp == 0))
+            {
+              /* If there are more variables, mark seperator with NUL.  */
+              if (*tmp != 0)
+                {
+                  *tmp++ = 0;
+                }              
+
+              /* Analyze setting.  */
+              
+              /* Handle width=<number>.  */
+              if ((grub_strcmp (param, "width") == 0) && (value != NULL))
+                {
+                  width = grub_strtoul (value, 0, 0);
+                  if (grub_errno != GRUB_ERR_NONE)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_errno;
+                    }
+                }
+
+              /* Handle height=<number>.  */
+              if ((grub_strcmp (param, "height") == 0) && (value != NULL))
+                {
+                  height = grub_strtoul (value, 0, 0);
+                  if (grub_errno != GRUB_ERR_NONE)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_errno;
+                    }
+                }
+
+              /* Handle rgb. Used to request RGB mode.  */
+              if ((grub_strcmp (param, "rgb") == 0) && (value == NULL))
+                {
+                  flags &= ~GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+                  flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+                }
+
+              /* Handle index. Used to request index color mode.  */
+              if ((grub_strcmp (param, "index") == 0) && (value == NULL))
+                {
+                  flags &= ~GRUB_VIDEO_MODE_TYPE_RGB;
+                  flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+                }                
+
+              /* Handle double. Used to request double buffering mode.  */
+              if ((grub_strcmp (param, "double") == 0) && (value == NULL))
+                {
+                  flags |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
+                }
+              
+              /* Handle <width>x<height>[x<depth>]*/
+              if (grub_isdigit (param[0]))
+                {
+                  /* Find width value.  */
+                  value = param;
+                  param = grub_strchr(param, 'x');
+                  if (param == NULL)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                                         "Invalid argument: %s\n",
+                                         param);
+                    }
+                    
+                  *param = 0;
+                  param++;
+                      
+                  width = grub_strtoul (value, 0, 0);
+                  if (grub_errno != GRUB_ERR_NONE)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_errno;
+                    }                      
+
+                  /* Find height value.  */
+                  value = param;
+                  param = grub_strchr(param, 'x');
+                  if (param == NULL)
+                    {                    
+                      height = grub_strtoul (value, 0, 0);
+                      if (grub_errno != GRUB_ERR_NONE)
+                        {
+                          /* Free memory before returning.  */
+                          grub_free (modevar);
+                          return grub_errno;
+                        }                      
+                    }
+                  else
+                    {
+                      /* We have optional color depth value.  */
+                      *param = 0;
+                      param++;
+                      
+                      height = grub_strtoul (value, 0, 0);
+                      if (grub_errno != GRUB_ERR_NONE)
+                        {
+                          /* Free memory before returning.  */
+                          grub_free (modevar);
+                          return grub_errno;
+                        }                      
+                      
+                      /* Convert color depth value.  */
+                      value = param;
+#if 0                      
+                      depth = grub_strtoul (value, 0, 0);
+                      if (grub_errno != GRUB_ERR_NONE)
+                        {
+                          /* Free memory before returning.  */
+                          grub_free (modevar);
+                          return grub_errno;
+                        }
+#endif                        
+                    }
+                }
+                
+              /* Skip whitespace.  */
+              while (grub_isspace (*tmp))
+                {
+                  tmp++;
+                }
+
+              /* Check if we are at end of string.  */
+              if (*tmp == 0)
+                {
+                  break;
+                }
+              
+              /* Initialize token holders.  */
+              param = tmp;
+              value = NULL;
+            }
+          
+          /* Check if there is value seperator.  */
+          if (*tmp == '=')
+            {
+              *tmp++ = 0;
+              value = tmp;
+            }
+          
+          /* Advance to next character.  */
+          tmp++;
+        }
+        
+        /* Free memory.  */
+        grub_free (modevar);
+    }
+
+  /* Intialize user requested mode.  */
+  if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Figure out what mode we ended up.  */
+  if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Make sure screen is black.  */
+  color = grub_video_map_rgb (0, 0, 0);
+  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+
+  /* Leave borders for virtual screen.  */
+  width = mode_info.width - (2 * 10);
+  height = mode_info.height - (2 * 10);
+  
+  /* Create virtual screen.  */
+  if (grub_virtual_screen_setup (10,
+                                 10,
+                                 width,
+                                height) != GRUB_ERR_NONE)
+    {
+      grub_video_restore ();
+      return grub_errno;
+    }
+
+  /* Mark whole screen as dirty.  */
+  dirty_region_reset ();  
+  dirty_region_add (0, 0, mode_info.width, mode_info.height);
+
+  return (grub_errno = GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_videoterm_fini (void)
+{
+  grub_virtual_screen_free ();
+
+  grub_video_restore ();
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+redraw_screen_rect (unsigned int x, 
+                    unsigned int y, 
+                    unsigned int width, 
+                    unsigned int height)
+{
+  grub_color_t color;
+  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Render background layer.  */
+  color = virtual_screen.bg_color;
+  grub_video_fill_rect (color, x, y, width, height);
+  
+  /* Render text layer.  */
+  grub_video_blit_render_target (text_layer,
+                                 x,
+                                 y,
+                                 x - virtual_screen.offset_x,
+                                 y - virtual_screen.offset_y,
+                                 width,
+                                 height);
+}
+
+static void
+dirty_region_reset (void)
+{
+  dirty_region.top_left_x = -1;
+  dirty_region.top_left_y = -1;
+  dirty_region.bottom_right_x = -1;
+  dirty_region.bottom_right_y = -1;
+}
+
+static int
+dirty_region_is_empty (void)
+{
+  if ((dirty_region.top_left_x == -1)
+      || (dirty_region.top_left_y == -1)
+      || (dirty_region.bottom_right_x == -1)
+      || (dirty_region.bottom_right_y == -1))
+    {
+      return 1;
+    }
+  return 0;
+}
+
+static void
+dirty_region_add (int x, int y, unsigned int width, unsigned int height)
+{
+  if ((width == 0) || (height == 0))
+    return;
+    
+  if (dirty_region_is_empty ())
+    {
+      dirty_region.top_left_x = x;
+      dirty_region.top_left_y = y;
+      dirty_region.bottom_right_x = x + width - 1;
+      dirty_region.bottom_right_y = y + height - 1;
+    } 
+  else
+    {
+      if (x < dirty_region.top_left_x)
+        {
+          dirty_region.top_left_x = x;
+        }
+      if (y < dirty_region.top_left_y)
+        {
+          dirty_region.top_left_y = y;
+        }
+      if ((x + (int)width - 1) > dirty_region.bottom_right_x)
+        {
+          dirty_region.bottom_right_x = x + width - 1;
+        }
+      if ((y + (int)height - 1) > dirty_region.bottom_right_y)
+        {
+          dirty_region.bottom_right_y = y + height - 1;
+        }
+    }
+} 
+
+static void
+dirty_region_add_virtualscreen (void)
+{
+  /* Mark virtual screen as dirty.  */
+  dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
+                    virtual_screen.width, virtual_screen.height);
+}
+
+
+static void
+dirty_region_redraw (void)
+{
+  int x;
+  int y;
+  int width;
+  int height;
+  
+  if (dirty_region_is_empty ())
+    return;
+  
+  x = dirty_region.top_left_x;
+  y = dirty_region.top_left_y;
+  
+  width = dirty_region.bottom_right_x - x + 1;
+  height = dirty_region.bottom_right_y - y + 1;
+  
+  redraw_screen_rect (x, y, width, height);
+  
+  dirty_region_reset ();
+}
+
+static void
+write_char (void)
+{
+  struct grub_colored_char *p;
+  struct grub_font_glyph glyph;
+  grub_uint32_t x, y;
+
+  grub_video_set_active_render_target (text_layer);
+  
+  p = (virtual_screen.text_buffer
+       + virtual_screen.cursor_x
+       + (virtual_screen.cursor_y * virtual_screen.columns));
+
+  p -= p->index;
+
+  grub_uint32_t color, bgcolor;
+    
+  grub_font_get_glyph (p->code, &glyph);
+
+  color = p->fg_color;
+  bgcolor = p->bg_color;
+
+  x = virtual_screen.cursor_x * virtual_screen.char_width;
+  y = virtual_screen.cursor_y * virtual_screen.char_height;
+
+  grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height);
+
+  grub_video_blit_glyph (&glyph, color, x, y);
+  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  dirty_region_add (virtual_screen.offset_x + x,
+                    virtual_screen.offset_y + y,
+                    glyph.width,
+                    glyph.height);
+}
+
+static void
+write_cursor (void)
+{
+  grub_uint32_t x;
+  grub_uint32_t y;
+  grub_uint32_t width;
+  grub_uint32_t height;
+  grub_uint32_t color;
+
+  grub_video_set_active_render_target (text_layer);
+  
+  x = virtual_screen.cursor_x * virtual_screen.char_width;
+  y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;  
+  width = virtual_screen.char_width;
+  height = 2;
+
+  color = virtual_screen.cursor_color;
+  grub_video_fill_rect (color, x, y, width, height);
+  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  dirty_region_add (virtual_screen.offset_x + x,
+                    virtual_screen.offset_y + y,
+                    width,
+                    height);
+}
+
+static void
+scroll_up (void)
+{
+  grub_uint32_t i;
+  grub_uint32_t color;
+
+  /* Scroll text buffer with one line to up.  */
+  grub_memmove (virtual_screen.text_buffer,
+               virtual_screen.text_buffer + virtual_screen.columns,
+                sizeof (*virtual_screen.text_buffer)
+                * virtual_screen.columns
+                * (virtual_screen.rows - 1));
+
+  /* Clear last line in text buffer.  */
+  for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+       i < virtual_screen.columns * virtual_screen.rows;
+       i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+      virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+    
+  /* Scroll physcal screen.  */
+  grub_video_set_active_render_target (text_layer);
+
+  color = virtual_screen.bg_color;
+
+  grub_video_scroll (color, 0, -virtual_screen.char_height);
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_videoterm_putchar (grub_uint32_t c)
+{
+  if (c == '\a')
+    /* FIXME */
+    return;
+
+  if (c == '\b' || c == '\n' || c == '\r')
+    {
+      /* Erase current cursor, if any.  */
+      if (virtual_screen.cursor_state)
+       write_char ();
+
+      switch (c)
+       {
+       case '\b':
+         if (virtual_screen.cursor_x > 0)
+           virtual_screen.cursor_x--;
+         break;
+         
+       case '\n':
+         if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+           scroll_up ();
+         else
+           virtual_screen.cursor_y++;
+         break;
+         
+       case '\r':
+         virtual_screen.cursor_x = 0;
+         break;
+       }
+
+      if (virtual_screen.cursor_state)
+       write_cursor ();
+    }
+  else
+    {
+      struct grub_font_glyph glyph;
+      struct grub_colored_char *p;
+      
+      grub_font_get_glyph (c, &glyph);
+
+      if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns)
+       grub_putchar ('\n');
+
+      p = (virtual_screen.text_buffer +
+          virtual_screen.cursor_x +
+          virtual_screen.cursor_y * virtual_screen.columns);
+      p->code = c;
+      p->fg_color = virtual_screen.fg_color;
+      p->bg_color = virtual_screen.bg_color;
+      p->width = glyph.char_width - 1;
+      p->index = 0;
+
+      if (glyph.char_width > 1)
+       {
+         unsigned i;
+
+         for (i = 1; i < glyph.char_width; i++)
+           {
+             p[i].code = ' ';
+             p[i].width = glyph.char_width - 1;
+             p[i].index = i;
+           }
+       }
+         
+      write_char ();
+  
+      virtual_screen.cursor_x += glyph.char_width;
+      if (virtual_screen.cursor_x >= virtual_screen.columns)
+       {
+         virtual_screen.cursor_x = 0;
+         
+         if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+           scroll_up ();
+         else
+           virtual_screen.cursor_y++;
+       }
+
+      if (virtual_screen.cursor_state)
+       write_cursor ();
+    }
+}
+
+static grub_ssize_t
+grub_videoterm_getcharwidth (grub_uint32_t c)
+{
+  struct grub_font_glyph glyph;
+  
+  if (! grub_font_get_glyph (c, &glyph))
+    return 0;
+
+  return glyph.char_width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+  return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+  return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_videoterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  if (x >= virtual_screen.columns || y >= virtual_screen.rows)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+                 (unsigned) x, (unsigned) y);
+      return;
+    }
+
+  if (virtual_screen.cursor_state)
+    write_char ();
+
+  virtual_screen.cursor_x = x;
+  virtual_screen.cursor_y = y;
+
+  if (virtual_screen.cursor_state)
+    write_cursor ();
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+  grub_uint32_t i;
+
+  for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+      virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_videoterm_cls (void)
+{
+  grub_uint32_t color;
+
+  grub_video_set_active_render_target (text_layer);
+  grub_virtual_screen_cls ();
+
+  color = virtual_screen.bg_color_setting;
+  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  /* Redraw only virtual screen.  */
+  dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      virtual_screen.fg_color = virtual_screen.fg_color_setting;
+      virtual_screen.bg_color = virtual_screen.bg_color_setting;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      virtual_screen.fg_color = virtual_screen.bg_color_setting;
+      virtual_screen.bg_color = virtual_screen.fg_color_setting;
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color __attribute__ 
((unused)),
+                             grub_uint8_t highlight_color __attribute__ 
((unused)))
+{
+  virtual_screen.fg_color_setting = grub_video_map_color (normal_color);
+  virtual_screen.bg_color_setting = grub_video_map_color (highlight_color);
+}
+
+static void
+grub_videoterm_setcursor (int on)
+{
+  if (virtual_screen.cursor_state != on)
+    {
+      if (virtual_screen.cursor_state)
+       write_char ();
+      else
+       write_cursor ();
+
+      virtual_screen.cursor_state = on;
+    }
+}
+
+static void
+grub_videoterm_refresh (void)
+{
+  /* Redraw only changed regions.  */
+  dirty_region_redraw ();
+}
+
+static struct grub_term grub_video_term =
+  {
+    .name = "videoterm",
+    .init = grub_videoterm_init,
+    .fini = grub_videoterm_fini,
+    .putchar = grub_videoterm_putchar,
+    .getcharwidth = grub_videoterm_getcharwidth,
+    .checkkey = grub_console_checkkey,
+    .getkey = grub_console_getkey,
+    .getwh = grub_virtual_screen_getwh,
+    .getxy = grub_virtual_screen_getxy,
+    .gotoxy = grub_videoterm_gotoxy,
+    .cls = grub_videoterm_cls,
+    .setcolorstate = grub_virtual_screen_setcolorstate,
+    .setcolor = grub_virtual_screen_setcolor,
+    .setcursor = grub_videoterm_setcursor,
+    .refresh = grub_videoterm_refresh,    
+    .flags = 0,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(term_videoterm)
+{
+  my_mod = mod;
+  grub_term_register (&grub_video_term);
+}
+
+GRUB_MOD_FINI(term_videoterm)
+{
+  grub_term_unregister (&grub_video_term);
+}
Files grub2/unifont.pff and grub2.new/unifont.pff differ
diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
--- grub2/video/i386/pc/vbe.c   2005-09-19 00:04:41.000000000 +0300
+++ grub2.new/video/i386/pc/vbe.c       2006-03-02 20:35:43.719014568 +0200
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2005-2006  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
@@ -17,6 +17,11 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* General TODO's:
+   - Implement mode optimized operations and automatically select best
+
+*/
+
 #include <grub/err.h>
 #include <grub/machine/memory.h>
 #include <grub/machine/vga.h>
@@ -31,6 +36,7 @@
 #include <grub/arg.h>
 #include <grub/mm.h>
 #include <grub/env.h>
+#include <grub/video.h>
 
 /* Specify "standard" VGA palette, some video cards may
    need this and this will also be used when using RGB modes.  */
@@ -57,15 +63,51 @@
   };
 
 static int vbe_detected = -1;
-static int index_color_mode = 0;
 
 static struct grub_vbe_info_block controller_info;
 static struct grub_vbe_mode_info_block active_mode_info;
 
-static grub_uint32_t active_mode = 0;
+static struct {
+  struct grub_video_render_target render_target;
+
+  unsigned int bytes_per_scan_line;
+  unsigned int bytes_per_pixel;
+  grub_uint32_t active_mode;
+  grub_uint8_t *ptr;
+  int index_color_mode;
+  struct grub_video_palette_data palette[256];
+} framebuffer;  
+
+static struct grub_video_render_target *render_target;
+
+static grub_dl_t my_mod = 0;
+
+static grub_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+                        grub_uint8_t green,
+                        grub_uint8_t blue);
 
-static grub_uint8_t *framebuffer = 0;
-static grub_uint32_t bytes_per_scan_line = 0;
+static grub_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+                         grub_uint8_t green,
+                         grub_uint8_t blue,
+                         grub_uint8_t alpha);
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+                            grub_color_t color,
+                            grub_uint8_t * red,
+                            grub_uint8_t * green,
+                            grub_uint8_t * blue,
+                            grub_uint8_t * alpha);
+
+
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+  return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+                   + ((unsigned long) ptr & 0x0000FFFF));
+}
 
 grub_err_t
 grub_vbe_probe (struct grub_vbe_info_block *info_block)
@@ -99,7 +141,7 @@
       vbe_ib->signature[3] = '2';
       
       /* Try to get controller info block.  */
-      status = grub_vbe_get_controller_info (vbe_ib);
+      status = grub_vbe_bios_get_controller_info (vbe_ib);
       if (status == 0x004F)
        {
          /* Copy it for later usage.  */
@@ -128,11 +170,13 @@
   grub_uint32_t old_mode;
   
   /* Make sure that VBE is supported.  */
-  if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* Try to get mode info.  */
-  if (grub_vbe_get_video_mode_info (mode, &active_mode_info) != GRUB_ERR_NONE)
+  grub_vbe_get_video_mode_info (mode, &active_mode_info);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* For all VESA BIOS modes, force linear frame buffer.  */
@@ -144,12 +188,12 @@
       /* Determine frame buffer pixel format.  */
       switch (active_mode_info.memory_model)
        {
-       case 0x04:
-         index_color_mode = 1;
+       case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+         framebuffer.index_color_mode = 1;
          break;
          
-       case 0x06:
-         index_color_mode = 0;
+       case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+         framebuffer.index_color_mode = 0;
          break;
          
        default:
@@ -160,51 +204,68 @@
     }
 
   /* Get current mode.  */
-  if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
+  grub_vbe_get_video_mode (&old_mode);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
   
   /* Try to set video mode.  */
-  status = grub_vbe_set_mode (mode, 0);
-  if (status != 0x004F)
+  status = grub_vbe_bios_set_mode (mode, 0);
+  if (status != GRUB_VBE_STATUS_OK)
     return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode);
 
   /* Save information for later usage.  */
-  active_mode = mode;
+  framebuffer.active_mode = mode;
 
   if (mode < 0x100)
     {
       /* If this is not a VESA mode, guess address.  */
-      framebuffer = (grub_uint8_t *) 0xA0000;
-      index_color_mode = 1;
+      framebuffer.ptr = (grub_uint8_t *) 0xA0000;
+      framebuffer.index_color_mode = 1;
     }
   else
     {
-      framebuffer = (grub_uint8_t *) active_mode_info.phys_base_addr;
+      framebuffer.ptr = (grub_uint8_t *) active_mode_info.phys_base_addr;
 
       if (controller_info.version >= 0x300)
-       bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
+       framebuffer.bytes_per_scan_line = 
active_mode_info.lin_bytes_per_scan_line;
       else
-       bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+       framebuffer.bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+    }
+    
+  /* Calculate bytes_per_pixel value.  */
+  switch(active_mode_info.bits_per_pixel)
+    {
+    case 32: framebuffer.bytes_per_pixel = 4; break;
+    case 24: framebuffer.bytes_per_pixel = 3; break;
+    case 16: framebuffer.bytes_per_pixel = 2; break;
+    case 15: framebuffer.bytes_per_pixel = 2; break;
+    case 8: framebuffer.bytes_per_pixel = 1; break;
+    default:    
+      grub_vbe_bios_set_mode (old_mode, 0);
+      return grub_error (GRUB_ERR_BAD_DEVICE, 
+                         "cannot set VBE mode %x", 
+                         mode);
+      break;
     }
 
   /* If video mode is in indexed color, setup default VGA palette.  */
-  if (index_color_mode)
+  if (framebuffer.index_color_mode)
     {
       struct grub_vbe_palette_data *palette
        = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
 
       /* Make sure that the BIOS can reach the palette.  */
       grub_memcpy (palette, vga_colors, sizeof (vga_colors));
-      status = grub_vbe_set_palette_data (sizeof (vga_colors) 
-                                          / sizeof (struct 
grub_vbe_palette_data), 
-                                          0, 
-                                          palette);
+      status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) 
+                                               / sizeof (struct 
grub_vbe_palette_data), 
+                                               0, 
+                                               palette);
 
       /* For now, ignore the status. Not sure if this is fatal.  */
 #if 0
-      if (status != 0x004F)
+      if (status != GRUB_VBE_STATUS_OK)
        {
-         grub_vbe_set_mode (old_mode, 0);
+         grub_vbe_bios_set_mode (old_mode, 0);
          return grub_error (GRUB_ERR_BAD_DEVICE,
                             "cannot set the default VGA palette");
        }
@@ -224,12 +285,13 @@
   grub_vbe_status_t status;
 
   /* Make sure that VBE is supported.  */
-  if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* Try to query current mode from VESA BIOS.  */
-  status = grub_vbe_get_mode (mode);
-  if (status != 0x004F)
+  status = grub_vbe_bios_get_mode (mode);
+  if (status != GRUB_VBE_STATUS_OK)
     return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current VBE mode");
 
   return GRUB_ERR_NONE;
@@ -244,15 +306,16 @@
   grub_vbe_status_t status;
 
   /* Make sure that VBE is supported.  */
-  if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* If mode is not VESA mode, skip mode info query.  */
   if (mode >= 0x100)
     {
       /* Try to get mode info from VESA BIOS.  */
-      status = grub_vbe_get_mode_info (mode, mi_tmp);
-      if (status != 0x004F)
+      status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
+      if (status != GRUB_VBE_STATUS_OK)
        return grub_error (GRUB_ERR_BAD_DEVICE,
                           "cannot get information on the mode %x", mode);
 
@@ -266,60 +329,75 @@
   return GRUB_ERR_NONE;
 }
 
-void
-grub_vbe_set_pixel_rgb (grub_uint32_t x,
-                       grub_uint32_t y,
-                        grub_uint8_t red,
-                        grub_uint8_t green,
-                        grub_uint8_t blue)
+static grub_uint8_t *
+grub_video_vbe_get_video_ptr (struct grub_video_render_target * source,
+                              grub_uint32_t x,
+                              grub_uint32_t y)
 {
-  grub_uint32_t value;
+  grub_uint8_t *ptr = 0;
+  
+  switch (source->mode_info.bpp)
+    {
+    case 32:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x * 4;
+      break;
 
-  if (x >= active_mode_info.x_resolution)
-    return;
+    case 24:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x * 3;
+      break;
 
-  if (y >= active_mode_info.y_resolution)
-    return;
+    case 16:
+    case 15:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x * 2;
+      break;
 
-  if (controller_info.version >= 0x300)
-    {
-      red >>= 8 - active_mode_info.lin_red_mask_size;
-      green >>= 8 - active_mode_info.lin_green_mask_size;
-      blue >>= 8 - active_mode_info.lin_blue_mask_size;
-
-      value = red << active_mode_info.lin_red_field_position;
-      value |= green << active_mode_info.lin_green_field_position;
-      value |= blue << active_mode_info.lin_blue_field_position;
+    case 8:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x;        
+      break;
     }
-  else
-    {
-      red >>= 8 - active_mode_info.red_mask_size;
-      green >>= 8 - active_mode_info.green_mask_size;
-      blue >>= 8 - active_mode_info.blue_mask_size;
+    
+  return ptr;
+}
 
-      value = red << active_mode_info.red_field_position;
-      value |= green << active_mode_info.green_field_position;
-      value |= blue << active_mode_info.blue_field_position;
-    }
+static void
+grub_video_vbe_draw_pixel (grub_uint32_t x,
+                           grub_uint32_t y,
+                           grub_color_t color)
+{
+  if (x >= render_target->mode_info.width)
+    return;
+
+  if (y >= render_target->mode_info.height)
+    return;
 
-  switch (active_mode_info.bits_per_pixel)
+  switch (render_target->mode_info.bpp)
     {
     case 32:
       {
-       grub_uint32_t *ptr = (grub_uint32_t *) (framebuffer
-                                               + y * bytes_per_scan_line
-                                               + x * 4);
+       grub_uint32_t *ptr;
+       
+        ptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (render_target,
+                                                             x,
+                                                             y);
        
-       *ptr = value;
+       *ptr = color;
       }
       break;
       
     case 24:
       {
-       grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
-                                             + y * bytes_per_scan_line
-                                             + x * 3);
-       grub_uint8_t *ptr2 = (grub_uint8_t *) &value;
+       grub_uint8_t *ptr;
+       grub_uint8_t *ptr2 = (grub_uint8_t *) &color;
+        
+        ptr = grub_video_vbe_get_video_ptr (render_target, x, y);
        
        ptr[0] = ptr2[0];
        ptr[1] = ptr2[1];
@@ -330,11 +408,25 @@
     case 16:
     case 15:
       {
-       grub_uint16_t *ptr = (grub_uint16_t *) (framebuffer
-                                               + y * bytes_per_scan_line
-                                               + x * 2);
+       grub_uint16_t *ptr;
+       
+        ptr = (grub_uint16_t *)grub_video_vbe_get_video_ptr (render_target,
+                                                             x,
+                                                             y);
        
-       *ptr = (grub_uint16_t) (value & 0xFFFF);
+       *ptr = (grub_uint16_t) (color & 0xFFFF);
+      }
+      break;
+
+    case 8:
+      {
+       grub_uint8_t *ptr;
+       
+        ptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (render_target,
+                                                            x,
+                                                            y);
+       
+       *ptr = (grub_uint8_t) (color & 0xFF);
       }
       break;
 
@@ -343,44 +435,1203 @@
     }
 }
 
-void
-grub_vbe_set_pixel_index (grub_uint32_t x,
-                          grub_uint32_t y,
-                          grub_uint8_t color)
+static grub_color_t
+grub_video_vbe_get_pixel (struct grub_video_render_target * source,
+                          grub_uint32_t x,
+                          grub_uint32_t y)
 {
-  if (x >= active_mode_info.x_resolution)
-    return;
+  grub_color_t color = 0;
+  
+  if (x >= source->mode_info.width)
+    return 0;
 
-  if (y >= active_mode_info.y_resolution)
-    return;
+  if (y >= source->mode_info.height)
+    return 0;
 
-  if (index_color_mode == 1)
+  switch (source->mode_info.bpp)
     {
-      grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
-                                           + y * bytes_per_scan_line
-                                           + x);
+    case 32:
+      {
+        color = *(grub_uint32_t *)grub_video_vbe_get_video_ptr (source, x, y);
+      }
+      break;
+      
+    case 24:
+      {
+       grub_uint8_t *ptr;
+        ptr = grub_video_vbe_get_video_ptr (source, x, y);
+        color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
+      }
+      break;
+
+    case 16:
+    case 15:
+      {
+        color = *(grub_uint16_t *)grub_video_vbe_get_video_ptr (source, x, y);
+      }
+      break;
+      
+    case 8:
+      {
+        color = *(grub_uint8_t *)grub_video_vbe_get_video_ptr (source, x, y);
+      }
+      break;
+      
+    default:
+      break;
+    }
+
+  return color;    
+}
+
+static grub_uint32_t initial_mode = 0;
+static grub_uint32_t mode_in_use = 0x55aa;
+static grub_uint16_t *mode_list = 0;
+
+static grub_err_t
+grub_video_vbe_init (void)
+{
+  grub_uint16_t *rm_mode_list;
+  grub_uint16_t *p;
+  grub_size_t mode_list_size;
+  struct grub_vbe_info_block info_block;
 
-      *ptr = color;
+  /* Check if there is adapter present.
+  
+     Firmware note: There has been a report that some cards store video mode
+     list in temporary memory. So we must first use vbe probe to get
+     refreshed information to receive valid pointers and data, and then
+     copy this information to somewhere safe.  */
+  grub_vbe_probe (&info_block);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+  
+  /* Copy modelist to local memory.  */
+  p = rm_mode_list = real2pm (info_block.video_mode_ptr);
+  while(*p++ != 0xFFFF)
+    ;
+  
+  mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_mode_list;
+  mode_list = grub_malloc (mode_list_size);
+  if (! mode_list)
+    return grub_errno;
+  grub_memcpy (mode_list, rm_mode_list, mode_list_size);
+
+  /* Adapter could be found, figure out initial video mode.  */
+  grub_vbe_get_video_mode (&initial_mode);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      /* Free allocated resources.  */
+      grub_free (mode_list);
+      mode_list = 0;
+      
+      return grub_errno;
+    }
+
+  /* Reset frame buffer and render target variables.  */
+  grub_memset (&framebuffer, 0, sizeof(framebuffer));  
+  render_target = &framebuffer.render_target;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_fini (void)
+{
+  grub_vbe_status_t status;
+  
+  /* Restore old video mode.  */
+  status = grub_vbe_bios_set_mode (initial_mode, 0);
+  if (status != GRUB_VBE_STATUS_OK)
+    {
+      /* TODO: Decide, is this something we want to do.  */
+      return grub_errno;
+    }
+  
+  /* TODO: Free any resources allocated by driver.  */
+  grub_free (mode_list);
+  mode_list = 0;
+
+  /* TODO: destroy render targets.  */
+  
+  /* Return success to caller.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_setup (unsigned int width,
+                      unsigned int height,
+                      unsigned int mode_type)
+{
+  grub_uint16_t *p;
+  struct grub_vbe_mode_info_block mode_info;
+  struct grub_vbe_mode_info_block best_mode_info;
+  grub_uint32_t best_mode = 0;
+  unsigned int i;
+  
+  /* Walk thru mode list and try to find matching mode.  */
+  for (p = mode_list; *p != 0xFFFF; p++)
+    {
+      grub_uint32_t mode = *p;
+      
+      grub_vbe_get_video_mode_info (mode, &mode_info);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          /* Could not retrieve mode info, retreat.  */
+          grub_errno = GRUB_ERR_NONE;
+          break;
+        }
+
+      if ((mode_info.mode_attributes & 0x001) == 0)
+        /* If not available, skip it.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x002) == 0)
+        /* Not enough information.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x008) == 0)
+        /* Monochrome is unusable.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x080) == 0)
+        /* We support only linear frame buffer modes.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x010) == 0)
+        /* We allow only graphical modes.  */
+        continue;
+      
+      if ((mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+          && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+        /* Not compatible memory model.  */
+        continue;
+      
+      if ((mode_info.x_resolution != width)
+          || (mode_info.y_resolution != height))
+        /* Non matching resolution.  */
+        continue;
+
+      /* Check if user requested RGB or index color mode.  */
+      if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+        {
+          if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+              && (mode_info.memory_model != 
GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
+            /* Requested only index color modes.  */
+            continue;
+
+          if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
+              && (mode_info.memory_model != 
GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+            /* Requested only RGB modes.  */
+            continue;
+        }
+      
+      /* Select mode with most number of bits per pixel.  */
+      if (best_mode != 0)
+       {
+         if (mode_info.bits_per_pixel < best_mode_info.bits_per_pixel)
+           continue;
+       }
+      
+      /* Save so far best mode information for later use.  */
+      best_mode = mode;
+      grub_memcpy (&best_mode_info, &mode_info, sizeof (mode_info));
+    }
+
+  /* Try to initialize best mode found.  */
+  if (best_mode != 0)
+    {
+      /* If this fails, then we have mode selection heuristics problem, 
+         or adapter failure.  */
+      grub_vbe_set_video_mode (best_mode, &active_mode_info);
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+      
+      /* Now we are happily in requested video mode. Cache some info
+         in order to fasten later operations.  */
+      mode_in_use = best_mode;
+
+      /* Reset render target to framebuffer one.  */
+      render_target = &framebuffer.render_target;
+      
+      /* Fill mode info details in framebuffer's render target.  */
+      render_target->mode_info.width = active_mode_info.x_resolution;
+      render_target->mode_info.height = active_mode_info.y_resolution;
+      
+      render_target->mode_info.width = active_mode_info.x_resolution;
+      render_target->mode_info.height = active_mode_info.y_resolution;
+
+      if (framebuffer.index_color_mode)
+        {
+          render_target->mode_info.mode_type = 
GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+        }
+      else
+        {
+          render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+        }
+
+      render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
+      render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+      render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
+      render_target->mode_info.number_of_colors = 256; /* TODO: fix me.  */
+      render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
+      render_target->mode_info.red_field_pos = 
active_mode_info.red_field_position;
+      render_target->mode_info.green_mask_size = 
active_mode_info.green_mask_size;
+      render_target->mode_info.green_field_pos = 
active_mode_info.green_field_position;
+      render_target->mode_info.blue_mask_size = 
active_mode_info.blue_mask_size;
+      render_target->mode_info.blue_field_pos = 
active_mode_info.blue_field_position;
+      render_target->mode_info.reserved_mask_size = 
active_mode_info.rsvd_mask_size;
+      render_target->mode_info.reserved_field_pos = 
active_mode_info.rsvd_field_position;
+     
+      /* Reset viewport to match new mode.  */
+      render_target->viewport.x = 0;
+      render_target->viewport.y = 0;
+      render_target->viewport.width = active_mode_info.x_resolution;
+      render_target->viewport.height = active_mode_info.y_resolution;
+
+      /* Set framebuffer pointer and mark it as non allocated.  */
+      render_target->is_allocated = 0;
+      render_target->data = framebuffer.ptr;
+
+      /* Copy default palette to initialize emulated palette.  */
+      for (i = 0; 
+           i < (sizeof (vga_colors) 
+                / sizeof (struct grub_vbe_palette_data));
+           i++)
+        {
+          framebuffer.palette[i].r = vga_colors[i].red;
+          framebuffer.palette[i].g = vga_colors[i].green;
+          framebuffer.palette[i].b = vga_colors[i].blue;
+          framebuffer.palette[i].a = 0xFF;
+        }
+
+      return GRUB_ERR_NONE;
+    }
+
+  /* Couldn't found matching mode.  */
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
+}
+
+static grub_err_t
+grub_video_vbe_get_info (struct grub_video_mode_info * mode_info)
+{
+  /* Copy mode info from active render target.  */
+  grub_memcpy (mode_info, 
+               &render_target->mode_info, 
+               sizeof (struct grub_video_mode_info));
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_palette (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned int i;
+  
+  if (framebuffer.index_color_mode)
+    {
+      /* TODO: Implement setting indexed color mode palette to hardware.  */
+      //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) 
+      //                                         / sizeof (struct 
grub_vbe_palette_data), 
+      //                                         0, 
+      //                                         palette);
+      
+    }
+
+  /* Then set color to emulated palette. */
+  for (i = 0; (i < count) && ((i + start) < 256); i++)
+    {
+      framebuffer.palette[start + i] = palette_data[i];
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_palette (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned int i;
+
+  /* Assume that we know everything from index color palette.  */
+  for (i = 0; (i < count) && ((i + start) < 256); i++)
+    {
+      palette_data[i] = framebuffer.palette[start + i];
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_viewport (unsigned int x,
+                             unsigned int y,
+                             unsigned int width,
+                             unsigned int height)
+{
+  /* Make sure viewport is withing screen dimensions. If viewport was set
+     to be out of the reqion, mark its size as zero.  */
+  if (x > active_mode_info.x_resolution)
+    {
+      x = 0;
+      width = 0;
+    }
+  
+  if (y > active_mode_info.y_resolution)
+    {
+      y = 0;
+      height = 0;
+    }
+    
+  if (x + width > active_mode_info.x_resolution)
+    {
+      width = active_mode_info.x_resolution - x;
+    }
+
+  if (y + height > active_mode_info.y_resolution)
+    {
+      height = active_mode_info.y_resolution - y;
+    }
+
+  render_target->viewport.x = x;
+  render_target->viewport.y = y;
+  render_target->viewport.width = width;
+  render_target->viewport.height = height;
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_viewport (unsigned int * x,
+                             unsigned int * y,
+                             unsigned int * width,
+                             unsigned int * height)
+{
+  if (x) *x = render_target->viewport.x;
+  if (y) *y = render_target->viewport.y;
+  if (width) *width = render_target->viewport.width;
+  if (height) *height = render_target->viewport.height;
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_color_t
+grub_video_vbe_map_color (grub_uint32_t color_name)
+{
+  /* TODO: implement color theme mapping code.  */
+  
+  if (color_name < 256)
+    {
+      if ((render_target->mode_info.mode_type
+           & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+        {
+          return color_name;
+        }
+      else
+        {
+          grub_color_t color;
+          
+          color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
+                                          framebuffer.palette[color_name].g,
+                                          framebuffer.palette[color_name].b);
+          
+          return color;
+        }
+    }
+    
+  return 0;
+}
+
+static grub_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+                        grub_uint8_t green,
+                        grub_uint8_t blue)
+{
+  if ((render_target->mode_info.mode_type 
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      int minindex = 0;
+      int delta = 0;
+      int tmp;
+      int val;
+      int i;
+      
+      /* Find best matching color.  */
+      for (i = 0; i < 256; i++)
+        {
+          val = framebuffer.palette[i].r - red;
+          tmp = val * val;
+          val = framebuffer.palette[i].g - green;
+          tmp += val * val;
+          val = framebuffer.palette[i].b - blue;
+          tmp += val * val;
+          
+          if (i == 0)
+            delta = tmp;
+          
+          if (tmp < delta)
+            {
+              delta = tmp;
+              minindex = i;
+              if (tmp == 0)
+                break;
+            }
+        }
+      
+      return minindex;
     }
   else
     {
-      color &= 0x0F;
+      grub_uint32_t value;
+      grub_uint8_t alpha = 255; /* Opaque color.  */
       
-      if (color < 16)
-       {
-         grub_vbe_set_pixel_rgb (x,
-                                  y,
-                                  vga_colors[color].red,
-                                  vga_colors[color].green,
-                                  vga_colors[color].blue);
-       }
+      red >>= 8 - render_target->mode_info.red_mask_size;
+      green >>= 8 - render_target->mode_info.green_mask_size;
+      blue >>= 8 - render_target->mode_info.blue_mask_size;
+      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+      value = red << render_target->mode_info.red_field_pos;
+      value |= green << render_target->mode_info.green_field_pos;
+      value |= blue << render_target->mode_info.blue_field_pos;
+      value |= alpha << render_target->mode_info.reserved_field_pos;
+      
+      return value;
+    }
+
+}
+
+static grub_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+                         grub_uint8_t green,
+                         grub_uint8_t blue,
+                         grub_uint8_t alpha)
+{
+  if ((render_target->mode_info.mode_type 
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      /* No alpha available in index color modes, just use
+         same value as in only RGB modes.  */
+      return grub_video_vbe_map_rgb (red, green, blue);
+    }
+  else
+    {
+      grub_uint32_t value;
+      
+      red >>= 8 - render_target->mode_info.red_mask_size;
+      green >>= 8 - render_target->mode_info.green_mask_size;
+      blue >>= 8 - render_target->mode_info.blue_mask_size;
+      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+      value = red << render_target->mode_info.red_field_pos;
+      value |= green << render_target->mode_info.green_field_pos;
+      value |= blue << render_target->mode_info.blue_field_pos;
+      value |= alpha << render_target->mode_info.reserved_field_pos;
+      
+      return value;
+    }
+}
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+                            grub_color_t color,
+                            grub_uint8_t * red,
+                            grub_uint8_t * green,
+                            grub_uint8_t * blue,
+                            grub_uint8_t * alpha)
+{
+  if ((source->mode_info.mode_type 
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      /* If we have out of bounds color, return trasnparent black.  */
+      if (color > 255)
+        {
+          *red = 0;
+          *green = 0;
+          *blue = 0;
+          *alpha = 0;
+          return;
+        }
+        
+      *red = framebuffer.palette[color].r;
+      *green = framebuffer.palette[color].g;
+      *blue = framebuffer.palette[color].b;
+      *alpha = framebuffer.palette[color].a;
+      return;
+    }
+  else
+    {      
+      grub_uint32_t tmp;
+      
+      /* Get red component.  */
+      tmp = color >> source->mode_info.red_field_pos;
+      tmp &= (1 << source->mode_info.red_mask_size) - 1;
+      tmp <<= 8 - source->mode_info.red_mask_size;
+      tmp |= (1 << (8 - source->mode_info.red_mask_size)) - 1;
+      *red = tmp & 0xFF;
+
+      /* Get green component.  */
+      tmp = color >> source->mode_info.green_field_pos;
+      tmp &= (1 << source->mode_info.green_mask_size) - 1;
+      tmp <<= 8 - source->mode_info.green_mask_size;
+      tmp |= (1 << (8 - source->mode_info.green_mask_size)) - 1;
+      *green = tmp & 0xFF;
+
+      /* Get blue component.  */
+      tmp = color >> source->mode_info.blue_field_pos;
+      tmp &= (1 << source->mode_info.blue_mask_size) - 1;
+      tmp <<= 8 - source->mode_info.blue_mask_size;
+      tmp |= (1 << (8 - source->mode_info.blue_mask_size)) - 1;
+      *blue = tmp & 0xFF;
+
+      /* Get alpha component.  */
+      if (source->mode_info.reserved_mask_size > 0)
+        {
+          tmp = color >> source->mode_info.reserved_field_pos;
+          tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
+          tmp <<= 8 - source->mode_info.reserved_mask_size;
+          tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
+        }
       else
-       {
-         grub_vbe_set_pixel_rgb (x,
-                                  y,
-                                  0,
-                                  0,
-                                  0);
-       }
+        {
+          /* If there is no alpha component, assume it opaque.  */
+          tmp = 255;
+        }
+
+      *alpha = tmp & 0xFF;
+    }
+}
+
+static grub_err_t
+grub_video_vbe_fill_rect (grub_color_t color,
+                          int x,
+                          int y,
+                          unsigned int width,
+                          unsigned int height)
+{
+  unsigned int i, j;
+
+  /* Make sure there is something to do.  */
+  if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (x < 0)
+    {
+      width += x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      y = 0;
+    }
+  
+  if ((x + width) > render_target->viewport.width)
+    {
+      width = render_target->viewport.width - x;
+    }
+  if ((y + height) > render_target->viewport.height)
+    {
+      height = render_target->viewport.height - y;
+    }
+
+  // add viewport offset
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_video_vbe_draw_pixel (x+i, y+j, color);
+        }
+    }
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
+                           grub_color_t color,
+                           int x,
+                           int y)
+{
+  unsigned int width;
+  unsigned int charwidth;
+  unsigned int height;
+  unsigned int i;
+  unsigned int j;
+  unsigned int x_offset = 0;
+  unsigned int y_offset = 0;
+  
+  /* Make sure there is something to do.  */
+  if (x > (int)render_target->viewport.width)
+    return GRUB_ERR_NONE;
+    
+  if (y > (int)render_target->viewport.height)
+    return GRUB_ERR_NONE;
+
+  /* Calculate glyph dimensions.  */
+  width = ((glyph->width + 7) / 8) * 8;
+  charwidth = width;
+  height = glyph->height;
+  
+  if (x + (int)width < 0)
+    return GRUB_ERR_NONE;
+    
+  if (y + (int)height < 0)
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (x < 0)
+    {
+      width += x;
+      x_offset = (unsigned int)-x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      y_offset = (unsigned int)-y;
+      y = 0;
+    }
+  
+  if ((x + width) > render_target->viewport.width)
+    {
+      width = render_target->viewport.width - x;
+    }
+  if ((y + height) > render_target->viewport.height)
+    {
+      height = render_target->viewport.height - y;
+    }
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+  
+  /* Draw glyph.  */
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          if ((glyph->bitmap[((i + x_offset) / 8) 
+                             + (j + y_offset) * (charwidth / 8)] 
+               & (1 << ((charwidth - (i + x_offset) - 1) % 8))))
+            {
+              grub_video_vbe_draw_pixel (x+i, y+j, color);
+            }
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap,
+                            int x,
+                            int y,
+                            int offset_x,
+                            int offset_y,
+                            unsigned int width,                            
+                            unsigned int height)
+{
+  /* Make sure there is something to do.  */
+  if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (offset_x < 0)
+    {
+      width += offset_x;
+      x -= offset_x;
+      offset_x = 0;
+    }
+    
+  if (offset_y < 0)
+    {
+      height += offset_y;
+      y -= offset_y;
+      offset_y = 0;
+    }
+
+  if (x < 0)
+    {
+      width += x;
+      offset_x += (unsigned int)-x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      offset_y += (unsigned int)-y;
+      y = 0;
+    }
+  
+  if ((x + width) > render_target->viewport.width)
+    {
+      width = render_target->viewport.width - x;
+    }
+  if ((y + height) > render_target->viewport.height)
+    {
+      height = render_target->viewport.height - y;
+    }
+
+  /* TODO: Limit drawing to bitmap dimensions.  */
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* TODO: Render bitmap.  */
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_render_target (struct grub_video_render_target * source,
+                                   int x,
+                                   int y,
+                                   int offset_x,
+                                   int offset_y,
+                                   unsigned int width,
+                                   unsigned int height)
+{
+  unsigned int i;
+  unsigned int j;
+
+  /* Make sure there is something to do.  */
+  if ((width == 0) || (height == 0))
+    return GRUB_ERR_NONE;
+  if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;    
+  if ((x + (int)source->mode_info.width) < 0)
+    return GRUB_ERR_NONE;
+  if ((y + (int)source->mode_info.height) < 0)
+    return GRUB_ERR_NONE;    
+  if ((offset_x > (int)source->mode_info.width) 
+      || (offset_x + (int)source->mode_info.width < 0))
+    return GRUB_ERR_NONE;
+  if ((offset_y > (int)source->mode_info.height) 
+      || (offset_y + (int)source->mode_info.height < 0))
+    return GRUB_ERR_NONE;    
+
+  /* If we have negative coordintes, optimize drawing to minimum.  */
+  if (offset_x < 0)
+    {
+      width += offset_x;
+      x -= offset_x;
+      offset_x = 0;
+    }
+    
+  if (offset_y < 0)
+    {
+      height += offset_y;
+      y -= offset_y;
+      offset_y = 0;
+    }
+    
+  if (x < 0)
+    {
+      width += x;
+      offset_x += (unsigned int)-x;
+      x = 0;
+    }
+    
+  if (y < 0)
+    {
+      height += y;
+      offset_y += (unsigned int)-y;
+      y = 0;
+    }
+  
+  /* Do not allow drawing out of viewport.  */
+  if ((x + width) > render_target->viewport.width)
+    {
+      width = render_target->viewport.width - x;
+    }
+  if ((y + height) > render_target->viewport.height)
+    {
+      height = render_target->viewport.height - y;
+    }
+  
+  if ((offset_x + width) > source->mode_info.width)
+    {
+      width = source->mode_info.width - offset_x;
+    }
+  if ((offset_y + height) > source->mode_info.height)
+    {
+      height = source->mode_info.height - offset_y;
+    }
+  
+  /* Limit drawing to source render target dimensions.  */
+  if (width > source->mode_info.width)
+    {
+      width = source->mode_info.width;
+    }
+  
+  if (height > source->mode_info.height)
+    {
+      height = source->mode_info.height;
+    }
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* Render.  */
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {              
+          grub_uint8_t src_red;
+          grub_uint8_t src_green;
+          grub_uint8_t src_blue;
+          grub_uint8_t src_alpha;
+          grub_uint8_t dst_red;
+          grub_uint8_t dst_green;
+          grub_uint8_t dst_blue;
+          grub_uint8_t dst_alpha;
+          grub_color_t src_color;
+          grub_color_t dst_color;
+          
+          src_color = grub_video_vbe_get_pixel (source, i + offset_x, j + 
offset_y);
+          grub_video_vbe_unmap_color (source, 
+                                      src_color, 
+                                      &src_red, 
+                                      &src_green, 
+                                      &src_blue, 
+                                      &src_alpha);
+              
+          if (src_alpha == 0) continue;
+          
+          if (src_alpha == 255)
+            {
+              dst_color = grub_video_vbe_map_rgba (src_red, 
+                                                   src_green,
+                                                   src_blue,
+                                                   src_alpha);
+               grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+               continue;
+            }
+
+          dst_color = grub_video_vbe_get_pixel (render_target,
+                                                x + i,
+                                                y + j);
+          
+          grub_video_vbe_unmap_color (render_target, 
+                                      dst_color, 
+                                      &dst_red, 
+                                      &dst_green, 
+                                      &dst_blue, 
+                                      &dst_alpha);
+          
+          dst_red = (((src_red * src_alpha)
+                      + (dst_red * (255 - src_alpha))) / 255);
+          dst_green = (((src_green * src_alpha)
+                        + (dst_green * (255 - src_alpha))) / 255);
+          dst_blue = (((src_blue * src_alpha)
+                       + (dst_blue * (255 - src_alpha))) / 255);
+                    
+          dst_alpha = src_alpha;
+          dst_color = grub_video_vbe_map_rgba (dst_red, 
+                                               dst_green,
+                                               dst_blue,
+                                               dst_alpha);
+
+           grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_scroll (grub_color_t color,
+                       int dx,
+                       int dy)
+{
+  int width;
+  int height;
+  int src_x;
+  int src_y;
+  int dst_x;
+  int dst_y;
+  
+  /* TODO: Fix x & y handling.  */
+  
+  /* 1. Check if we have something to do.  */
+  if ((dx == 0) && (dy == 0))
+    return GRUB_ERR_NONE;
+
+  width = render_target->viewport.width - grub_abs(dx);
+  height = render_target->viewport.height - grub_abs(dy);
+  
+  if (dx < 0)
+    {
+      src_x = render_target->viewport.x - dx;
+      dst_x = render_target->viewport.x;
+    }
+  else
+    {
+      src_x = render_target->viewport.x;
+      dst_x = render_target->viewport.x + dx;
+    }
+
+  if (dy < 0)
+    {
+      src_y = render_target->viewport.y - dy;
+      dst_y = render_target->viewport.y;
+    }
+  else
+    {
+      src_y = render_target->viewport.y;
+      dst_y = render_target->viewport.y + dy;
+    }
+
+  /* 2. Check if there is need to copy data.  */
+  if ((grub_abs (dx) < render_target->viewport.width) 
+       && (grub_abs (dy) < render_target->viewport.height))
+    {
+      /* 3. Move data in render target.  */
+      grub_uint8_t *src;
+      grub_uint8_t *dst;
+      int j;
+            
+      for (j = 0; j < height; j++)
+        {
+          dst = grub_video_vbe_get_video_ptr (render_target, dst_x, dst_y + j);
+          src = grub_video_vbe_get_video_ptr (render_target, src_x, src_y + j);
+          grub_memmove (dst, 
+                        src,
+                        width * render_target->mode_info.bytes_per_pixel);
+        }
+    }
+  
+  /* 4. Fill empty space with specified color. In this implementation
+     there might be colliding areas but at the moment there is no need
+     to optimize this.  */
+
+  // TODO: PROOFREAD THIS!.
+  
+  /* 4a. Fill top & bottom parts.  */
+  if (dy > 0)
+    {
+      grub_video_vbe_fill_rect (color,
+                                0, 0,
+                                render_target->viewport.width, dy);
+    }
+  else if (dy < 0)
+    {
+      if (render_target->viewport.height < grub_abs(dy))
+        dy = -render_target->viewport.height;
+        
+      grub_video_vbe_fill_rect (color, 
+                                0, render_target->viewport.height + dy, 
+                                render_target->viewport.width, -dy);
+    }
+
+  /* 4b. Fill left & right parts.  */
+  if (dx > 0)
+    {
+      grub_video_vbe_fill_rect (color, 
+                                0, 0, 
+                                dx, render_target->viewport.height);
+    }
+  else if (dx < 0)
+    {
+      if (render_target->viewport.width < grub_abs(dx))
+        dx = -render_target->viewport.width;
+        
+      grub_video_vbe_fill_rect (color, 
+                                render_target->viewport.width + dx, 0, 
+                                -dx, render_target->viewport.height);
+    }
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t 
+grub_video_vbe_swap_buffers (void)
+{
+  /* TODO: Implement buffer swapping.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_create_render_target (struct grub_video_render_target * * 
result,
+                                     unsigned int mode_type,
+                                     unsigned int width,
+                                     unsigned int height)
+{
+  struct grub_video_render_target *target;
+  unsigned int size;
+  
+  /* Validate arguments.  */
+  if ((! result)
+      || (width == 0)
+      || (height == 0))
+    {
+      return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                         "invalid argument given.");
+    }
+  
+  /* Allocate memory for render target.  */
+  target = grub_malloc (sizeof (struct grub_video_render_target));
+  if (! target)
+    return grub_errno;
+  
+  /* TODO: Implement other types too.  */
+  size = (width * 4) * height;
+  
+  target->data = grub_malloc (size);
+  if (! target->data)
+    {
+      grub_free (target);
+      return grub_errno;
+    }
+  
+  /* Clear render target with black and maximum transparency.  */
+  grub_memset (target->data, 0, size);
+
+  /* Mark render target as allocated.  */
+  target->is_allocated = 1;
+  
+  /* Maximize viewport.  */
+  target->viewport.x = 0;
+  target->viewport.y = 0;
+  target->viewport.width = width;
+  target->viewport.height = height;
+
+  /* Setup render target format.  */
+  target->mode_info.width = width;
+  target->mode_info.height = height;
+  target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB 
+                                | GRUB_VIDEO_MODE_TYPE_ALPHA;
+  target->mode_info.bpp = 32;
+  target->mode_info.bytes_per_pixel = 4;
+  target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
+  target->mode_info.number_of_colors = 256;
+  target->mode_info.red_mask_size = 8;
+  target->mode_info.red_field_pos = 0;
+  target->mode_info.green_mask_size = 8;
+  target->mode_info.green_field_pos = 8;
+  target->mode_info.blue_mask_size = 8;
+  target->mode_info.blue_field_pos = 16;
+  target->mode_info.reserved_mask_size = 8;
+  target->mode_info.reserved_field_pos = 24;
+
+  /* TODO: Add render target to render target list.  */
+  
+  /* Save result to caller.  */
+  *result = target;
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_delete_render_target (struct grub_video_render_target * target)
+{
+  /* If there is no target, then just return without error.  */
+  if (! target)
+    {
+      return GRUB_ERR_NONE;
+    }
+    
+  /* TODO: Delist render target fron render target list.  */
+    
+  /* If this is software render target, free it's memory.  */
+  if (target->is_allocated)
+    {
+      grub_free (target->data);
+    }        
+        
+  /* Free render target.  */
+  grub_free (target);
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_active_render_target (struct grub_video_render_target * 
target)
+{
+  if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
+    {
+      render_target = &framebuffer.render_target;
+      
+      return GRUB_ERR_NONE;
     }
+  
+  if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
+    {
+      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+                         "double buffering not implemented yet.");
+    }
+    
+  if (! target->data)
+    {
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                         "invalid render target given.");
+    }
+  
+  render_target = target;
+  
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_vbe_adapter =
+  {
+    .name = "VESA BIOS Extension Video Driver",
+
+    .init = grub_video_vbe_init,
+    .fini = grub_video_vbe_fini,
+    .setup = grub_video_vbe_setup,
+    .get_info = grub_video_vbe_get_info,
+    .set_palette = grub_video_vbe_set_palette,
+    .get_palette = grub_video_vbe_get_palette,
+    .set_viewport = grub_video_vbe_set_viewport,
+    .get_viewport = grub_video_vbe_get_viewport,
+    .map_color = grub_video_vbe_map_color,
+    .map_rgb = grub_video_vbe_map_rgb,
+    .map_rgba = grub_video_vbe_map_rgba,
+    .fill_rect = grub_video_vbe_fill_rect,
+    .blit_glyph = grub_video_vbe_blit_glyph,
+    .blit_bitmap = grub_video_vbe_blit_bitmap,
+    .blit_render_target = grub_video_vbe_blit_render_target,
+    .scroll = grub_video_vbe_scroll,
+    .swap_buffers = grub_video_vbe_swap_buffers,
+    .create_render_target = grub_video_vbe_create_render_target,
+    .delete_render_target = grub_video_vbe_delete_render_target,
+    .set_active_render_target = grub_video_vbe_set_active_render_target,
+    
+    .next = 0  
+  };
+
+GRUB_MOD_INIT(video_i386_pc_vbe)
+{
+  my_mod = mod;
+  grub_video_register (&grub_video_vbe_adapter);
+}
+
+GRUB_MOD_FINI(video_i386_pc_ovbe)
+{
+  grub_video_unregister (&grub_video_vbe_adapter);
 }
diff -ruN -x '*CVS*' grub2/video/video.c grub2.new/video/video.c
--- grub2/video/video.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/video/video.c     2006-03-02 16:49:13.022283256 +0200
@@ -0,0 +1,482 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  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.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/font.h>
+#include <grub/term.h>
+
+/* The list of video adapters registerd to system.  */
+static grub_video_adapter_t grub_video_adapter_list;
+
+/* Active video adapter.  */
+static grub_video_adapter_t grub_video_adapter_active;
+
+static grub_dl_t my_mod;
+
+void
+grub_video_register (grub_video_adapter_t adapter)
+{
+  adapter->next = grub_video_adapter_list;
+  grub_video_adapter_list = adapter;
+}
+
+void
+grub_video_unregister (grub_video_adapter_t adapter)
+{
+  grub_video_adapter_t *p, q;
+  
+  for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == adapter)
+      {
+        *p = q->next;
+        break;
+      }                                    
+}
+
+void
+grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
+{
+  grub_video_adapter_t p;
+  
+  for (p = grub_video_adapter_list; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+grub_err_t
+grub_video_setup (unsigned int width,
+                  unsigned int height,
+                  unsigned int mode_type)
+{
+  grub_video_adapter_t p;
+
+  /* De-activate last set video adapter.  */
+  if (grub_video_adapter_active)
+    {
+      /* Finalize adapter.  */
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+        
+      /* Mark active adapter as not set.  */
+      grub_video_adapter_active = 0;
+    }
+  
+  /* Loop thru all possible video adapter trying to find requested mode.  */
+  for (p = grub_video_adapter_list; p; p = p->next)
+    {
+      /* Try to initialize adapter, if can't skip to next.  */
+      p->init ();
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_errno = GRUB_ERR_NONE;
+          continue;
+        }
+
+      /* Try to initialize video mode.  */      
+      p->setup (width, height, mode_type);
+      if (grub_errno == GRUB_ERR_NONE)
+        {
+          /* Valid mode found from adapter, and it has been activated.
+             Specify it as active adapter.  */
+          grub_video_adapter_active = p;
+          return GRUB_ERR_NONE;
+        }
+      else
+        {
+          grub_errno = GRUB_ERR_NONE;        
+        }
+
+      /* No valid mode found in this adapter, finalize adapter.  */
+      p->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+    }
+  
+  /* We couldn't find suitable adapter for specified mode.  */
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, 
+                     "Can't locate valid adapter for mode");
+}
+
+grub_err_t
+grub_video_restore (void)
+{
+  if (grub_video_adapter_active)
+    {
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+      
+      grub_video_adapter_active = 0;
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_get_info (struct grub_video_mode_info * mode_info)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+  
+  return grub_video_adapter_active->get_info (mode_info);
+}
+
+grub_err_t
+grub_video_set_palette (unsigned int start,
+                        unsigned int count,
+                        struct grub_video_palette_data *palette_data)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+  
+  return grub_video_adapter_active->set_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_get_palette (unsigned int start,
+                        unsigned int count,
+                        struct grub_video_palette_data *palette_data)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+  
+  return grub_video_adapter_active->get_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_set_viewport (unsigned int x,
+                         unsigned int y,
+                         unsigned int width,
+                         unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->set_viewport (x, y, width, height);
+}
+
+grub_err_t
+grub_video_get_viewport (unsigned int * x,
+                         unsigned int * y,
+                         unsigned int * width,
+                         unsigned int * height)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->get_viewport (x, y, width, height);
+}
+
+grub_color_t
+grub_video_map_color (grub_uint32_t color_name)
+{
+  if (! grub_video_adapter_active)
+    {
+      return 0;
+    }
+
+  return grub_video_adapter_active->map_color (color_name);
+}
+
+grub_color_t
+grub_video_map_rgb (grub_uint8_t red,
+                    grub_uint8_t green,
+                    grub_uint8_t blue)
+{
+  if (! grub_video_adapter_active)
+    {
+      return 0;
+    }
+
+  return grub_video_adapter_active->map_rgb (red, green, blue);
+}
+
+grub_color_t
+grub_video_map_rgba (grub_uint8_t red,
+                     grub_uint8_t green,
+                     grub_uint8_t blue,
+                     grub_uint8_t alpha)
+{
+  if (! grub_video_adapter_active)
+    {
+      return 0;
+    }
+
+  return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
+}
+
+grub_err_t
+grub_video_fill_rect (grub_color_t color,
+                      int x,
+                      int y,
+                      unsigned int width,
+                      unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->fill_rect (color, x, y, width, height);
+}
+
+grub_err_t
+grub_video_blit_glyph (struct grub_font_glyph * glyph,
+                       grub_color_t color,
+                       int x,
+                       int y)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
+}
+
+grub_err_t
+grub_video_blit_bitmap (struct grub_video_bitmap * bitmap,
+                        int x,
+                        int y,
+                        int offset_x,
+                        int offset_y,
+                        unsigned int width,
+                        unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->blit_bitmap (bitmap, 
+                                                 x, y, 
+                                                 offset_x, offset_y,
+                                                 width, height);
+}
+
+grub_err_t
+grub_video_blit_render_target (struct grub_video_render_target * target,
+                               int x,
+                               int y,
+                               int offset_x,
+                               int offset_y,
+                               unsigned int width,
+                               unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->blit_render_target (target, 
+                                                        x, y,
+                                                        offset_x, offset_y, 
+                                                        width, height);
+}
+
+grub_err_t
+grub_video_scroll (grub_color_t color,
+                   int dx,
+                   int dy)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->scroll (color, dx, dy);
+}
+
+grub_err_t
+grub_video_swap_buffers (void)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->swap_buffers ();
+}
+
+grub_err_t
+grub_video_create_render_target (struct grub_video_render_target * * result,
+                                 unsigned int mode_type,
+                                 unsigned int width,
+                                 unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->create_render_target (result,
+                                                          mode_type,
+                                                          width,
+                                                          height);
+}
+
+grub_err_t
+grub_video_delete_render_target (struct grub_video_render_target * target)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->delete_render_target (target);
+}
+
+grub_err_t
+grub_video_set_active_render_target (struct grub_video_render_target * target)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->set_active_render_target (target);
+}
+
+static grub_err_t
+grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
+                    int argc __attribute__ ((unused)),
+                    char **args __attribute__ ((unused)))
+{
+  if (grub_video_setup (1024, 
+                        768,
+                        GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+    {
+      return grub_errno;
+    }
+  
+  grub_getkey ();
+
+  grub_uint32_t color;
+  grub_uint32_t x, y, width, height;
+  int i;
+  struct grub_font_glyph glyph;
+  struct grub_video_render_target *text_layer;
+  grub_color_t palette[16];
+  
+  grub_video_get_viewport (&x, &y, &width, &height);
+
+  grub_video_create_render_target (&text_layer,
+                                   GRUB_VIDEO_MODE_TYPE_RGB
+                                   | GRUB_VIDEO_MODE_TYPE_ALPHA,
+                                   width,
+                                   height);
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);      
                             
+
+  color = grub_video_map_rgb (0, 0, 0);
+  grub_video_fill_rect (color, 0, 0, width, height);
+  
+  color = grub_video_map_rgb (255,0,0);
+  grub_video_fill_rect (color, 0, 0, 100, 100);
+  
+  color = grub_video_map_rgb (0,255,255);
+  grub_video_fill_rect (color, 100, 100, 100, 100);
+
+  grub_font_get_glyph ('*', &glyph);  
+  grub_video_blit_glyph (&glyph, color, 200 ,0);
+
+  grub_video_set_viewport (x + 150, y + 150, width - 150*2, height - 150*2);
+  color = grub_video_map_rgb (77,33,77);
+  grub_video_fill_rect (color, 0, 0, width, height);
+  
+  grub_video_set_active_render_target (text_layer);
+  
+  color = grub_video_map_rgb (255,255,255);
+  
+  grub_font_get_glyph ('A', &glyph);  
+  grub_video_blit_glyph (&glyph, color, 16, 16);
+  grub_font_get_glyph ('B', &glyph);  
+  grub_video_blit_glyph (&glyph, color, 16*2, 16);
+
+  grub_font_get_glyph ('*', &glyph);  
+  
+  for (i = 0; i < 16; i++)
+    {
+      color = grub_video_map_color (i);
+      palette[i] = color;
+      grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
+    }
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  for (i = 0; i < 255; i++)
+    {
+      color = grub_video_map_rgb (i, 33, 77);
+      grub_video_fill_rect (color, 0, 0, width, height);
+      grub_video_blit_render_target (text_layer, 0, 0, 0, 0, width, height);
+    }
+  
+  grub_getkey ();
+  
+  grub_video_delete_render_target (text_layer);
+  
+  grub_video_restore ();
+  
+  for (i = 0; i < 16; i++)
+    {
+      grub_printf("color %d: %08x\n", i, palette[i]);
+    }
+  
+  grub_errno = GRUB_ERR_NONE;
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(video_video)
+{
+  my_mod = mod;
+
+  grub_video_adapter_active = 0;
+  grub_video_adapter_list = 0;
+
+  grub_register_command ("videotest",
+                         grub_cmd_videotest,
+                         GRUB_COMMAND_FLAG_BOTH,
+                         "videotest",
+                         "Test video subsystem",
+                         0);
+}
+
+GRUB_MOD_FINI(video_video)
+{
+  grub_unregister_command ("videotest");
+}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]