[2469] 2009-08-04 Robert Millan <[email protected]>

Robert Millan <[email protected]> Tue, 04 Aug 2009 21:28:19 +0000
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 2469
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2469
Author:   robertmh
Date:     2009-08-04 21:28:19 +0000 (Tue, 04 Aug 2009)
Log Message:
-----------
2009-08-04  Robert Millan  <[email protected]>

        Fix a bug resulting in black screen when loading Linux using a
        packed video mode.

        * kern/i386/pc/startup.S (grub_vbe_bios_getset_dac_palette_width): New
        function.

        * include/grub/i386/pc/vbe.h (GRUB_VBE_CAPABILITY_DACWIDTH): New macro.
        (grub_vbe_bios_getset_dac_palette_width): New function.
        (grub_vbe_bios_get_dac_palette_width)
        (grub_vbe_bios_set_dac_palette_width): New macros (act as wrappers for
        grub_vbe_bios_getset_dac_palette_width()).

        * video/i386/pc/vbe.c (grub_vbe_probe): Use `GRUB_VBE_STATUS_OK' to
        check for return status.
        (grub_vbe_get_video_mode_info): When getting information for a packed
        mode (<= 8 bpp), obtain DAC palette width using
        grub_vbe_bios_getset_dac_palette_width(), and use that for initializing
        {red,green,blue}_mark_size.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/include/grub/i386/pc/vbe.h
    trunk/grub2/kern/i386/pc/startup.S
    trunk/grub2/video/i386/pc/vbe.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2009-08-04 21:23:11 UTC (rev 2468)
+++ trunk/grub2/ChangeLog	2009-08-04 21:28:19 UTC (rev 2469)
@@ -1,3 +1,24 @@
+2009-08-04  Robert Millan  <[email protected]>
+
+	Fix a bug resulting in black screen when loading Linux using a
+	packed video mode.
+
+	* kern/i386/pc/startup.S (grub_vbe_bios_getset_dac_palette_width): New
+	function.
+
+	* include/grub/i386/pc/vbe.h (GRUB_VBE_CAPABILITY_DACWIDTH): New macro.
+	(grub_vbe_bios_getset_dac_palette_width): New function.
+	(grub_vbe_bios_get_dac_palette_width)
+	(grub_vbe_bios_set_dac_palette_width): New macros (act as wrappers for
+	grub_vbe_bios_getset_dac_palette_width()).
+
+	* video/i386/pc/vbe.c (grub_vbe_probe): Use `GRUB_VBE_STATUS_OK' to
+	check for return status.
+	(grub_vbe_get_video_mode_info): When getting information for a packed
+	mode (<= 8 bpp), obtain DAC palette width using
+	grub_vbe_bios_getset_dac_palette_width(), and use that for initializing
+	{red,green,blue}_mark_size.
+
 2009-08-04  Felix Zielcke  <[email protected]>
 
 	* commands/search.c (options): Fix help output to match actual code.

Modified: trunk/grub2/include/grub/i386/pc/vbe.h
===================================================================
--- trunk/grub2/include/grub/i386/pc/vbe.h	2009-08-04 21:23:11 UTC (rev 2468)
+++ trunk/grub2/include/grub/i386/pc/vbe.h	2009-08-04 21:28:19 UTC (rev 2469)
@@ -30,6 +30,8 @@
 /* VBE status codes.  */
 #define GRUB_VBE_STATUS_OK		0x004f
 
+#define GRUB_VBE_CAPABILITY_DACWIDTH	(1 << 0)
+
 /* Bits from the GRUB_VBE "mode_attributes" field in the mode info struct.  */
 #define GRUB_VBE_MODEATTR_SUPPORTED                 (1 << 0)
 #define GRUB_VBE_MODEATTR_RESERVED_1                (1 << 1)
@@ -181,6 +183,11 @@
 grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
                                                             struct grub_vbe_mode_info_block *mode_info);
 
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_getset_dac_palette_width) (int set, int *width);
+
+#define grub_vbe_bios_get_dac_palette_width(width)	grub_vbe_bios_getset_dac_palette_width(0, (width))
+#define grub_vbe_bios_set_dac_palette_width(width)	grub_vbe_bios_getset_dac_palette_width(1, (width))
+
 /* Call VESA BIOS 0x4f02 to set video mode, return status.  */
 grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
                                                        struct grub_vbe_crtc_info_block *crtc_info);

Modified: trunk/grub2/kern/i386/pc/startup.S
===================================================================
--- trunk/grub2/kern/i386/pc/startup.S	2009-08-04 21:23:11 UTC (rev 2468)
+++ trunk/grub2/kern/i386/pc/startup.S	2009-08-04 21:28:19 UTC (rev 2469)
@@ -1733,6 +1733,52 @@
 	ret
 
 /*
+ * grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size)
+ *
+ * Register allocations for parameters:
+ * %eax		set
+ * %edx		*dac_mask_size
+ */
+FUNCTION(grub_vbe_bios_getset_dac_palette_width)
+	pushl	%ebp
+	pushl	%ebx
+
+	xorl	%ebx, %ebx
+
+	/* If we only want to fetch the value, set %bl to 1.  */
+	testl	%eax, %eax
+	jne	1f
+	incb	%bl
+1:
+
+	/* Put desired width in %bh.  */
+	movl	(%edx), %eax
+	movb	%al, %bh
+
+	call    prot_to_real
+	.code16
+
+	movw	$0x4f08, %ax
+	int	$0x10
+
+	movw	%ax, %dx	/* real_to_prot destroys %eax.  */
+
+	DATA32 call	real_to_prot
+	.code32
+
+	/* Move result back to *dac_mask_size.  */
+	movb	%bh, %al
+	movl	%eax, (%edx)
+
+	/* Return value in %eax.  */
+	xorl	%eax, %eax
+	movw	%dx, %ax
+
+	popl	%ebx
+	popl	%ebp
+	ret
+
+/*
  * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
  *						      grub_uint32_t position);
  *

Modified: trunk/grub2/video/i386/pc/vbe.c
===================================================================
--- trunk/grub2/video/i386/pc/vbe.c	2009-08-04 21:23:11 UTC (rev 2468)
+++ trunk/grub2/video/i386/pc/vbe.c	2009-08-04 21:28:19 UTC (rev 2469)
@@ -116,7 +116,7 @@
 
       /* Try to get controller info block.  */
       status = grub_vbe_bios_get_controller_info (vbe_ib);
-      if (status == 0x004F)
+      if (status == GRUB_VBE_STATUS_OK)
         {
           /* Copy it for later usage.  */
           grub_memcpy (&controller_info, vbe_ib, sizeof (controller_info));
@@ -300,6 +300,24 @@
 
       /* Make copy of mode info block.  */
       grub_memcpy (mode_info, mi_tmp, sizeof (*mode_info));
+
+      /* Packed mode.  Query DAC Palette width for color sizes.  */
+      if (mode_info->bits_per_pixel <= 8)
+	{
+	  int width = 8;
+	  status = 0;
+
+	  if (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH)
+	    status = grub_vbe_bios_set_dac_palette_width (& width);
+
+	  if (status != GRUB_VBE_STATUS_OK)
+	    /* 6 is default after mode reset.  */
+	    width = 6;
+
+	  mode_info->red_mask_size = mode_info->green_mask_size
+	    = mode_info->blue_mask_size = width;
+	  mode_info->rsvd_mask_size = 0;
+	}
     }
   else
     /* Just clear mode info block if it isn't a VESA mode.  */