All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Multiboot video support
@ 2010-01-14 14:55 Vladimir 'φ-coder/phcoder' Serbinenko
  2010-01-15 14:50 ` Vladimir 'phi-coder/phcoder' Serbinenko
  2010-01-20 11:43 ` Michal Suchanek
  0 siblings, 2 replies; 10+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-01-14 14:55 UTC (permalink / raw)
  To: The development of GRUB 2


[-- Attachment #1.1: Type: text/plain, Size: 58 bytes --]


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: mbivid.diff --]
[-- Type: text/x-diff; name="mbivid.diff", Size: 17128 bytes --]

=== added file 'ChangeLog.mbivid'
--- ChangeLog.mbivid	1970-01-01 00:00:00 +0000
+++ ChangeLog.mbivid	2010-01-14 14:44:14 +0000
@@ -0,0 +1,24 @@
+2010-01-14  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Video multiboot support.
+
+	* include/grub/multiboot.h (grub_multiboot_set_accepts_video):
+	New prototype.
+	* include/grub/video.h (grub_video_driver_id): New type.
+	(grub_video_adapter): New member 'id'. All users updated.
+	(grub_video_get_driver_id): New proto.
+	* include/multiboot.h: Resynced with multiboot specification.
+	* include/multiboot2.h: Likewise.
+	* loader/i386/multiboot.c (UNSUPPORTED_FLAGS): Support video flags.
+	(grub_multiboot): Parse MULTIBOOT_VIDEO_MODE fields.
+	* loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): New constant.
+	(HAS_VGA_TEXT): Likewise.
+	(HAS_VBE): Likewise.
+	(accepts_video): New variable.
+	(grub_multiboot_set_accepts_video): New function.
+	(grub_multiboot_get_mbi_size): Account for video structures.
+	(set_video_mode): New function.
+	(fill_vbe_info) [HAS_VBE]: Likewise.
+	(retrieve_video_parameters): Likewise.
+	(grub_multiboot_make_mbi): Fill video fields.
+	* video/video.c (grub_video_get_driver_id): New function.

=== modified file 'include/grub/multiboot.h'
--- include/grub/multiboot.h	2010-01-10 17:58:18 +0000
+++ include/grub/multiboot.h	2010-01-14 14:26:47 +0000
@@ -35,6 +35,8 @@
 void grub_multiboot (int argc, char *argv[]);
 void grub_module (int argc, char *argv[]);
 
+void grub_multiboot_set_accepts_video (int val);
+
 grub_size_t grub_multiboot_get_mbi_size (void);
 grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
 				    grub_off_t buf_off, grub_size_t bufsize);

=== modified file 'include/grub/video.h'
--- include/grub/video.h	2009-08-14 12:41:58 +0000
+++ include/grub/video.h	2010-01-14 14:22:33 +0000
@@ -159,10 +159,19 @@
   grub_uint8_t a; /* Reserved bits value (0-255).  */
 };
 
+typedef enum grub_video_driver_id
+  {
+    GRUB_VIDEO_DRIVER_NONE,
+    GRUB_VIDEO_DRIVER_VBE,
+    GRUB_VIDEO_DRIVER_EFI_UGA,
+    GRUB_VIDEO_DRIVER_EFI_GOP
+  } grub_video_driver_id_t;
+
 struct grub_video_adapter
 {
   /* The video adapter name.  */
   const char *name;
+  grub_video_driver_id_t id;
 
   /* Initialize the video adapter.  */
   grub_err_t (*init) (void);
@@ -310,4 +319,7 @@
 				int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
 							      struct grub_video_mode_info *mode_info));
 
+grub_video_driver_id_t
+grub_video_get_driver_id (void);
+
 #endif /* ! GRUB_VIDEO_HEADER */

=== modified file 'include/multiboot.h'
--- include/multiboot.h	2010-01-07 19:55:16 +0000
+++ include/multiboot.h	2010-01-14 14:22:27 +0000
@@ -85,10 +85,12 @@
 #define MULTIBOOT_INFO_APM_TABLE		0x00000400
 
 /* Is there video information?  */
-#define MULTIBOOT_INFO_VIDEO_INFO		0x00000800
+#define MULTIBOOT_INFO_VBE_INFO		        0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO	        0x00001000
 
 #ifndef ASM_FILE
 
+typedef unsigned char		multiboot_uint8_t;
 typedef unsigned short		multiboot_uint16_t;
 typedef unsigned int		multiboot_uint32_t;
 typedef unsigned long long	multiboot_uint64_t;
@@ -187,9 +189,43 @@
   multiboot_uint16_t vbe_interface_seg;
   multiboot_uint16_t vbe_interface_off;
   multiboot_uint16_t vbe_interface_len;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+  multiboot_uint8_t framebuffer_type;
+  union
+  {
+    struct
+    {
+      multiboot_uint32_t framebuffer_palette_addr;
+      multiboot_uint16_t framebuffer_palette_num_colors;
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
 };
 typedef struct multiboot_info multiboot_info_t;
 
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+
 struct multiboot_mmap_entry
 {
   multiboot_uint32_t size;

=== modified file 'include/multiboot2.h'
--- include/multiboot2.h	2010-01-07 21:05:25 +0000
+++ include/multiboot2.h	2010-01-14 14:22:27 +0000
@@ -85,10 +85,12 @@
 #define MULTIBOOT_INFO_APM_TABLE		0x00000400
 
 /* Is there video information?  */
-#define MULTIBOOT_INFO_VIDEO_INFO		0x00000800
+#define MULTIBOOT_INFO_VBE_INFO		        0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO	        0x00001000
 
 #ifndef ASM_FILE
 
+typedef unsigned char		multiboot_uint8_t;
 typedef unsigned short		multiboot_uint16_t;
 typedef unsigned int		multiboot_uint32_t;
 typedef unsigned long long	multiboot_uint64_t;
@@ -187,9 +189,43 @@
   multiboot_uint16_t vbe_interface_seg;
   multiboot_uint16_t vbe_interface_off;
   multiboot_uint16_t vbe_interface_len;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+  multiboot_uint8_t framebuffer_type;
+  union
+  {
+    struct
+    {
+      multiboot_uint32_t framebuffer_palette_addr;
+      multiboot_uint16_t framebuffer_palette_num_colors;
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
 };
 typedef struct multiboot_info multiboot_info_t;
 
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+
 struct multiboot_mmap_entry
 {
   multiboot_uint32_t size;

=== modified file 'loader/i386/multiboot.c'
--- loader/i386/multiboot.c	2010-01-12 18:47:02 +0000
+++ loader/i386/multiboot.c	2010-01-14 14:22:27 +0000
@@ -20,7 +20,6 @@
 /*
  *  FIXME: The following features from the Multiboot specification still
  *         need to be implemented:
- *  - VBE support
  *  - symbol table
  *  - drives table
  *  - ROM configuration table
@@ -28,13 +27,11 @@
  */
 
 /* The bits in the required part of flags field we don't support.  */
-#define UNSUPPORTED_FLAGS			0x0000fffc
+#define UNSUPPORTED_FLAGS			0x0000fff8
 
 #include <grub/loader.h>
 #include <grub/machine/loader.h>
 #include <grub/multiboot.h>
-#include <grub/machine/init.h>
-#include <grub/machine/memory.h>
 #include <grub/cpu/multiboot.h>
 #include <grub/elf.h>
 #include <grub/aout.h>
@@ -232,6 +229,34 @@
   else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
 
+  if (header->flags & MULTIBOOT_VIDEO_MODE)
+    {
+      switch (header->mode_type)
+	{
+	case 1:
+	  grub_env_set ("gfxpayload", "text");
+	  break;
+
+	case 0:
+	  {
+	    char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")];
+	    if (header->depth && header->width && header->height)
+	      grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width,
+			    header->height, header->depth, header->width,
+			    header->height);
+	    else if (header->width && header->height)
+	      grub_sprintf (buf, "%dx%d,auto", header->width, header->height);
+	    else
+	      grub_sprintf (buf, "auto");
+
+	    grub_env_set ("gfxpayload", buf);
+	    break;
+	  }
+	}
+    }
+
+  grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
+
   grub_multiboot_set_bootdev ();
 
   grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);

=== modified file 'loader/i386/multiboot_mbi.c'
--- loader/i386/multiboot_mbi.c	2010-01-10 17:58:18 +0000
+++ loader/i386/multiboot_mbi.c	2010-01-14 14:29:26 +0000
@@ -29,6 +29,18 @@
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/env.h>
+#include <grub/video.h>
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
+#include <grub/i386/pc/vbe.h>
+#define DEFAULT_VIDEO_MODE "text"
+#define HAS_VGA_TEXT 1
+#define HAS_VBE 1
+#else
+#define DEFAULT_VIDEO_MODE "auto"
+#define HAS_VGA_TEXT 0
+#define HAS_VBE 0
+#endif
 
 struct module
 {
@@ -46,6 +58,13 @@
 static char *cmdline = NULL;
 static grub_uint32_t bootdev;
 static int bootdev_set;
+static int accepts_video;
+
+void
+grub_multiboot_set_accepts_video (int val)
+{
+  accepts_video = val;
+}
 
 /* Return the length of the Multiboot mmap that will be needed to allocate
    our platform's map.  */
@@ -73,7 +92,12 @@
 {
   return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
     + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
-    + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ();
+    + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+#if HAS_VBE
+    + sizeof (struct grub_vbe_info_block)
+    + sizeof (struct grub_vbe_mode_info_block)
+#endif
+    + 256 * sizeof (struct multiboot_color);
 }
 
 /* Fill previously allocated Multiboot mmap.  */
@@ -106,6 +130,160 @@
   grub_mmap_iterate (hook);
 }
 
+static grub_err_t
+set_video_mode (void)
+{
+  grub_err_t err;
+  const char *modevar;
+
+  if (accepts_video || !HAS_VGA_TEXT)
+    {
+      modevar = grub_env_get ("gfxpayload");
+      if (! modevar || *modevar == 0)
+	err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+      else
+	{
+	  char *tmp;
+	  tmp = grub_malloc (grub_strlen (modevar)
+			     + sizeof (DEFAULT_VIDEO_MODE) + 1);
+	  if (! tmp)
+	    return grub_errno;
+	  grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+	  err = grub_video_set_mode (tmp, 0);
+	  grub_free (tmp);
+	}
+    }
+  else
+    err = grub_video_set_mode ("text", 0);
+
+  return err;
+}
+
+#if HAS_VBE
+static grub_err_t
+fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
+	       grub_uint32_t ptrdest)
+{
+  grub_vbe_status_t status;
+  grub_uint32_t vbe_mode;
+  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+    
+  status = grub_vbe_bios_get_controller_info (scratch);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "Can't get controller info.");
+  
+  mbi->vbe_control_info = ptrdest;
+  grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block));
+  ptrorig += sizeof (struct grub_vbe_info_block);
+  ptrdest += sizeof (struct grub_vbe_info_block);
+  
+  status = grub_vbe_bios_get_mode (scratch);
+  vbe_mode = *(grub_uint32_t *) scratch;
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "Can't get VBE mode.");
+  mbi->vbe_mode = vbe_mode;
+
+  status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "Can't get mode info.");
+  mbi->vbe_mode_info = ptrdest;
+  grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_mode_info_block));
+  ptrorig += sizeof (struct grub_vbe_mode_info_block);
+  ptrdest += sizeof (struct grub_vbe_mode_info_block);
+      
+  /* FIXME: retrieve those.  */
+  mbi->vbe_interface_seg = 0;
+  mbi->vbe_interface_off = 0;
+  mbi->vbe_interface_len = 0;
+  
+  mbi->flags |= MULTIBOOT_INFO_VBE_INFO;
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static grub_err_t
+retrieve_video_parameters (struct multiboot_info *mbi,
+			   grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
+{
+  grub_err_t err;
+  struct grub_video_mode_info mode_info;
+  void *framebuffer;
+#if HAS_VBE
+  int vbe_active;
+#endif
+  struct grub_video_palette_data palette[256];
+
+  err = set_video_mode ();
+  if (err)
+    return err;
+
+  grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
+
+#if HAS_VBE
+  {
+    grub_video_driver_id_t driv_id;
+    driv_id = grub_video_get_driver_id ();
+  
+    vbe_active = ((driv_id == GRUB_VIDEO_DRIVER_VBE)
+		  || ((driv_id == GRUB_VIDEO_DRIVER_NONE) && HAS_VGA_TEXT));
+  }
+#endif
+
+  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
+  if (err)
+    return err;
+
+  mbi->framebuffer_addr = (grub_addr_t) framebuffer;
+  mbi->framebuffer_pitch = mode_info.pitch;
+
+  mbi->framebuffer_width = mode_info.width;
+  mbi->framebuffer_height = mode_info.height;
+
+  mbi->framebuffer_bpp = mode_info.bpp;
+      
+  if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
+    {
+      struct multiboot_color *mb_palette;
+      unsigned i;
+      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
+      mbi->framebuffer_palette_addr = ptrdest;
+      mbi->framebuffer_palette_num_colors = mode_info.number_of_colors;
+      if (mbi->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
+	mbi->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
+      mb_palette = (struct multiboot_color *) ptrorig;
+      for (i = 0; i < mbi->framebuffer_palette_num_colors; i++)
+	{
+	  mb_palette[i].red = palette[i].r;
+	  mb_palette[i].green = palette[i].g;
+	  mb_palette[i].blue = palette[i].b;
+	}
+      ptrorig += mbi->framebuffer_palette_num_colors
+	* sizeof (struct multiboot_color);
+      ptrdest += mbi->framebuffer_palette_num_colors
+	* sizeof (struct multiboot_color);
+    }
+  else
+    {
+      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
+      mbi->framebuffer_red_field_position = mode_info.green_field_pos;
+      mbi->framebuffer_red_mask_size = mode_info.green_mask_size;
+      mbi->framebuffer_green_field_position = mode_info.green_field_pos;
+      mbi->framebuffer_green_mask_size = mode_info.green_mask_size;
+      mbi->framebuffer_blue_field_position = mode_info.blue_field_pos;
+      mbi->framebuffer_blue_mask_size = mode_info.blue_mask_size;
+    }
+
+  mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
+
+#if HAS_VBE
+  if (vbe_active)
+    fill_vbe_info (mbi, ptrorig, ptrdest);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
 grub_err_t
 grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
 			 grub_size_t bufsize)
@@ -117,6 +295,7 @@
   unsigned i;
   struct module *cur;
   grub_size_t mmap_size;
+  grub_err_t err;
 
   if (bufsize < grub_multiboot_get_mbi_size ())
     return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
@@ -182,6 +361,19 @@
       mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
     }
 
+  err = retrieve_video_parameters (mbi, ptrorig, ptrdest);
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+    }
+#if HAS_VBE
+  ptrorig += sizeof (struct grub_vbe_info_block);
+  ptrdest += sizeof (struct grub_vbe_info_block);
+  ptrorig += sizeof (struct grub_vbe_mode_info_block);
+  ptrdest += sizeof (struct grub_vbe_mode_info_block);
+#endif
+
   return GRUB_ERR_NONE;
 }
 

=== modified file 'video/efi_gop.c'
--- video/efi_gop.c	2009-12-24 22:53:05 +0000
+++ video/efi_gop.c	2010-01-14 14:22:33 +0000
@@ -353,6 +353,7 @@
 static struct grub_video_adapter grub_video_gop_adapter =
   {
     .name = "EFI GOP driver",
+    .id = GRUB_VIDEO_DRIVER_EFI_GOP,
 
     .init = grub_video_gop_init,
     .fini = grub_video_gop_fini,

=== modified file 'video/efi_uga.c'
--- video/efi_uga.c	2009-12-24 22:53:05 +0000
+++ video/efi_uga.c	2010-01-14 14:22:33 +0000
@@ -300,6 +300,7 @@
 static struct grub_video_adapter grub_video_uga_adapter =
   {
     .name = "EFI UGA driver",
+    .id = GRUB_VIDEO_DRIVER_EFI_UGA,
 
     .init = grub_video_uga_init,
     .fini = grub_video_uga_fini,

=== modified file 'video/i386/pc/vbe.c'
--- video/i386/pc/vbe.c	2009-12-24 22:53:05 +0000
+++ video/i386/pc/vbe.c	2010-01-14 14:22:33 +0000
@@ -557,6 +557,7 @@
 static struct grub_video_adapter grub_video_vbe_adapter =
   {
     .name = "VESA BIOS Extension Video Driver",
+    .id = GRUB_VIDEO_DRIVER_VBE,
 
     .init = grub_video_vbe_init,
     .fini = grub_video_vbe_fini,

=== modified file 'video/video.c'
--- video/video.c	2009-12-24 22:53:05 +0000
+++ video/video.c	2010-01-14 14:22:33 +0000
@@ -93,6 +93,14 @@
   return grub_video_adapter_active->get_info (mode_info);
 }
 
+grub_video_driver_id_t
+grub_video_get_driver_id (void)
+{
+  if (! grub_video_adapter_active)
+    return GRUB_VIDEO_DRIVER_NONE;
+  return grub_video_adapter_active->id;
+}
+
 /* Get information about active video mode.  */
 grub_err_t
 grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-14 14:55 [PATCH] Multiboot video support Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-01-15 14:50 ` Vladimir 'phi-coder/phcoder' Serbinenko
  2010-01-15 15:44   ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-01-20 11:43 ` Michal Suchanek
  1 sibling, 1 reply; 10+ messages in thread
From: Vladimir 'phi-coder/phcoder' Serbinenko @ 2010-01-15 14:50 UTC (permalink / raw)
  To: The development of GRUB 2


[-- Attachment #1.1: Type: text/plain, Size: 84 bytes --]

Added EGA text support


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: mbivid.diff --]
[-- Type: text/x-diff; name="mbivid.diff", Size: 18478 bytes --]

=== added file 'ChangeLog.mbivid'
--- ChangeLog.mbivid	1970-01-01 00:00:00 +0000
+++ ChangeLog.mbivid	2010-01-14 14:44:14 +0000
@@ -0,0 +1,24 @@
+2010-01-14  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Video multiboot support.
+
+	* include/grub/multiboot.h (grub_multiboot_set_accepts_video):
+	New prototype.
+	* include/grub/video.h (grub_video_driver_id): New type.
+	(grub_video_adapter): New member 'id'. All users updated.
+	(grub_video_get_driver_id): New proto.
+	* include/multiboot.h: Resynced with multiboot specification.
+	* include/multiboot2.h: Likewise.
+	* loader/i386/multiboot.c (UNSUPPORTED_FLAGS): Support video flags.
+	(grub_multiboot): Parse MULTIBOOT_VIDEO_MODE fields.
+	* loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): New constant.
+	(HAS_VGA_TEXT): Likewise.
+	(HAS_VBE): Likewise.
+	(accepts_video): New variable.
+	(grub_multiboot_set_accepts_video): New function.
+	(grub_multiboot_get_mbi_size): Account for video structures.
+	(set_video_mode): New function.
+	(fill_vbe_info) [HAS_VBE]: Likewise.
+	(retrieve_video_parameters): Likewise.
+	(grub_multiboot_make_mbi): Fill video fields.
+	* video/video.c (grub_video_get_driver_id): New function.

=== modified file 'include/grub/multiboot.h'
--- include/grub/multiboot.h	2010-01-10 17:58:18 +0000
+++ include/grub/multiboot.h	2010-01-14 14:26:47 +0000
@@ -35,6 +35,8 @@
 void grub_multiboot (int argc, char *argv[]);
 void grub_module (int argc, char *argv[]);
 
+void grub_multiboot_set_accepts_video (int val);
+
 grub_size_t grub_multiboot_get_mbi_size (void);
 grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
 				    grub_off_t buf_off, grub_size_t bufsize);

=== modified file 'include/grub/video.h'
--- include/grub/video.h	2009-08-14 12:41:58 +0000
+++ include/grub/video.h	2010-01-14 14:22:33 +0000
@@ -159,10 +159,19 @@
   grub_uint8_t a; /* Reserved bits value (0-255).  */
 };
 
+typedef enum grub_video_driver_id
+  {
+    GRUB_VIDEO_DRIVER_NONE,
+    GRUB_VIDEO_DRIVER_VBE,
+    GRUB_VIDEO_DRIVER_EFI_UGA,
+    GRUB_VIDEO_DRIVER_EFI_GOP
+  } grub_video_driver_id_t;
+
 struct grub_video_adapter
 {
   /* The video adapter name.  */
   const char *name;
+  grub_video_driver_id_t id;
 
   /* Initialize the video adapter.  */
   grub_err_t (*init) (void);
@@ -310,4 +319,7 @@
 				int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
 							      struct grub_video_mode_info *mode_info));
 
+grub_video_driver_id_t
+grub_video_get_driver_id (void);
+
 #endif /* ! GRUB_VIDEO_HEADER */

=== modified file 'include/multiboot.h'
--- include/multiboot.h	2010-01-07 19:55:16 +0000
+++ include/multiboot.h	2010-01-15 12:54:32 +0000
@@ -85,10 +85,12 @@
 #define MULTIBOOT_INFO_APM_TABLE		0x00000400
 
 /* Is there video information?  */
-#define MULTIBOOT_INFO_VIDEO_INFO		0x00000800
+#define MULTIBOOT_INFO_VBE_INFO		        0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO	        0x00001000
 
 #ifndef ASM_FILE
 
+typedef unsigned char		multiboot_uint8_t;
 typedef unsigned short		multiboot_uint16_t;
 typedef unsigned int		multiboot_uint32_t;
 typedef unsigned long long	multiboot_uint64_t;
@@ -187,9 +189,43 @@
   multiboot_uint16_t vbe_interface_seg;
   multiboot_uint16_t vbe_interface_off;
   multiboot_uint16_t vbe_interface_len;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT	2
+  multiboot_uint8_t framebuffer_type;
+  union
+  {
+    struct
+    {
+      multiboot_uint32_t framebuffer_palette_addr;
+      multiboot_uint16_t framebuffer_palette_num_colors;
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
 };
 typedef struct multiboot_info multiboot_info_t;
 
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
 struct multiboot_mmap_entry
 {
   multiboot_uint32_t size;

=== modified file 'include/multiboot2.h'
--- include/multiboot2.h	2010-01-07 21:05:25 +0000
+++ include/multiboot2.h	2010-01-15 12:54:48 +0000
@@ -85,10 +85,12 @@
 #define MULTIBOOT_INFO_APM_TABLE		0x00000400
 
 /* Is there video information?  */
-#define MULTIBOOT_INFO_VIDEO_INFO		0x00000800
+#define MULTIBOOT_INFO_VBE_INFO		        0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO	        0x00001000
 
 #ifndef ASM_FILE
 
+typedef unsigned char		multiboot_uint8_t;
 typedef unsigned short		multiboot_uint16_t;
 typedef unsigned int		multiboot_uint32_t;
 typedef unsigned long long	multiboot_uint64_t;
@@ -187,9 +189,43 @@
   multiboot_uint16_t vbe_interface_seg;
   multiboot_uint16_t vbe_interface_off;
   multiboot_uint16_t vbe_interface_len;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT	2
+  multiboot_uint8_t framebuffer_type;
+  union
+  {
+    struct
+    {
+      multiboot_uint32_t framebuffer_palette_addr;
+      multiboot_uint16_t framebuffer_palette_num_colors;
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
 };
 typedef struct multiboot_info multiboot_info_t;
 
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
 struct multiboot_mmap_entry
 {
   multiboot_uint32_t size;

=== modified file 'loader/i386/multiboot.c'
--- loader/i386/multiboot.c	2010-01-14 21:08:31 +0000
+++ loader/i386/multiboot.c	2010-01-15 14:49:11 +0000
@@ -20,7 +20,6 @@
 /*
  *  FIXME: The following features from the Multiboot specification still
  *         need to be implemented:
- *  - VBE support
  *  - symbol table
  *  - drives table
  *  - ROM configuration table
@@ -28,13 +27,11 @@
  */
 
 /* The bits in the required part of flags field we don't support.  */
-#define UNSUPPORTED_FLAGS			0x0000fffc
+#define UNSUPPORTED_FLAGS			0x0000fff8
 
 #include <grub/loader.h>
 #include <grub/machine/loader.h>
 #include <grub/multiboot.h>
-#include <grub/machine/init.h>
-#include <grub/machine/memory.h>
 #include <grub/cpu/multiboot.h>
 #include <grub/elf.h>
 #include <grub/aout.h>
@@ -90,8 +87,6 @@
   if (err)
     return err;
 
-  grub_video_set_mode ("text", NULL);
-
   grub_relocator32_boot (grub_multiboot_payload_orig,
 			 grub_multiboot_payload_dest,
 			 state);
@@ -235,6 +230,34 @@
   else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
 
+  if (header->flags & MULTIBOOT_VIDEO_MODE)
+    {
+      switch (header->mode_type)
+	{
+	case 1:
+	  grub_env_set ("gfxpayload", "text");
+	  break;
+
+	case 0:
+	  {
+	    char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")];
+	    if (header->depth && header->width && header->height)
+	      grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width,
+			    header->height, header->depth, header->width,
+			    header->height);
+	    else if (header->width && header->height)
+	      grub_sprintf (buf, "%dx%d,auto", header->width, header->height);
+	    else
+	      grub_sprintf (buf, "auto");
+
+	    grub_env_set ("gfxpayload", buf);
+	    break;
+	  }
+	}
+    }
+
+  grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
+
   grub_multiboot_set_bootdev ();
 
   grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);

=== modified file 'loader/i386/multiboot_mbi.c'
--- loader/i386/multiboot_mbi.c	2010-01-10 17:58:18 +0000
+++ loader/i386/multiboot_mbi.c	2010-01-15 14:45:03 +0000
@@ -29,6 +29,18 @@
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/env.h>
+#include <grub/video.h>
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
+#include <grub/i386/pc/vbe.h>
+#define DEFAULT_VIDEO_MODE "text"
+#define HAS_VGA_TEXT 1
+#define HAS_VBE 1
+#else
+#define DEFAULT_VIDEO_MODE "auto"
+#define HAS_VGA_TEXT 0
+#define HAS_VBE 0
+#endif
 
 struct module
 {
@@ -46,6 +58,13 @@
 static char *cmdline = NULL;
 static grub_uint32_t bootdev;
 static int bootdev_set;
+static int accepts_video;
+
+void
+grub_multiboot_set_accepts_video (int val)
+{
+  accepts_video = val;
+}
 
 /* Return the length of the Multiboot mmap that will be needed to allocate
    our platform's map.  */
@@ -73,7 +92,12 @@
 {
   return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
     + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
-    + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ();
+    + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+#if HAS_VBE
+    + sizeof (struct grub_vbe_info_block)
+    + sizeof (struct grub_vbe_mode_info_block)
+#endif
+    + 256 * sizeof (struct multiboot_color);
 }
 
 /* Fill previously allocated Multiboot mmap.  */
@@ -106,6 +130,189 @@
   grub_mmap_iterate (hook);
 }
 
+static grub_err_t
+set_video_mode (void)
+{
+  grub_err_t err;
+  const char *modevar;
+
+  if (accepts_video || !HAS_VGA_TEXT)
+    {
+      modevar = grub_env_get ("gfxpayload");
+      if (! modevar || *modevar == 0)
+	err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+      else
+	{
+	  char *tmp;
+	  tmp = grub_malloc (grub_strlen (modevar)
+			     + sizeof (DEFAULT_VIDEO_MODE) + 1);
+	  if (! tmp)
+	    return grub_errno;
+	  grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+	  err = grub_video_set_mode (tmp, 0);
+	  grub_free (tmp);
+	}
+    }
+  else
+    err = grub_video_set_mode ("text", 0);
+
+  return err;
+}
+
+#if HAS_VBE
+static grub_err_t
+fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
+	       grub_uint32_t ptrdest, int fill_generic)
+{
+  grub_vbe_status_t status;
+  grub_uint32_t vbe_mode;
+  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  struct grub_vbe_mode_info_block *mode_info;
+    
+  status = grub_vbe_bios_get_controller_info (scratch);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "Can't get controller info.");
+  
+  mbi->vbe_control_info = ptrdest;
+  grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block));
+  ptrorig += sizeof (struct grub_vbe_info_block);
+  ptrdest += sizeof (struct grub_vbe_info_block);
+  
+  status = grub_vbe_bios_get_mode (scratch);
+  vbe_mode = *(grub_uint32_t *) scratch;
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "can't get VBE mode");
+  mbi->vbe_mode = vbe_mode;
+
+  mode_info = (struct grub_vbe_mode_info_block *) ptrorig;
+  mbi->vbe_mode_info = ptrdest;
+  /* get_mode_info isn't available for mode 3.  */
+  if (vbe_mode == 3)
+    {
+      grub_memset (mode_info, 0, sizeof (struct grub_vbe_mode_info_block));
+      mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
+      mode_info->x_resolution = 80;
+      mode_info->y_resolution = 25;
+    }
+  else
+    {
+      status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
+      if (status != GRUB_VBE_STATUS_OK)
+	return grub_error (GRUB_ERR_IO, "can't get mode info");
+      grub_memcpy (mode_info, scratch,
+		   sizeof (struct grub_vbe_mode_info_block));
+    }
+  ptrorig += sizeof (struct grub_vbe_mode_info_block);
+  ptrdest += sizeof (struct grub_vbe_mode_info_block);
+      
+  /* FIXME: retrieve those.  */
+  mbi->vbe_interface_seg = 0;
+  mbi->vbe_interface_off = 0;
+  mbi->vbe_interface_len = 0;
+  
+  mbi->flags |= MULTIBOOT_INFO_VBE_INFO;
+
+  if (fill_generic && mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
+    {
+      mbi->framebuffer_addr = 0xb8000;
+
+      mbi->framebuffer_pitch = 2 * mode_info->x_resolution;	
+      mbi->framebuffer_width = mode_info->x_resolution;
+      mbi->framebuffer_height = mode_info->y_resolution;
+
+      mbi->framebuffer_bpp = 16;
+
+      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
+
+      mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
+    }
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static grub_err_t
+retrieve_video_parameters (struct multiboot_info *mbi,
+			   grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
+{
+  grub_err_t err;
+  struct grub_video_mode_info mode_info;
+  void *framebuffer;
+  grub_video_driver_id_t driv_id;
+  struct grub_video_palette_data palette[256];
+
+  err = set_video_mode ();
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+    }
+
+  grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
+
+  driv_id = grub_video_get_driver_id ();
+#if HAS_VGA_TEXT
+  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
+    return fill_vbe_info (mbi, ptrorig, ptrdest, 1);
+#else
+  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
+    return GRUB_ERR_NONE;
+#endif
+
+  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
+  if (err)
+    return err;
+
+  mbi->framebuffer_addr = (grub_addr_t) framebuffer;
+  mbi->framebuffer_pitch = mode_info.pitch;
+
+  mbi->framebuffer_width = mode_info.width;
+  mbi->framebuffer_height = mode_info.height;
+
+  mbi->framebuffer_bpp = mode_info.bpp;
+      
+  if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
+    {
+      struct multiboot_color *mb_palette;
+      unsigned i;
+      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
+      mbi->framebuffer_palette_addr = ptrdest;
+      mbi->framebuffer_palette_num_colors = mode_info.number_of_colors;
+      if (mbi->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
+	mbi->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
+      mb_palette = (struct multiboot_color *) ptrorig;
+      for (i = 0; i < mbi->framebuffer_palette_num_colors; i++)
+	{
+	  mb_palette[i].red = palette[i].r;
+	  mb_palette[i].green = palette[i].g;
+	  mb_palette[i].blue = palette[i].b;
+	}
+      ptrorig += mbi->framebuffer_palette_num_colors
+	* sizeof (struct multiboot_color);
+      ptrdest += mbi->framebuffer_palette_num_colors
+	* sizeof (struct multiboot_color);
+    }
+  else
+    {
+      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
+      mbi->framebuffer_red_field_position = mode_info.green_field_pos;
+      mbi->framebuffer_red_mask_size = mode_info.green_mask_size;
+      mbi->framebuffer_green_field_position = mode_info.green_field_pos;
+      mbi->framebuffer_green_mask_size = mode_info.green_mask_size;
+      mbi->framebuffer_blue_field_position = mode_info.blue_field_pos;
+      mbi->framebuffer_blue_mask_size = mode_info.blue_mask_size;
+    }
+
+  mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
+
+#if HAS_VBE
+  if (driv_id == GRUB_VIDEO_DRIVER_VBE)
+    return fill_vbe_info (mbi, ptrorig, ptrdest, 0);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
 grub_err_t
 grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
 			 grub_size_t bufsize)
@@ -117,6 +324,7 @@
   unsigned i;
   struct module *cur;
   grub_size_t mmap_size;
+  grub_err_t err;
 
   if (bufsize < grub_multiboot_get_mbi_size ())
     return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
@@ -182,6 +390,19 @@
       mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
     }
 
+  err = retrieve_video_parameters (mbi, ptrorig, ptrdest);
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+    }
+#if HAS_VBE
+  ptrorig += sizeof (struct grub_vbe_info_block);
+  ptrdest += sizeof (struct grub_vbe_info_block);
+  ptrorig += sizeof (struct grub_vbe_mode_info_block);
+  ptrdest += sizeof (struct grub_vbe_mode_info_block);
+#endif
+
   return GRUB_ERR_NONE;
 }
 

=== modified file 'video/efi_gop.c'
--- video/efi_gop.c	2009-12-24 22:53:05 +0000
+++ video/efi_gop.c	2010-01-14 14:22:33 +0000
@@ -353,6 +353,7 @@
 static struct grub_video_adapter grub_video_gop_adapter =
   {
     .name = "EFI GOP driver",
+    .id = GRUB_VIDEO_DRIVER_EFI_GOP,
 
     .init = grub_video_gop_init,
     .fini = grub_video_gop_fini,

=== modified file 'video/efi_uga.c'
--- video/efi_uga.c	2009-12-24 22:53:05 +0000
+++ video/efi_uga.c	2010-01-14 14:22:33 +0000
@@ -300,6 +300,7 @@
 static struct grub_video_adapter grub_video_uga_adapter =
   {
     .name = "EFI UGA driver",
+    .id = GRUB_VIDEO_DRIVER_EFI_UGA,
 
     .init = grub_video_uga_init,
     .fini = grub_video_uga_fini,

=== modified file 'video/i386/pc/vbe.c'
--- video/i386/pc/vbe.c	2009-12-24 22:53:05 +0000
+++ video/i386/pc/vbe.c	2010-01-14 14:22:33 +0000
@@ -557,6 +557,7 @@
 static struct grub_video_adapter grub_video_vbe_adapter =
   {
     .name = "VESA BIOS Extension Video Driver",
+    .id = GRUB_VIDEO_DRIVER_VBE,
 
     .init = grub_video_vbe_init,
     .fini = grub_video_vbe_fini,

=== modified file 'video/video.c'
--- video/video.c	2009-12-24 22:53:05 +0000
+++ video/video.c	2010-01-14 14:22:33 +0000
@@ -93,6 +93,14 @@
   return grub_video_adapter_active->get_info (mode_info);
 }
 
+grub_video_driver_id_t
+grub_video_get_driver_id (void)
+{
+  if (! grub_video_adapter_active)
+    return GRUB_VIDEO_DRIVER_NONE;
+  return grub_video_adapter_active->id;
+}
+
 /* Get information about active video mode.  */
 grub_err_t
 grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-15 14:50 ` Vladimir 'phi-coder/phcoder' Serbinenko
@ 2010-01-15 15:44   ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-01-19 22:41     ` Robert Millan
  0 siblings, 1 reply; 10+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-01-15 15:44 UTC (permalink / raw)
  To: The development of GRUB 2


[-- Attachment #1.1: Type: text/plain, Size: 208 bytes --]

Vladimir 'phi-coder/phcoder' Serbinenko wrote:
> Added EGA text support
>   
Non-VBE parts reviewed and comitted. Resending VBE parts.
>
>   


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: mbivid.diff --]
[-- Type: text/x-diff; name="mbivid.diff", Size: 5400 bytes --]

=== added file 'ChangeLog.mbivid'
--- ChangeLog.mbivid	1970-01-01 00:00:00 +0000
+++ ChangeLog.mbivid	2010-01-15 15:35:51 +0000
@@ -0,0 +1,9 @@
+2010-01-14  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	VBE multiboot support.
+
+	* loader/i386/multiboot_mbi.c (HAS_VBE): New constant.
+	(grub_multiboot_get_mbi_size) [HAS_VBE]: Account for VBE structures.
+	(grub_multiboot_make_mbi) [HAS_VBE]: Likewise.
+	(fill_vbe_info) [HAS_VBE]: New function.
+	(retrieve_video_parameters) [HAS_VBE]: Call fill_vbe_info.

=== modified file 'loader/i386/multiboot.c'
--- loader/i386/multiboot.c	2010-01-15 15:30:57 +0000
+++ loader/i386/multiboot.c	2010-01-15 15:31:45 +0000
@@ -20,7 +20,6 @@
 /*
  *  FIXME: The following features from the Multiboot specification still
  *         need to be implemented:
- *  - VBE support
  *  - symbol table
  *  - drives table
  *  - ROM configuration table

=== modified file 'loader/i386/multiboot_mbi.c'
--- loader/i386/multiboot_mbi.c	2010-01-15 15:30:57 +0000
+++ loader/i386/multiboot_mbi.c	2010-01-15 15:32:50 +0000
@@ -35,9 +35,11 @@
 #include <grub/i386/pc/vbe.h>
 #define DEFAULT_VIDEO_MODE "text"
 #define HAS_VGA_TEXT 1
+#define HAS_VBE 1
 #else
 #define DEFAULT_VIDEO_MODE "auto"
 #define HAS_VGA_TEXT 0
+#define HAS_VBE 0
 #endif
 
 struct module
@@ -91,6 +93,10 @@
   return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
     + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
     + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+#if HAS_VBE
+    + sizeof (struct grub_vbe_info_block)
+    + sizeof (struct grub_vbe_mode_info_block)
+#endif
     + 256 * sizeof (struct multiboot_color);
 }
 
@@ -153,6 +159,78 @@
   return err;
 }
 
+#if HAS_VBE
+static grub_err_t
+fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
+	       grub_uint32_t ptrdest, int fill_generic)
+{
+  grub_vbe_status_t status;
+  grub_uint32_t vbe_mode;
+  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  struct grub_vbe_mode_info_block *mode_info;
+    
+  status = grub_vbe_bios_get_controller_info (scratch);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "Can't get controller info.");
+  
+  mbi->vbe_control_info = ptrdest;
+  grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block));
+  ptrorig += sizeof (struct grub_vbe_info_block);
+  ptrdest += sizeof (struct grub_vbe_info_block);
+  
+  status = grub_vbe_bios_get_mode (scratch);
+  vbe_mode = *(grub_uint32_t *) scratch;
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "can't get VBE mode");
+  mbi->vbe_mode = vbe_mode;
+
+  mode_info = (struct grub_vbe_mode_info_block *) ptrorig;
+  mbi->vbe_mode_info = ptrdest;
+  /* get_mode_info isn't available for mode 3.  */
+  if (vbe_mode == 3)
+    {
+      grub_memset (mode_info, 0, sizeof (struct grub_vbe_mode_info_block));
+      mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
+      mode_info->x_resolution = 80;
+      mode_info->y_resolution = 25;
+    }
+  else
+    {
+      status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
+      if (status != GRUB_VBE_STATUS_OK)
+	return grub_error (GRUB_ERR_IO, "can't get mode info");
+      grub_memcpy (mode_info, scratch,
+		   sizeof (struct grub_vbe_mode_info_block));
+    }
+  ptrorig += sizeof (struct grub_vbe_mode_info_block);
+  ptrdest += sizeof (struct grub_vbe_mode_info_block);
+      
+  /* FIXME: retrieve those.  */
+  mbi->vbe_interface_seg = 0;
+  mbi->vbe_interface_off = 0;
+  mbi->vbe_interface_len = 0;
+  
+  mbi->flags |= MULTIBOOT_INFO_VBE_INFO;
+
+  if (fill_generic && mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
+    {
+      mbi->framebuffer_addr = 0xb8000;
+
+      mbi->framebuffer_pitch = 2 * mode_info->x_resolution;	
+      mbi->framebuffer_width = mode_info->x_resolution;
+      mbi->framebuffer_height = mode_info->y_resolution;
+
+      mbi->framebuffer_bpp = 16;
+
+      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
+
+      mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
+    }
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
 static grub_err_t
 retrieve_video_parameters (struct multiboot_info *mbi,
 			   grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
@@ -173,8 +251,13 @@
   grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
 
   driv_id = grub_video_get_driver_id ();
+#if HAS_VGA_TEXT
+  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
+    return fill_vbe_info (mbi, ptrorig, ptrdest, 1);
+#else
   if (driv_id == GRUB_VIDEO_DRIVER_NONE)
     return GRUB_ERR_NONE;
+#endif
 
   err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
   if (err)
@@ -222,6 +305,11 @@
 
   mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
 
+#if HAS_VBE
+  if (driv_id == GRUB_VIDEO_DRIVER_VBE)
+    return fill_vbe_info (mbi, ptrorig, ptrdest, 0);
+#endif
+
   return GRUB_ERR_NONE;
 }
 
@@ -308,6 +396,12 @@
       grub_print_error ();
       grub_errno = GRUB_ERR_NONE;
     }
+#if HAS_VBE
+  ptrorig += sizeof (struct grub_vbe_info_block);
+  ptrdest += sizeof (struct grub_vbe_info_block);
+  ptrorig += sizeof (struct grub_vbe_mode_info_block);
+  ptrdest += sizeof (struct grub_vbe_mode_info_block);
+#endif
 
   return GRUB_ERR_NONE;
 }


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-15 15:44   ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-01-19 22:41     ` Robert Millan
  0 siblings, 0 replies; 10+ messages in thread
From: Robert Millan @ 2010-01-19 22:41 UTC (permalink / raw)
  To: The development of GNU GRUB

On Fri, Jan 15, 2010 at 04:44:50PM +0100, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> Vladimir 'phi-coder/phcoder' Serbinenko wrote:
> > Added EGA text support
> >   
> Non-VBE parts reviewed and comitted. Resending VBE parts.

This is vetoed (in both trunk and experimental) unless someone provides a
very good reason to provide it.

-- 
Robert Millan

  "Be the change you want to see in the world" -- Gandhi



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-14 14:55 [PATCH] Multiboot video support Vladimir 'φ-coder/phcoder' Serbinenko
  2010-01-15 14:50 ` Vladimir 'phi-coder/phcoder' Serbinenko
@ 2010-01-20 11:43 ` Michal Suchanek
  2010-01-24 19:02   ` Robert Millan
  1 sibling, 1 reply; 10+ messages in thread
From: Michal Suchanek @ 2010-01-20 11:43 UTC (permalink / raw)
  To: The development of GNU GRUB

Shouldn't the structure also include the framebuffer orientation?

If framebuffer transform support is included in grub it would be good
to pass the orientation the user specified for grub graphics output to
the OS so that the OS console output is displayed the same way
automatically.

Thanks

Michal



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-20 11:43 ` Michal Suchanek
@ 2010-01-24 19:02   ` Robert Millan
  2010-01-24 21:05     ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 10+ messages in thread
From: Robert Millan @ 2010-01-24 19:02 UTC (permalink / raw)
  To: The development of GNU GRUB

On Wed, Jan 20, 2010 at 12:43:38PM +0100, Michal Suchanek wrote:
> Shouldn't the structure also include the framebuffer orientation?
> 
> If framebuffer transform support is included in grub it would be good
> to pass the orientation the user specified for grub graphics output to
> the OS so that the OS console output is displayed the same way
> automatically.

Makes sense.  Can you draft a proposal?

-- 
Robert Millan

  "Be the change you want to see in the world" -- Gandhi



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-24 19:02   ` Robert Millan
@ 2010-01-24 21:05     ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-01-24 23:29       ` Michal Suchanek
  0 siblings, 1 reply; 10+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-01-24 21:05 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: text/plain, Size: 836 bytes --]

Robert Millan wrote:
> On Wed, Jan 20, 2010 at 12:43:38PM +0100, Michal Suchanek wrote:
>   
>> Shouldn't the structure also include the framebuffer orientation?
>>
>> If framebuffer transform support is included in grub it would be good
>> to pass the orientation the user specified for grub graphics output to
>> the OS so that the OS console output is displayed the same way
>> automatically.
>>     
>
> Makes sense.  Can you draft a proposal?
>
>   
There is a big difference between orientation and the rest of fields:
orientation is configuration variable whereas other fields are a
hardware information. We need to draw aline of what we want and what we
don't want to pass, otherwise, we may end up passing font, background
images and even logos.


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-24 21:05     ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-01-24 23:29       ` Michal Suchanek
  2010-01-25  7:37         ` Robert Millan
  0 siblings, 1 reply; 10+ messages in thread
From: Michal Suchanek @ 2010-01-24 23:29 UTC (permalink / raw)
  To: The development of GNU GRUB

2010/1/24 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> Robert Millan wrote:
>> On Wed, Jan 20, 2010 at 12:43:38PM +0100, Michal Suchanek wrote:
>>
>>> Shouldn't the structure also include the framebuffer orientation?
>>>
>>> If framebuffer transform support is included in grub it would be good
>>> to pass the orientation the user specified for grub graphics output to
>>> the OS so that the OS console output is displayed the same way
>>> automatically.
>>>
>>
>> Makes sense.  Can you draft a proposal?
>>
>>
> There is a big difference between orientation and the rest of fields:
> orientation is configuration variable whereas other fields are a
> hardware information. We need to draw aline of what we want and what we
> don't want to pass, otherwise, we may end up passing font, background
> images and even logos.
>

Unlike font, background image or logos the orientation of the screen
is hardware property. Unfortunately, few screens allow determining
this property in software so you have to rely on user input in most
cases.

Have you looked at the patch?

The framebuffer transform is represented as a bit field which could be
added to the mode flags.

I am not sure if that is the best approach, though. OSes might refuse
modes with unknown flags and this is not really mode specific so
perhaps separate flags would be better.

Thanks

Michal



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-24 23:29       ` Michal Suchanek
@ 2010-01-25  7:37         ` Robert Millan
  2010-01-25  9:26           ` Michal Suchanek
  0 siblings, 1 reply; 10+ messages in thread
From: Robert Millan @ 2010-01-25  7:37 UTC (permalink / raw)
  To: The development of GNU GRUB

On Mon, Jan 25, 2010 at 12:29:41AM +0100, Michal Suchanek wrote:
> 2010/1/24 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> > There is a big difference between orientation and the rest of fields:
> > orientation is configuration variable whereas other fields are a
> > hardware information. [...]
> 
> Unlike font, background image or logos the orientation of the screen
> is hardware property.

I think nobody wants font, background image or logos to be part of the
transferred data, as it's clearly overkill.

As for orientation of a screen, I don't know if you'd call this hardware
information, but if a screen is physically rotated, it's clearly not
software.

-- 
Robert Millan

  "Be the change you want to see in the world" -- Gandhi



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Multiboot video support
  2010-01-25  7:37         ` Robert Millan
@ 2010-01-25  9:26           ` Michal Suchanek
  0 siblings, 0 replies; 10+ messages in thread
From: Michal Suchanek @ 2010-01-25  9:26 UTC (permalink / raw)
  To: The development of GNU GRUB

2010/1/25 Robert Millan <rmh@aybabtu.com>:
> On Mon, Jan 25, 2010 at 12:29:41AM +0100, Michal Suchanek wrote:
>> 2010/1/24 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
>> > There is a big difference between orientation and the rest of fields:
>> > orientation is configuration variable whereas other fields are a
>> > hardware information. [...]
>>
>> Unlike font, background image or logos the orientation of the screen
>> is hardware property.
>
> I think nobody wants font, background image or logos to be part of the
> transferred data, as it's clearly overkill.

Well, it would be actually nice if people with specific needs (such as
large high-contrast fonts) could set this once for good. This would
improve usability greatly for them. However, propagating such setting
throughout the system is somewhat unrealistic given the multitude of
UI toolkits involved. Even if that was solved (or left to integrators
who want to support this feature) the problem is that in a complex
theme (which are planned for grub) you can no longer point at
particular font size, color and background color and say with
confidence this is what the user wants. We would be in the same boat
as Mozilla trying to determine "system colors" from the current GTK
theme and failing for odd themes (like a theme using black text and
background color and relying on background bitmap). Also there are
going to be multiple styles in a layout and it is not obvious which to
choose.

Thanks

Michal



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-01-25  9:26 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-14 14:55 [PATCH] Multiboot video support Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-15 14:50 ` Vladimir 'phi-coder/phcoder' Serbinenko
2010-01-15 15:44   ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-19 22:41     ` Robert Millan
2010-01-20 11:43 ` Michal Suchanek
2010-01-24 19:02   ` Robert Millan
2010-01-24 21:05     ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-24 23:29       ` Michal Suchanek
2010-01-25  7:37         ` Robert Millan
2010-01-25  9:26           ` Michal Suchanek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.