[SeaBIOS] [PATCH 4/4] SeaVGABios/cbvga: Advertise compatible VESA modes

Kevin O'Connor kevin at koconnor.net
Sat Mar 18 02:14:24 CET 2017


On Fri, Mar 17, 2017 at 05:49:42PM +0100, Patrick Rudolph wrote:
> Advertise compatible VESA modes, that are smaller or equal to
> coreboot's active framebuffer. Only modes that have the same Bpp
> are advertise and can be selected.
> 
> Allows the Windows 7 bootloader NTLDR to show up in VESA mode.
> Allows to show the Windows 7 boot logo.
> Allows Windows to boot in safe mode and in normal boot using
> VgaSave driver with resolution up to 1600x1200.
> 
> This fixes most likely other bootloader and operating systems as well,
> in case the are relying on VESA framebuffer support.

Interesting - just declaring the modes gets windows much further
along..  Seems worthwhile.

> Known issues:
> Windows replaces int 15h handler, resulting in memcpy_far not being available.
> The call will prematurely exit and Windows won't show any picture at all.
> All tests were done with clear screen on mode change disabled.

Not sure how to fix that.  The reason the code uses int 1587 calls is
to try and allow the code to work even when the OS is in vm86 mode.
Presumably Windows is catching int 1587 because it's running in
protected mode - but if it doesn't allow the writes to the
framebuffer, not sure how the vgabios will get the writes there
either.

> NTLDR is aware of the framebuffer's pitch, but the internal
> clear screen method isn't. Some text artifacts might stay on screen.
> That's nothing SeaVGABios can fix.

The seavgabios clear screen isn't clearing the whole screen?  That
should be fixable.

[...]
> diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
> index 4c349c5..6be6936 100644
> --- a/vgasrc/cbvga.c
> +++ b/vgasrc/cbvga.c
> @@ -18,8 +18,73 @@ static struct vgamode_s CBmodeinfo VAR16;
>  static struct vgamode_s CBemulinfo VAR16;
>  static u32 CBlinelength VAR16;
>  
> +static struct cbvga_mode_s
> +{
> +    u16 mode;
> +    struct vgamode_s info;
> +} cbvesa_modes[] VAR16 = {
> +    /* VESA 1.0 modes */
> +    { 0x110, { MM_DIRECT, 640,  480,  15, 8, 16, SEG_GRAPH } },
> +    { 0x111, { MM_DIRECT, 640,  480,  16, 8, 16, SEG_GRAPH } },
> +    { 0x112, { MM_DIRECT, 640,  480,  24, 8, 16, SEG_GRAPH } },
> +    { 0x113, { MM_DIRECT, 800,  600,  15, 8, 16, SEG_GRAPH } },
> +    { 0x114, { MM_DIRECT, 800,  600,  16, 8, 16, SEG_GRAPH } },
> +    { 0x115, { MM_DIRECT, 800,  600,  24, 8, 16, SEG_GRAPH } },
> +    { 0x116, { MM_DIRECT, 1024, 768,  15, 8, 16, SEG_GRAPH } },
> +    { 0x117, { MM_DIRECT, 1024, 768,  16, 8, 16, SEG_GRAPH } },
> +    { 0x118, { MM_DIRECT, 1024, 768,  24, 8, 16, SEG_GRAPH } },
> +    { 0x119, { MM_DIRECT, 1280, 1024, 15, 8, 16, SEG_GRAPH } },
> +    { 0x11A, { MM_DIRECT, 1280, 1024, 16, 8, 16, SEG_GRAPH } },
> +    { 0x11B, { MM_DIRECT, 1280, 1024, 24, 8, 16, SEG_GRAPH } },
> +    { 0x11D, { MM_DIRECT, 1600, 1200, 15, 8, 16, SEG_GRAPH } },
> +    { 0x11E, { MM_DIRECT, 1600, 1200, 16, 8, 16, SEG_GRAPH } },
> +    { 0x11F, { MM_DIRECT, 1600, 1200, 24, 8, 16, SEG_GRAPH } },
> +    /* VESA 2.0 modes */
> +    { 0x141, { MM_DIRECT, 640,  400,  32, 8, 16, SEG_GRAPH } },
> +    { 0x142, { MM_DIRECT, 640,  480,  32, 8, 16, SEG_GRAPH } },
> +    { 0x143, { MM_DIRECT, 800,  600,  32, 8, 16, SEG_GRAPH } },
> +    { 0x144, { MM_DIRECT, 1024, 768,  32, 8, 16, SEG_GRAPH } },
> +    { 0x145, { MM_DIRECT, 1280, 1024, 32, 8, 16, SEG_GRAPH } },
> +    { 0x147, { MM_DIRECT, 1600, 1200, 32, 8, 16, SEG_GRAPH } },
> +    { 0x149, { MM_DIRECT, 1152, 864,  15, 8, 16, SEG_GRAPH } },
> +    { 0x14a, { MM_DIRECT, 1152, 864,  16, 8, 16, SEG_GRAPH } },
> +    { 0x14b, { MM_DIRECT, 1152, 864,  24, 8, 16, SEG_GRAPH } },
> +    { 0x14c, { MM_DIRECT, 1152, 864,  32, 8, 16, SEG_GRAPH } },
> +    { 0x175, { MM_DIRECT, 1280, 768,  16, 8, 16, SEG_GRAPH } },
> +    { 0x176, { MM_DIRECT, 1280, 768,  24, 8, 16, SEG_GRAPH } },
> +    { 0x177, { MM_DIRECT, 1280, 768,  32, 8, 16, SEG_GRAPH } },
> +    { 0x178, { MM_DIRECT, 1280, 800,  16, 8, 16, SEG_GRAPH } },
> +    { 0x179, { MM_DIRECT, 1280, 800,  24, 8, 16, SEG_GRAPH } },
> +    { 0x17a, { MM_DIRECT, 1280, 800,  32, 8, 16, SEG_GRAPH } },
> +    { 0x17b, { MM_DIRECT, 1280, 960,  16, 8, 16, SEG_GRAPH } },
> +    { 0x17c, { MM_DIRECT, 1280, 960,  24, 8, 16, SEG_GRAPH } },
> +    { 0x17d, { MM_DIRECT, 1280, 960,  32, 8, 16, SEG_GRAPH } },
> +    { 0x17e, { MM_DIRECT, 1440, 900,  16, 8, 16, SEG_GRAPH } },
> +    { 0x17f, { MM_DIRECT, 1440, 900,  24, 8, 16, SEG_GRAPH } },
> +    { 0x180, { MM_DIRECT, 1440, 900,  32, 8, 16, SEG_GRAPH } },
> +    { 0x181, { MM_DIRECT, 1400, 1050, 16, 8, 16, SEG_GRAPH } },
> +    { 0x182, { MM_DIRECT, 1400, 1050, 24, 8, 16, SEG_GRAPH } },
> +    { 0x183, { MM_DIRECT, 1400, 1050, 32, 8, 16, SEG_GRAPH } },
> +    { 0x184, { MM_DIRECT, 1680, 1050, 16, 8, 16, SEG_GRAPH } },
> +    { 0x185, { MM_DIRECT, 1680, 1050, 24, 8, 16, SEG_GRAPH } },
> +    { 0x186, { MM_DIRECT, 1680, 1050, 32, 8, 16, SEG_GRAPH } },
> +    { 0x187, { MM_DIRECT, 1920, 1200, 16, 8, 16, SEG_GRAPH } },
> +    { 0x188, { MM_DIRECT, 1920, 1200, 24, 8, 16, SEG_GRAPH } },
> +    { 0x189, { MM_DIRECT, 1920, 1200, 32, 8, 16, SEG_GRAPH } },
> +    { 0x18a, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } },
> +    { 0x18b, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } },
> +    { 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } },
> +    { 0x18d, { MM_DIRECT, 1280, 720,  16, 8, 16, SEG_GRAPH } },
> +    { 0x18e, { MM_DIRECT, 1280, 720,  24, 8, 16, SEG_GRAPH } },
> +    { 0x18f, { MM_DIRECT, 1280, 720,  32, 8, 16, SEG_GRAPH } },
> +    { 0x190, { MM_DIRECT, 1920, 1080, 16, 8, 16, SEG_GRAPH } },
> +    { 0x191, { MM_DIRECT, 1920, 1080, 24, 8, 16, SEG_GRAPH } },
> +    { 0x192, { MM_DIRECT, 1920, 1080, 32, 8, 16, SEG_GRAPH } },
> +};
> +
>  struct vgamode_s *cbvga_find_mode(int mode)
>  {
> +    int i;
>      /* Assume VGA compatible hardware in text-mode. */
>      if (GET_GLOBAL(CBmode) == 0x3)
>          return stdvga_find_mode(mode);
> @@ -28,16 +93,61 @@ struct vgamode_s *cbvga_find_mode(int mode)
>          return &CBmodeinfo;
>      if (mode == 0x03)
>          return &CBemulinfo;
> +
> +    /* Advertise compatible VESA VGA modes. */
> +    for (i = 0; i < ARRAY_SIZE(cbvesa_modes); i++) {
> +        struct cbvga_mode_s *cbmode_g = &cbvesa_modes[i];
> +        /* Skip VBE modes that doesn't fit into coreboot's framebuffer */
> +        if (GET_GLOBAL(cbmode_g->info.height) > GET_GLOBAL(CBmodeinfo.height))
> +            continue;
> +        if (GET_GLOBAL(cbmode_g->info.width) > GET_GLOBAL(CBmodeinfo.width))
> +            continue;
> +        if (GET_GLOBAL(cbmode_g->info.depth) != GET_GLOBAL(CBmodeinfo.depth))
> +            continue;
> +        if (GET_GLOBAL(cbmode_g->mode) == mode)
> +            return &cbmode_g->info;
> +    }
>      return NULL;
>  }
>  
>  void
>  cbvga_list_modes(u16 seg, u16 *dest, u16 *last)
>  {
> +    int i;
> +    u8 found = 0;
>  
>      /* Assume VGA compatible hardware in text-mode. */
>      if (GET_GLOBAL(CBmode) == 0x3) {
>          stdvga_list_modes(seg, dest, last);
> +    } else {
> +        /* Advertise additional SVGA modes for Microsoft NTLDR graphical mode.
> +         * Microsoft NTLDR:
> +         * * Graphical mode uses a maximum resolution of 1600x1200.
> +         * * Expects to find VESA mode with 800x600 or 1024x768.
> +         * * 24 Bpp and 32 Bpp are supported
> +         */
> +        for (i = 0; i < ARRAY_SIZE(cbvesa_modes) && dest < last; i++) {
> +            struct cbvga_mode_s *cbmode_g = &cbvesa_modes[i];
> +            u16 mode = GET_GLOBAL(cbmode_g->mode);
> +            /* Skip VBE modes that doesn't fit into coreboot's framebuffer */
> +            if (GET_GLOBAL(cbmode_g->info.height) > GET_GLOBAL(CBmodeinfo.height))
> +                continue;
> +            if (GET_GLOBAL(cbmode_g->info.width) > GET_GLOBAL(CBmodeinfo.width))
> +                continue;
> +            /* Skip VBE modes with unsupported Bpp */
> +            if (GET_GLOBAL(cbmode_g->info.depth) != GET_GLOBAL(CBmodeinfo.depth))
> +                continue;
> +            if ((GET_GLOBAL(cbmode_g->info.height) == GET_GLOBAL(CBmodeinfo.height)) &&
> +               (GET_GLOBAL(cbmode_g->info.width) == GET_GLOBAL(CBmodeinfo.width)))
> +                   found = 1;
> +            SET_FARVAR(seg, *dest, mode);
> +            dest++;
> +        }
> +        if ((dest < last) && !found) {
> +            SET_FARVAR(seg, *dest, GET_GLOBAL(CBmode));
> +            dest++;
> +        }
> +        SET_FARVAR(seg, *dest, 0xffff);

I think it would be preferable if cbvga_setup() scanned all the modes
at startup and invalidated the non working modes - see the "Validate
modes" block in bochsvga_setup() as an example.

Thanks.
-Kevin



More information about the SeaBIOS mailing list