When using packed color modes, Linux expects we fill the color sizes with the value obtained from the DAC. If we give it zeroes (like we currently do) it displays a blank screen.
This can be reproduced by attempting to boot Linux with a 8-bit color mode (e.g. set gfxpayload=800x600x8). Now I'm not completely sure where does this belong. I think it's somewhat generic and we can reasonably expect other OSes to want this information too, but I'm not completely sure. An alternative would be to do this query in the Linux loader, but this has the disadvantage that we're putting backend-specific code in the loader which aims to be completely backend-independant someday. Also, tell me what you think about the "getset" hack. It looks like a clean way of providing both functions in less space, but then I'm not sure if we really want both functions. For now we only use the "set" one. Then again, once you have "set" getting "get" comes really cheap. -- Robert Millan The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and how) you may access your data; but nobody's threatening your freedom: we still allow you to remove your data and not access it at all."
Index: kern/i386/pc/startup.S =================================================================== --- kern/i386/pc/startup.S (revision 2439) +++ kern/i386/pc/startup.S (working copy) @@ -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); * Index: video/i386/pc/vbe.c =================================================================== --- video/i386/pc/vbe.c (revision 2439) +++ video/i386/pc/vbe.c (working copy) @@ -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 != 0x004F) + /* 6 is default after mode reset. */ + width = 6; + + mode_info->red_mask_size = mode_info->green_mask_size + = mode_info->blue_mask_size = mode_info->rsvd_mask_size + = width; + } } else /* Just clear mode info block if it isn't a VESA mode. */ Index: include/grub/i386/pc/vbe.h =================================================================== --- include/grub/i386/pc/vbe.h (revision 2439) +++ include/grub/i386/pc/vbe.h (working copy) @@ -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);
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel