]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Added first version of the VBE terminal code.
authorchaac <chaac@localhost>
Mon, 15 Aug 2005 21:25:41 +0000 (21:25 +0000)
committerchaac <chaac@localhost>
Mon, 15 Aug 2005 21:25:41 +0000 (21:25 +0000)
ChangeLog
DISTLIST
commands/i386/pc/vbe_list_modes.c [new file with mode: 0644]
commands/i386/pc/vbe_test.c [new file with mode: 0644]
conf/i386-pc.mk
conf/i386-pc.rmk
include/grub/i386/pc/vbe.h
term/i386/pc/vesafb.c [new file with mode: 0644]
video/i386/pc/vbe.c [new file with mode: 0644]

index 32d0db32c3f397ac251bbf19adb01259e4d23ecd..1f66c50dba45930c8903b91f6550f95b4bbddd72 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2005-08-16  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * DISTLIST: Added term/i386/pc/vesafb.c
+       DISTLIST: Added video/i386/pc/vbe.c
+       DISTLIST: Added commands/i386/pc/vbe_list_modes.c.
+       DISTLIST: Added commands/i386/pc/vbe_test.c.
+       * commands/i386/pc/vbe_list_modes.c: New file.
+       * commands/i386/pc/vbe_test.c: Likewise.
+       * term/i386/pc/vesafb.c: Likewise.
+       * video/i386/pc/vbe.c: Likewise.
+       * include/grub/i386/pc/vbe.h (GRUB_VBE_DEFAULT_VIDEO_MODE): Added define.
+       (grub_vbe_probe) Added prototype.
+       (grub_vbe_set_video_mode) Likewise.
+       (grub_vbe_get_video_mode) Likewise.
+       (grub_vbe_get_video_mode_info) Likewise.
+       (grub_vbe_set_pixel_rgb) Likewise.
+       (grub_vbe_set_pixel_index) Likewise.
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added vbe.mod.
+       (pkgdata_MODULES): Added vesafb.mod.
+       (pkgdata_MODULES): Added vbe_list_modes.mod.
+       (pkgdata_MODULES): Added vbe_test.mod.
+       (vbe_mod_SOURCES): Added.
+       (vbe_mod_CFLAGS): Likewise.
+       (vesafb_mod_SOURCES): Likewise.
+       (vesafb_mod_CFLAGS): Likewise.
+       (vbe_list_modes_mod_SOURCES): Likewise.
+       (vbe_list_modes_mod_CFLAGS): Likewise.
+       (vbe_test_mod_SOURCES): Likewise.
+       (vbe_test_mod_CFLAGS): Likewise.
+
 2005-08-14  Yoshinori K. Okuji  <okuji@enbug.org>
 
        * normal/command.c (grub_command_execute): If INTERACTIVE is
index 724d9f3986970edc8ff9ec665a7f42ca199855a1..f92df267d583e2681595dd66b958fb9b3ae9e2b9 100644 (file)
--- a/DISTLIST
+++ b/DISTLIST
@@ -32,6 +32,8 @@ boot/powerpc/ieee1275/cmain.c
 boot/powerpc/ieee1275/crt0.S
 commands/i386/pc/halt.c
 commands/i386/pc/reboot.c
+commands/i386/pc/vbe_list_modes.c
+commands/i386/pc/vbe_test.c
 commands/ieee1275/halt.c
 commands/ieee1275/reboot.c
 commands/ieee1275/suspend.c
@@ -163,6 +165,7 @@ partmap/apple.c
 partmap/pc.c
 partmap/sun.c
 term/i386/pc/console.c
+term/i386/pc/vesafb.c
 term/i386/pc/vga.c
 term/ieee1275/ofconsole.c
 util/i386/pc/biosdisk.c
@@ -180,3 +183,4 @@ util/grub-emu.c
 util/misc.c
 util/resolve.c
 util/unifont2pff.rb
+video/i386/pc/vbe.c
diff --git a/commands/i386/pc/vbe_list_modes.c b/commands/i386/pc/vbe_list_modes.c
new file mode 100644 (file)
index 0000000..d4e07a6
--- /dev/null
@@ -0,0 +1,143 @@
+/* vbe_list_modes.c - command to list compatible VBE video modes.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/machine/init.h>
+#include <grub/machine/vbe.h>
+
+static void *
+real2pm(grub_vbe_farptr_t ptr)
+{
+  return (void *)((((unsigned long)ptr & 0xFFFF0000) >> 12UL) +
+                 ((unsigned long)ptr & 0x0000FFFF));
+}
+
+static grub_err_t
+grub_cmd_vbe_list_modes(struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc __attribute__ ((unused)),
+                       char **args __attribute__ ((unused)))
+{
+  struct grub_vbe_info_block controller_info;
+  struct grub_vbe_mode_info_block mode_info_tmp;
+  grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
+  grub_uint16_t *sptr;
+  grub_uint32_t rc;
+  char *modevar;
+
+  grub_printf ("List of compatible video modes:\n");
+
+  rc = grub_vbe_probe (&controller_info);
+
+  if (rc != GRUB_ERR_NONE)
+    {
+      grub_printf ("VESA BIOS Extension not detected!\n");
+      return rc;
+    }
+
+  sptr = real2pm (controller_info.video_mode_ptr);
+
+  /* Walk thru all video modes listed.  */
+  for (;*sptr != 0xFFFF; sptr++)
+    {
+      int valid_mode = 1;
+
+      rc = grub_vbe_get_video_mode_info (*sptr, &mode_info_tmp);
+      if (rc != GRUB_ERR_NONE) continue;
+
+      if ((mode_info_tmp.mode_attributes & 0x080) == 0)
+       {
+         /* We support only linear frame buffer modes.  */
+         continue;
+       }
+
+      if ((mode_info_tmp.mode_attributes & 0x010) == 0)
+       {
+         /* We allow only graphical modes.  */
+         continue;
+       }
+
+      switch(mode_info_tmp.memory_model)
+       {
+       case 0x04:
+       case 0x06:
+         break;
+
+       default:
+         valid_mode = 0;
+         break;
+       }
+
+      if (valid_mode == 0) continue;
+
+      grub_printf ("0x%03x: %d x %d x %d bpp\n",
+                   *sptr,
+                   mode_info_tmp.x_resolution,
+                   mode_info_tmp.y_resolution,
+                   mode_info_tmp.bits_per_pixel);
+    }
+
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+
+  if (modevar != 0)
+    {
+      unsigned long value = 0;
+
+      if ((grub_strncmp (modevar, "0x", 2) == 0) ||
+         (grub_strncmp (modevar, "0X", 2) == 0))
+       {
+         /* Convert HEX mode number.  */
+         value = grub_strtoul (modevar + 2, 0, 16);
+       }
+      else
+       {
+         /* Convert DEC mode number.  */
+         value = grub_strtoul (modevar, 0, 10);
+       }
+
+      if (value != 0)
+       {
+         use_mode = value;
+       }
+    }
+
+  grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode);
+
+  return 0;
+}
+
+GRUB_MOD_INIT
+{
+  (void)mod;                   /* To stop warning.  */
+  grub_register_command ("vbe_list_modes", grub_cmd_vbe_list_modes, GRUB_COMMAND_FLAG_BOTH,
+                         "vbe_list_modes", "List compatible VESA BIOS extension video modes.", 0);
+}
+
+GRUB_MOD_FINI
+{
+  grub_unregister_command ("vbe_list_modes");
+}
diff --git a/commands/i386/pc/vbe_test.c b/commands/i386/pc/vbe_test.c
new file mode 100644 (file)
index 0000000..b0cbecb
--- /dev/null
@@ -0,0 +1,195 @@
+/* vbe_test.c - command to test VESA BIOS Extension 2.0+ support.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/machine/init.h>
+#include <grub/machine/vbe.h>
+
+static void *
+real2pm(grub_vbe_farptr_t ptr)
+{
+  return (void *)((((unsigned long)ptr & 0xFFFF0000) >> 12UL) +
+                 ((unsigned long)ptr & 0x0000FFFF));
+}
+
+static grub_err_t
+grub_cmd_vbe_test(struct grub_arg_list *state __attribute__ ((unused)),
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  grub_uint32_t rc;
+  grub_uint16_t *sptr;
+  char *modevar;
+  struct grub_vbe_mode_info_block mode_info;
+  struct grub_vbe_info_block controller_info;
+  grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
+  grub_uint32_t old_mode;
+  grub_uint8_t *framebuffer = 0;
+  grub_uint32_t bytes_per_scan_line = 0;
+  unsigned char *ptr;
+  int i;
+
+  grub_printf ("Probing for VESA BIOS Extension ... ");
+
+  /* Check if VESA BIOS exists.  */
+  rc = grub_vbe_probe(&controller_info);
+  if (rc != GRUB_ERR_NONE)
+    {
+      grub_printf ("not found!\n");
+      return rc;
+    }
+  grub_printf ("found!\n");
+
+  /* Dump out controller information.  */
+  grub_printf ("VBE signature = %c%c%c%c\n",
+              controller_info.signature[0],
+              controller_info.signature[1],
+              controller_info.signature[2],
+              controller_info.signature[3]);
+
+  grub_printf ("VBE version = %d.%d\n",
+              controller_info.version >> 8,
+              controller_info.version & 0xFF);
+  grub_printf ("OEM string ptr = %08x\n",
+              controller_info.oem_string_ptr);
+  grub_printf ("Total memory = %d\n",
+              controller_info.total_memory);
+
+  sptr = real2pm(controller_info.video_mode_ptr);
+
+  rc = grub_vbe_get_video_mode(&old_mode);
+  grub_printf ("Get video mode rc = %04x\n", rc);
+
+  if (rc == GRUB_ERR_NONE)
+    {
+      grub_printf ("Old video mode = %04x\n", old_mode);
+    }
+
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+
+  if (modevar != 0)
+    {
+      unsigned long value = 0;
+
+      if ((grub_strncmp (modevar, "0x", 2) == 0) ||
+         (grub_strncmp (modevar, "0X", 2) == 0))
+       {
+         /* Convert HEX mode number.  */
+         value = grub_strtoul (modevar + 2, 0, 16);
+       }
+      else
+       {
+         /* Convert DEC mode number.  */
+         value = grub_strtoul (modevar, 0, 10);
+       }
+
+      if (value != 0)
+       {
+         use_mode = value;
+       }
+    }
+
+  rc = grub_vbe_get_video_mode_info (use_mode, &mode_info);
+
+  /* Dump out details about the mode being tested.  */
+  grub_printf ("mode: 0x%03x\n",
+               use_mode);
+  grub_printf ("width : %d\n",
+               mode_info.x_resolution);
+  grub_printf ("height: %d\n",
+               mode_info.y_resolution);
+  grub_printf ("memory model: %02x\n",
+               mode_info.memory_model);
+  grub_printf ("bytes/scanline: %d\n",
+               mode_info.bytes_per_scan_line);
+  grub_printf ("bytes/scanline (lin): %d\n",
+               mode_info.lin_bytes_per_scan_line);
+  grub_printf ("base address: %08x\n",
+               mode_info.phys_base_addr);
+  grub_printf ("red mask/pos: %d/%d\n",
+               mode_info.red_mask_size,
+               mode_info.red_field_position);
+  grub_printf ("green mask/pos: %d/%d\n",
+               mode_info.green_mask_size,
+               mode_info.green_field_position);
+  grub_printf ("blue mask/pos: %d/%d\n",
+               mode_info.blue_mask_size,
+               mode_info.blue_field_position);
+
+  grub_printf ("Press any key to continue.\n");
+
+  grub_getkey ();
+
+  /* Setup GFX mode.  */
+  rc = grub_vbe_set_video_mode (use_mode, &mode_info);
+
+  /* Determine framebuffer address and how many bytes are in scan line.  */
+  framebuffer = (grub_uint8_t *)mode_info.phys_base_addr;
+  ptr = framebuffer;
+
+  if (controller_info.version >= 0x300)
+    {
+      bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
+    }
+  else
+    {
+      bytes_per_scan_line = mode_info.bytes_per_scan_line;
+    }
+
+  /* Draw some random data to screen.  */
+  for (i = 0; i < 256 * 256; i++)
+    {
+      ptr[i] = i & 0x0F;
+    }
+
+  /* Draw white line to screen.  */
+  for (i = 0; i < 100; i++)
+    {
+      ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F;
+    }
+
+  /* Draw another white line to screen.  */
+  grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line);
+
+  grub_getkey ();
+
+  /* Restore old video mode.  */
+  grub_vbe_set_video_mode (old_mode, 0);
+
+  return 0;
+}
+
+GRUB_MOD_INIT
+{
+  (void)mod;                   /* To stop warning.  */
+  grub_register_command ("vbe_test", grub_cmd_vbe_test, GRUB_COMMAND_FLAG_BOTH,
+                         "vbe_test", "Test VESA BIOS Extension 2.0+ support", 0);
+}
+
+GRUB_MOD_FINI
+{
+  grub_unregister_command ("vbe_test");
+}
index fd41dbb3cd9dc3e4cf70d4fa7e493ff9f6a19e3c..0d65502e45dc5240414574606726b69e7b37a759 100644 (file)
@@ -1141,7 +1141,8 @@ pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod \
        font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod         \
        terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod       \
        apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod       \
-       help.mod default.mod timeout.mod configfile.mod
+       help.mod default.mod timeout.mod configfile.mod vbe.mod         \
+       vesafb.mod vbe_test.mod vbe_list_modes.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -2951,6 +2952,206 @@ fs-configfile.lst: commands/configfile.c genfslist.sh
 
 
 configfile_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vbe.mod.
+vbe_mod_SOURCES = video/i386/pc/vbe.c
+CLEANFILES += vbe.mod mod-vbe.o mod-vbe.c pre-vbe.o vbe_mod-video_i386_pc_vbe.o def-vbe.lst und-vbe.lst
+MOSTLYCLEANFILES += vbe_mod-video_i386_pc_vbe.d
+DEFSYMFILES += def-vbe.lst
+UNDSYMFILES += und-vbe.lst
+
+vbe.mod: pre-vbe.o mod-vbe.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-vbe.o: vbe_mod-video_i386_pc_vbe.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+
+mod-vbe.o: mod-vbe.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -c -o $@ $<
+
+mod-vbe.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vbe' $< > $@ || (rm -f $@; exit 1)
+
+def-vbe.lst: pre-vbe.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vbe/' > $@
+
+und-vbe.lst: pre-vbe.o
+       echo 'vbe' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vbe_mod-video_i386_pc_vbe.o: video/i386/pc/vbe.c
+       $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -c -o $@ $<
+
+vbe_mod-video_i386_pc_vbe.d: video/i386/pc/vbe.c
+       set -e;           $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -M $<           | sed 's,vbe\.o[ :]*,vbe_mod-video_i386_pc_vbe.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include vbe_mod-video_i386_pc_vbe.d
+
+CLEANFILES += cmd-vbe.lst fs-vbe.lst
+COMMANDFILES += cmd-vbe.lst
+FSFILES += fs-vbe.lst
+
+cmd-vbe.lst: video/i386/pc/vbe.c gencmdlist.sh
+       set -e;           $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1)
+
+fs-vbe.lst: video/i386/pc/vbe.c genfslist.sh
+       set -e;           $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1)
+
+
+vbe_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vesafb.mod.
+vesafb_mod_SOURCES = term/i386/pc/vesafb.c
+CLEANFILES += vesafb.mod mod-vesafb.o mod-vesafb.c pre-vesafb.o vesafb_mod-term_i386_pc_vesafb.o def-vesafb.lst und-vesafb.lst
+MOSTLYCLEANFILES += vesafb_mod-term_i386_pc_vesafb.d
+DEFSYMFILES += def-vesafb.lst
+UNDSYMFILES += und-vesafb.lst
+
+vesafb.mod: pre-vesafb.o mod-vesafb.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-vesafb.o: vesafb_mod-term_i386_pc_vesafb.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+
+mod-vesafb.o: mod-vesafb.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(vesafb_mod_CFLAGS) -c -o $@ $<
+
+mod-vesafb.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vesafb' $< > $@ || (rm -f $@; exit 1)
+
+def-vesafb.lst: pre-vesafb.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vesafb/' > $@
+
+und-vesafb.lst: pre-vesafb.o
+       echo 'vesafb' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vesafb_mod-term_i386_pc_vesafb.o: term/i386/pc/vesafb.c
+       $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(vesafb_mod_CFLAGS) -c -o $@ $<
+
+vesafb_mod-term_i386_pc_vesafb.d: term/i386/pc/vesafb.c
+       set -e;           $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(vesafb_mod_CFLAGS) -M $<          | sed 's,vesafb\.o[ :]*,vesafb_mod-term_i386_pc_vesafb.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include vesafb_mod-term_i386_pc_vesafb.d
+
+CLEANFILES += cmd-vesafb.lst fs-vesafb.lst
+COMMANDFILES += cmd-vesafb.lst
+FSFILES += fs-vesafb.lst
+
+cmd-vesafb.lst: term/i386/pc/vesafb.c gencmdlist.sh
+       set -e;           $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(vesafb_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh vesafb > $@ || (rm -f $@; exit 1)
+
+fs-vesafb.lst: term/i386/pc/vesafb.c genfslist.sh
+       set -e;           $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(vesafb_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh vesafb > $@ || (rm -f $@; exit 1)
+
+
+vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vbe_list_modes.mod.
+vbe_list_modes_mod_SOURCES = commands/i386/pc/vbe_list_modes.c
+CLEANFILES += vbe_list_modes.mod mod-vbe_list_modes.o mod-vbe_list_modes.c pre-vbe_list_modes.o vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.o def-vbe_list_modes.lst und-vbe_list_modes.lst
+MOSTLYCLEANFILES += vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.d
+DEFSYMFILES += def-vbe_list_modes.lst
+UNDSYMFILES += und-vbe_list_modes.lst
+
+vbe_list_modes.mod: pre-vbe_list_modes.o mod-vbe_list_modes.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-vbe_list_modes.o: vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+
+mod-vbe_list_modes.o: mod-vbe_list_modes.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(vbe_list_modes_mod_CFLAGS) -c -o $@ $<
+
+mod-vbe_list_modes.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vbe_list_modes' $< > $@ || (rm -f $@; exit 1)
+
+def-vbe_list_modes.lst: pre-vbe_list_modes.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vbe_list_modes/' > $@
+
+und-vbe_list_modes.lst: pre-vbe_list_modes.o
+       echo 'vbe_list_modes' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.o: commands/i386/pc/vbe_list_modes.c
+       $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_list_modes_mod_CFLAGS) -c -o $@ $<
+
+vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.d: commands/i386/pc/vbe_list_modes.c
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_list_modes_mod_CFLAGS) -M $<          | sed 's,vbe_list_modes\.o[ :]*,vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include vbe_list_modes_mod-commands_i386_pc_vbe_list_modes.d
+
+CLEANFILES += cmd-vbe_list_modes.lst fs-vbe_list_modes.lst
+COMMANDFILES += cmd-vbe_list_modes.lst
+FSFILES += fs-vbe_list_modes.lst
+
+cmd-vbe_list_modes.lst: commands/i386/pc/vbe_list_modes.c gencmdlist.sh
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_list_modes_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh vbe_list_modes > $@ || (rm -f $@; exit 1)
+
+fs-vbe_list_modes.lst: commands/i386/pc/vbe_list_modes.c genfslist.sh
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_list_modes_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh vbe_list_modes > $@ || (rm -f $@; exit 1)
+
+
+vbe_list_modes_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vbe_test.mod.
+vbe_test_mod_SOURCES = commands/i386/pc/vbe_test.c
+CLEANFILES += vbe_test.mod mod-vbe_test.o mod-vbe_test.c pre-vbe_test.o vbe_test_mod-commands_i386_pc_vbe_test.o def-vbe_test.lst und-vbe_test.lst
+MOSTLYCLEANFILES += vbe_test_mod-commands_i386_pc_vbe_test.d
+DEFSYMFILES += def-vbe_test.lst
+UNDSYMFILES += und-vbe_test.lst
+
+vbe_test.mod: pre-vbe_test.o mod-vbe_test.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-vbe_test.o: vbe_test_mod-commands_i386_pc_vbe_test.o
+       -rm -f $@
+       $(LD) -r -d -o $@ $^
+
+mod-vbe_test.o: mod-vbe_test.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(vbe_test_mod_CFLAGS) -c -o $@ $<
+
+mod-vbe_test.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vbe_test' $< > $@ || (rm -f $@; exit 1)
+
+def-vbe_test.lst: pre-vbe_test.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vbe_test/' > $@
+
+und-vbe_test.lst: pre-vbe_test.o
+       echo 'vbe_test' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vbe_test_mod-commands_i386_pc_vbe_test.o: commands/i386/pc/vbe_test.c
+       $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_test_mod_CFLAGS) -c -o $@ $<
+
+vbe_test_mod-commands_i386_pc_vbe_test.d: commands/i386/pc/vbe_test.c
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_test_mod_CFLAGS) -M $<        | sed 's,vbe_test\.o[ :]*,vbe_test_mod-commands_i386_pc_vbe_test.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include vbe_test_mod-commands_i386_pc_vbe_test.d
+
+CLEANFILES += cmd-vbe_test.lst fs-vbe_test.lst
+COMMANDFILES += cmd-vbe_test.lst
+FSFILES += fs-vbe_test.lst
+
+cmd-vbe_test.lst: commands/i386/pc/vbe_test.c gencmdlist.sh
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_test_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh vbe_test > $@ || (rm -f $@; exit 1)
+
+fs-vbe_test.lst: commands/i386/pc/vbe_test.c genfslist.sh
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_test_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh vbe_test > $@ || (rm -f $@; exit 1)
+
+
+vbe_test_mod_CFLAGS = $(COMMON_CFLAGS)
 CLEANFILES += moddep.lst command.lst fs.lst
 pkgdata_DATA += moddep.lst command.lst fs.lst
 moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep
index aa5d4f8f61dc372ee104f27405add03f00fbdace..3e93b2c86c556c1cdb6b1220201eaafff08104f7 100644 (file)
@@ -111,7 +111,8 @@ pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod   \
        font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod         \
        terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod       \
        apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod       \
-       help.mod default.mod timeout.mod configfile.mod
+       help.mod default.mod timeout.mod configfile.mod vbe.mod         \
+       vesafb.mod vbe_test.mod vbe_list_modes.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -251,3 +252,19 @@ timeout_mod_CFLAGS = $(COMMON_CFLAGS)
 # For configfile.mod
 configfile_mod_SOURCES = commands/configfile.c
 configfile_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vbe.mod.
+vbe_mod_SOURCES = video/i386/pc/vbe.c
+vbe_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vesafb.mod.
+vesafb_mod_SOURCES = term/i386/pc/vesafb.c
+vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vbe_list_modes.mod.
+vbe_list_modes_mod_SOURCES = commands/i386/pc/vbe_list_modes.c
+vbe_list_modes_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For vbe_test.mod.
+vbe_test_mod_SOURCES = commands/i386/pc/vbe_test.c
+vbe_test_mod_CFLAGS = $(COMMON_CFLAGS)
index 8f7781f329edbdaa3912e9476d2f32522d1da992..bade315bd61283f9dd3213d80f38dc1bc399d4f5 100644 (file)
 
 #include <grub/symbol.h>
 #include <grub/types.h>
+#include <grub/err.h>
+
+/* Default video mode to be used.  */
+#define GRUB_VBE_DEFAULT_VIDEO_MODE     0x101
 
 /* Note:
  
@@ -140,6 +144,8 @@ struct grub_vbe_palette_data
   grub_uint8_t aligment;
 } __attribute__ ((packed));
 
+/* 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);
 
@@ -181,4 +187,13 @@ grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_palette_data) (grub_uint32_t color_co
                                                           grub_uint32_t start_index,
                                                           struct grub_vbe_palette_data *palette_data);
 
+/* Prototypes for helper functions.  */
+
+grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block);
+grub_err_t grub_vbe_set_video_mode (grub_uint32_t mode, struct grub_vbe_mode_info_block *mode_info);
+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 --git a/term/i386/pc/vesafb.c b/term/i386/pc/vesafb.c
new file mode 100644 (file)
index 0000000..f1b72a2
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ *  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/vga.h>
+#include <grub/machine/vbe.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>
+
+#define DEFAULT_CHAR_WIDTH  8
+#define DEFAULT_CHAR_HEIGHT 16
+
+#define DEFAULT_FG_COLOR    0xa
+#define DEFAULT_BG_COLOR    0x0
+
+struct grub_colored_char
+{
+  /* An Unicode codepoint.  */
+  grub_uint32_t code;
+
+  /* Color indexes.  */
+  unsigned char fg_color;
+  unsigned char 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_uint8_t fg_color;
+  grub_uint8_t bg_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 unsigned char *vga_font = 0;
+static grub_uint32_t old_mode = 0;
+
+static struct grub_vbe_mode_info_block mode_info;
+static grub_uint8_t *framebuffer = 0;
+static grub_uint32_t bytes_per_scan_line = 0;
+
+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));
+}
+
+static grub_err_t
+grub_virtual_screen_setup (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 = 0;
+  virtual_screen.offset_y = 0;
+  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;
+  virtual_screen.fg_color = DEFAULT_FG_COLOR;
+  virtual_screen.bg_color = DEFAULT_BG_COLOR;
+
+  /* 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(struct grub_colored_char));
+  if (virtual_screen.text_buffer == 0)
+    {
+      return GRUB_ERR_OUT_OF_MEMORY;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_vesafb_init (void)
+{
+  grub_uint32_t rc;
+  grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
+  struct grub_vbe_info_block controller_info;
+  char *modevar;
+
+  /* Use fonts from VGA bios.  */
+  vga_font = grub_vga_get_font ();
+
+  /* Check if we have VESA BIOS installed.  */
+  rc = grub_vbe_probe (&controller_info);
+  if (rc != GRUB_ERR_NONE)
+    {
+      return rc;
+    }
+
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+
+  if (modevar != 0)
+    {
+      unsigned long value = 0;
+
+      if ((grub_strncmp (modevar, "0x", 2) == 0) ||
+         (grub_strncmp (modevar, "0X", 2) == 0))
+       {
+         /* Convert HEX mode number.  */
+         value = grub_strtoul (modevar + 2, 0, 16);
+       }
+      else
+       {
+         /* Convert DEC mode number.  */
+         value = grub_strtoul (modevar, 0, 10);
+       }
+
+      if (value != 0)
+       {
+         use_mode = value;
+       }
+    }
+
+  /* Store initial video mode.  */
+  rc = grub_vbe_get_video_mode (&old_mode);
+
+  /* Setup desired graphics mode.  */
+  rc = grub_vbe_set_video_mode (use_mode, &mode_info);
+  if (rc != GRUB_ERR_NONE)
+    {
+      return rc;
+    }
+
+  /* Determine framebuffer and bytes per scan line.  */
+  framebuffer = (grub_uint8_t *)mode_info.phys_base_addr;
+
+  if (controller_info.version >= 0x300)
+  {
+      bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
+  }
+  else
+  {
+      bytes_per_scan_line = mode_info.bytes_per_scan_line;
+  }
+
+  /* Create virtual screen.  */
+  rc = grub_virtual_screen_setup (mode_info.x_resolution,
+                                 mode_info.y_resolution);
+  if (rc != GRUB_ERR_NONE)
+    {
+      grub_vbe_set_video_mode (old_mode, 0);
+      return rc;
+    }
+
+  /* Make sure frame buffer is black.  */
+  grub_memset (framebuffer,
+              0,
+              bytes_per_scan_line * mode_info.y_resolution);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_vesafb_fini (void)
+{
+  grub_virtual_screen_free ();
+
+  grub_vbe_set_video_mode (old_mode, 0);
+
+  return GRUB_ERR_NONE;
+}
+
+static int
+grub_virtual_screen_get_glyph (grub_uint32_t code,
+                              unsigned char bitmap[32],
+                              unsigned *width)
+{
+  if (code > 0x7f)
+    {
+      /* Map some unicode characters to the VGA font, if possible.  */
+      switch (code)
+       {
+       case 0x2190:    /* left arrow */
+         code = 0x1b;
+         break;
+       case 0x2191:    /* up arrow */
+         code = 0x18;
+         break;
+       case 0x2192:    /* right arrow */
+         code = 0x1a;
+         break;
+       case 0x2193:    /* down arrow */
+         code = 0x19;
+         break;
+       case 0x2501:    /* horizontal line */
+         code = 0xc4;
+         break;
+       case 0x2503:    /* vertical line */
+         code = 0xb3;
+         break;
+       case 0x250F:    /* upper-left corner */
+         code = 0xda;
+         break;
+       case 0x2513:    /* upper-right corner */
+         code = 0xbf;
+         break;
+       case 0x2517:    /* lower-left corner */
+         code = 0xc0;
+         break;
+       case 0x251B:    /* lower-right corner */
+         code = 0xd9;
+         break;
+
+       default:
+         return grub_font_get_glyph (code, bitmap, width);
+       }
+    }
+
+  if (bitmap)
+    grub_memcpy (bitmap,
+                vga_font + code * virtual_screen.char_height,
+                virtual_screen.char_height);
+  *width = 1;
+  return 1;
+}
+
+static void
+grub_virtual_screen_invalidate_char (struct grub_colored_char *p)
+{
+  p->code = 0xFFFF;
+  
+  if (p->width)
+    {
+      struct grub_colored_char *q;
+
+      for (q = p + 1; q <= p + p->width; q++)
+       {
+         q->code = 0xFFFF;
+         q->width = 0;
+         q->index = 0;
+       }
+    }
+
+  p->width = 0;
+}
+
+static void
+write_char (void)
+{
+  struct grub_colored_char *p;
+  unsigned char bitmap[32];
+  unsigned width;
+
+  p = (virtual_screen.text_buffer +
+       virtual_screen.cursor_x +
+       (virtual_screen.cursor_y * virtual_screen.columns));
+
+  p -= p->index;
+
+  if (! grub_virtual_screen_get_glyph (p->code, bitmap, &width))
+    {
+      grub_virtual_screen_invalidate_char (p);
+      width = 0;
+    }
+
+  unsigned y;
+  unsigned offset;
+
+  for (y = 0, offset = 0;
+       y < virtual_screen.char_height;
+       y++, offset++)
+    {
+      unsigned i;
+
+      for (i = 0;
+          (i < width * virtual_screen.char_width) && (offset < 32);
+          i++)
+       {
+         unsigned char color;
+
+         if (bitmap[offset] & (1<<(8-i)))
+           {
+             color = p->fg_color;
+           }
+         else
+           {
+             color = p->bg_color;
+           }
+
+         grub_vbe_set_pixel_index(i + (virtual_screen.cursor_x * virtual_screen.char_width),
+                                   y + (virtual_screen.cursor_y * virtual_screen.char_height),
+                                   color);
+       }
+    }
+}
+
+static void
+write_cursor (void)
+{
+  grub_uint32_t x;
+  grub_uint32_t y;
+
+  for (y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
+       y < ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 1;
+       y++)
+    {
+      for (x = virtual_screen.cursor_x * virtual_screen.char_width;
+          x < (virtual_screen.cursor_x + 1) * virtual_screen.char_width;
+          x++)
+       {
+         grub_vbe_set_pixel_index(x, y, 10);
+       }
+    }
+}
+
+static void
+scroll_up (void)
+{
+  grub_uint32_t i;
+
+  /* Scroll text buffer with one line to up.  */
+  grub_memmove (virtual_screen.text_buffer,
+               virtual_screen.text_buffer + virtual_screen.columns,
+               sizeof (struct grub_colored_char) *
+               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 = 0;
+      virtual_screen.text_buffer[i].bg_color = 0;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  /* Scroll frambuffer with one line to up.  */
+  grub_memmove (framebuffer,
+               framebuffer + bytes_per_scan_line * virtual_screen.char_height,
+               bytes_per_scan_line *
+               (mode_info.y_resolution - virtual_screen.char_height));
+
+  /* Clear last line in framebuffer.  */
+  grub_memset (framebuffer +
+              (bytes_per_scan_line *
+               (mode_info.y_resolution - virtual_screen.char_height)),
+              0,
+              bytes_per_scan_line * virtual_screen.char_height);
+}
+
+static void
+grub_vesafb_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
+    {
+      unsigned width;
+      struct grub_colored_char *p;
+      
+      grub_virtual_screen_get_glyph (c, 0, &width);
+
+      if (virtual_screen.cursor_x + 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 = width - 1;
+      p->index = 0;
+
+      if (width > 1)
+       {
+         unsigned i;
+
+         for (i = 1; i < width; i++)
+           {
+             p[i].code = ' ';
+             p[i].width = width - 1;
+             p[i].index = i;
+           }
+       }
+         
+      write_char ();
+  
+      virtual_screen.cursor_x += 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_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_vesafb_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 = 0;
+      virtual_screen.text_buffer[i].bg_color = 0;
+      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_vesafb_cls (void)
+{
+  grub_virtual_screen_cls ();
+
+  grub_memset (framebuffer,
+               0, 
+              mode_info.y_resolution * bytes_per_scan_line);
+}
+
+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 = DEFAULT_FG_COLOR;
+      virtual_screen.bg_color = DEFAULT_BG_COLOR;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      virtual_screen.fg_color = DEFAULT_BG_COLOR;
+      virtual_screen.bg_color = DEFAULT_FG_COLOR;
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color __attribute__ ((unused)),
+                             grub_uint8_t highlight_color __attribute__ ((unused)))
+{
+  /* FIXME */
+}
+
+static void
+grub_vesafb_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 struct grub_term grub_vesafb_term =
+  {
+    .name = "vesafb",
+    .init = grub_vesafb_init,
+    .fini = grub_vesafb_fini,
+    .putchar = grub_vesafb_putchar,
+    .checkkey = grub_console_checkkey,
+    .getkey = grub_console_getkey,
+    .getwh = grub_virtual_screen_getwh,
+    .getxy = grub_virtual_screen_getxy,
+    .gotoxy = grub_vesafb_gotoxy,
+    .cls = grub_vesafb_cls,
+    .setcolorstate = grub_virtual_screen_setcolorstate,
+    .setcolor = grub_virtual_screen_setcolor,
+    .setcursor = grub_vesafb_setcursor,
+    .flags = 0,
+    .next = 0
+  };
+
+GRUB_MOD_INIT
+{
+  my_mod = mod;
+  grub_term_register (&grub_vesafb_term);
+}
+
+GRUB_MOD_FINI
+{
+  grub_term_unregister (&grub_vesafb_term);
+}
diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c
new file mode 100644 (file)
index 0000000..317aed9
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ *  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/err.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/vga.h>
+#include <grub/machine/vbe.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>
+
+/* Specify "standard" VGA palette, some video cards may
+   need this and this will also be used when using RGB modes.  */
+static struct grub_vbe_palette_data vga_colors[16] =
+  {
+    // {B, G, R, A}
+    {0x00, 0x00, 0x00, 0x00}, // 0 = black
+    {0xA8, 0x00, 0x00, 0x00}, // 1 = blue
+    {0x00, 0xA8, 0x00, 0x00}, // 2 = green
+    {0xA8, 0xA8, 0x00, 0x00}, // 3 = cyan
+    {0x00, 0x00, 0xA8, 0x00}, // 4 = red
+    {0xA8, 0x00, 0xA8, 0x00}, // 5 = magenta
+    {0x00, 0x54, 0xA8, 0x00}, // 6 = brown
+    {0xA8, 0xA8, 0xA8, 0x00}, // 7 = ligth gray
+
+    {0x54, 0x54, 0x54, 0x00}, // 8 = dark gray
+    {0xFE, 0x54, 0x54, 0x00}, // 9 = bright blue
+    {0x54, 0xFE, 0x54, 0x00}, // 10 = bright green
+    {0xFE, 0xFE, 0x54, 0x00}, // 11 = bright cyan
+    {0x54, 0x54, 0xFE, 0x00}, // 12 = bright red
+    {0xFE, 0x54, 0xFE, 0x00}, // 13 = bright magenta
+    {0x54, 0xFE, 0xFE, 0x00}, // 14 = yellow
+    {0xFE, 0xFE, 0xFE, 0x00}  // 15 = white
+  };
+
+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 grub_uint8_t *framebuffer = 0;
+static grub_uint32_t bytes_per_scan_line = 0;
+
+grub_err_t
+grub_vbe_probe (struct grub_vbe_info_block *info_block)
+{
+  struct grub_vbe_info_block *vbe_ib;
+  grub_uint32_t rc;
+
+  /* Clear caller's controller info block.  */
+  if (info_block != 0)
+    {
+      grub_memset (info_block, 0, sizeof(struct grub_vbe_info_block));
+    }
+
+  /* Do not probe more than one time.  */
+  if (vbe_detected != -1)
+    {
+      if (vbe_detected == 1)
+       {
+          /* Make copy of controller info block to caller.  */
+         if (info_block != 0)
+           {
+             grub_memcpy (info_block,
+                          &controller_info,
+                          sizeof(struct grub_vbe_info_block));
+           }
+         return GRUB_ERR_NONE;
+       }
+      else
+       {
+         return GRUB_ERR_BAD_DEVICE;
+       }
+    }
+
+  /* Clear old copy of controller info block.  */
+  grub_memset (&controller_info, 0, sizeof(struct grub_vbe_info_block));
+
+  /* Mark VESA BIOS extension as undetected.  */
+  vbe_detected = 0;
+
+  /* Use low memory scratch area as temporary storage for VESA BIOS call.  */
+  vbe_ib = (struct grub_vbe_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+  /* Prepare info block.  */
+  grub_memset (vbe_ib, 0, sizeof(struct grub_vbe_info_block));
+
+  vbe_ib->signature[0] = 'V';
+  vbe_ib->signature[1] = 'B';
+  vbe_ib->signature[2] = 'E';
+  vbe_ib->signature[3] = '2';
+
+  /* Try to get controller info block.  */
+  rc = grub_vbe_get_controller_info (vbe_ib);
+  if (rc != 0x004F)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  /* Copy it for later usage.  */
+  grub_memcpy (&controller_info,
+              vbe_ib,
+              sizeof(struct grub_vbe_info_block));
+
+  /* Copy it for caller.  */
+  grub_memcpy (info_block,
+              vbe_ib,
+              sizeof(struct grub_vbe_info_block));
+
+  /* Mark VESA BIOS extension as detected.  */
+  vbe_detected = 1;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_vbe_set_video_mode (grub_uint32_t mode,
+                         struct grub_vbe_mode_info_block *mode_info)
+{
+  grub_uint32_t rc;
+
+  /* If grub_vesafb_probe has not been called or no VBE, abort.  */
+  if (vbe_detected == 0)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  /* Try to get mode info.  */
+  rc = grub_vbe_get_video_mode_info (mode, &active_mode_info);
+  if (rc != GRUB_ERR_NONE)
+    {
+      return rc;
+    }
+
+  /* For all VESA BIOS modes, force linear frame buffer.  */
+  if (mode >= 0x100)
+    {
+      /* We only want linear frame buffer modes.  */
+      mode |= 1 << 14;
+
+      /* Determine frame buffer pixel format.  */
+      switch(active_mode_info.memory_model)
+       {
+       case 0x04:
+         index_color_mode = 1;
+         break;
+
+       case 0x06:
+         index_color_mode = 0;
+         break;
+
+       default:
+         return GRUB_ERR_BAD_DEVICE;
+       }
+    }
+
+  /* Try to set video mode.  */
+  rc = grub_vbe_set_mode (mode, 0);
+  if (rc != 0x004F)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  /* Save information for later usage.  */
+  active_mode = mode;
+
+  if (mode < 0x100)
+    {
+      /* If this is not a VESA mode, guess address.  */
+      framebuffer = (grub_uint8_t *)0xA0000;
+      index_color_mode = 1;
+    }
+  else
+    {
+      framebuffer = (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;
+       }
+      else
+       {
+         bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+       }
+    }
+
+  /* If video mode is in indexed color, setup default VGA palette.  */
+  if (index_color_mode != 0)
+    {
+      rc = grub_vbe_set_palette_data (16, 0, vga_colors);
+      if (rc != 0x004F)
+        {
+          return GRUB_ERR_BAD_DEVICE;
+        }
+    }
+
+  /* Copy mode info for caller.  */
+  if (mode_info != 0)
+    {
+      grub_memcpy (mode_info,
+                   &active_mode_info,
+                   sizeof(struct grub_vbe_mode_info_block));
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_vbe_get_video_mode (grub_uint32_t *mode)
+{
+  grub_uint32_t rc;
+
+  /* If grub_vesafb_probe has not been called or no VBE, abort.  */
+  if (vbe_detected == 0)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  /* Try to query current mode from VESA BIOS.  */
+  rc = grub_vbe_get_mode (mode);
+  if (rc != 0x004F)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_vbe_get_video_mode_info (grub_uint32_t mode,
+                              struct grub_vbe_mode_info_block *mode_info)
+{
+  struct grub_vbe_mode_info_block *mi_tmp = (struct grub_vbe_mode_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  grub_uint32_t rc;
+
+  /* If grub_vesafb_probe has not been called or no VBE, abort.  */
+  if (vbe_detected == 0)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  /* If mode is not VESA mode, skip mode info query.  */
+  if (mode >= 0x100)
+    {
+      /* Try to get mode info from VESA BIOS.  */
+      rc = grub_vbe_get_mode_info (mode, mi_tmp);
+      if (rc != 0x004F)
+       {
+         return GRUB_ERR_BAD_DEVICE;
+       }
+
+      /* Make copy of mode info block.  */
+      grub_memcpy (mode_info,
+                  mi_tmp,
+                  sizeof(struct grub_vbe_mode_info_block));
+    }
+  else
+    {
+      /* Just clear mode info block if it isn't a VESA mode.  */
+      grub_memset (mode_info,
+                  0,
+                  sizeof(struct grub_vbe_mode_info_block));
+    }
+
+  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)
+{
+  grub_uint32_t value;
+
+  if (x >= active_mode_info.x_resolution)
+    return;
+
+  if (y >= active_mode_info.y_resolution)
+    return;
+
+  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;
+    }
+  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;
+
+      value = red << active_mode_info.red_field_position;
+      value |= green << active_mode_info.green_field_position;
+      value |= blue << active_mode_info.blue_field_position;
+    }
+
+  if (active_mode_info.bits_per_pixel == 32)
+    {
+      grub_uint32_t *ptr = (grub_uint32_t *)(framebuffer + y * bytes_per_scan_line + x * 4);
+
+      *ptr = value;
+    }
+  else if (active_mode_info.bits_per_pixel == 24)
+    {
+      grub_uint8_t *ptr = (grub_uint8_t *)(framebuffer + y * bytes_per_scan_line + x * 3);
+      grub_uint8_t *ptr2 = (grub_uint8_t *)&value;
+
+      ptr[0] = ptr2[0];
+      ptr[1] = ptr2[1];
+      ptr[2] = ptr2[2];
+    }
+  else if ((active_mode_info.bits_per_pixel == 16) ||
+          (active_mode_info.bits_per_pixel == 15))
+    {
+      grub_uint16_t *ptr = (grub_uint16_t *)(framebuffer + y * bytes_per_scan_line + x * 2);
+
+      *ptr = (grub_uint16_t)(value & 0xFFFF);
+    }
+}
+
+void
+grub_vbe_set_pixel_index (grub_uint32_t x,
+                          grub_uint32_t y,
+                          grub_uint8_t color)
+{
+  if (x >= active_mode_info.x_resolution)
+    return;
+
+  if (y >= active_mode_info.y_resolution)
+    return;
+
+  if (index_color_mode == 1)
+    {
+      grub_uint8_t *ptr = (grub_uint8_t *)(framebuffer + y * bytes_per_scan_line + x);
+
+      *ptr = color;
+    }
+  else
+    {
+      color &= 0x0F;
+
+      if (color < 16)
+       {
+         grub_vbe_set_pixel_rgb (x,
+                                  y,
+                                  vga_colors[color].red,
+                                  vga_colors[color].green,
+                                  vga_colors[color].blue);
+       }
+      else
+       {
+         grub_vbe_set_pixel_rgb (x,
+                                  y,
+                                  0,
+                                  0,
+                                  0);
+       }
+  }
+}