]> xenbits.xensource.com Git - people/andrewcoop/seabios.git/commitdiff
SeaVGABios/cbvga: Advertise compatible VESA modes
authorPatrick Rudolph <siro@das-labor.org>
Mon, 29 May 2017 17:25:14 +0000 (19:25 +0200)
committerKevin O'Connor <kevin@koconnor.net>
Mon, 12 Jun 2017 19:25:12 +0000 (15:25 -0400)
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.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>
vgasrc/cbvga.c

index 4b7cd0ef95c1abfbdced5d10eea5ece947b97c50..f85989a232df187f654b2964f41c1b45b34a3863 100644 (file)
@@ -19,19 +19,109 @@ 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)
 {
     if (mode == GET_GLOBAL(CBmode))
         return &CBmodeinfo;
     if (mode == 0x03)
         return &CBemulinfo;
+
+    int i;
+    for (i = 0; i < ARRAY_SIZE(cbvesa_modes); i++) {
+        struct cbvga_mode_s *cbmode_g = &cbvesa_modes[i];
+        if (GET_GLOBAL(cbmode_g->mode) == 0xffff)
+            continue;
+        if (GET_GLOBAL(cbmode_g->mode) == mode)
+            return &cbmode_g->info;
+    }
     return NULL;
 }
 
 void
 cbvga_list_modes(u16 seg, u16 *dest, u16 *last)
 {
-    if (dest<last) {
+    if (GET_GLOBAL(CBmode) != 0x3) {
+        /* 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
+         */
+        int i;
+        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);
+            if (mode == 0xffff)
+                continue;
+            SET_FARVAR(seg, *dest, mode);
+            dest++;
+        }
+    }
+    if (dest < last) {
         SET_FARVAR(seg, *dest, GET_GLOBAL(CBmode));
         dest++;
     }
@@ -145,6 +235,7 @@ struct cb_framebuffer {
 int
 cbvga_setup(void)
 {
+    int i;
     dprintf(1, "coreboot vga init\n");
 
     if (GET_GLOBAL(HaveRunInit))
@@ -199,5 +290,16 @@ cbvga_setup(void)
     memcpy_far(get_global_seg(), &CBemulinfo
                , get_global_seg(), &CBmodeinfo, sizeof(CBemulinfo));
 
+    // Validate 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) > ylines)
+            || (GET_GLOBAL(cbmode_g->info.width) > xlines)
+            || (GET_GLOBAL(cbmode_g->info.depth) != bpp)) {
+            dprintf(3, "Removing mode %x\n", GET_GLOBAL(cbmode_g->mode));
+            SET_VGA(cbmode_g->mode, 0xffff);
+        }
+    }
     return 0;
 }