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

Patrick Rudolph siro at das-labor.org
Fri Mar 17 17:49:42 CET 2017


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.

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.

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.

Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
 vgasrc/cbvga.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)

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);
     }
 }
 
-- 
2.7.4




More information about the SeaBIOS mailing list