[SeaBIOS] [PATCH 0/8] SeaVGABIOS improvments for coreboot's framebuffer v2

Patrick Rudolph posted 8 patches 7 years ago
Only 3 patches received!
vgasrc/bochsvga.c |   5 +
vgasrc/bochsvga.h |   1 +
vgasrc/cbvga.c    | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
vgasrc/clext.c    |   5 +
vgasrc/stdvga.c   |   5 +
vgasrc/vbe.c      |   2 +-
vgasrc/vgaentry.S |   2 +-
vgasrc/vgafb.c    |   2 +-
vgasrc/vgafb.h    |   2 +-
vgasrc/vgahw.h    |  10 ++
vgasrc/vgautil.h  |   3 +
11 files changed, 301 insertions(+), 10 deletions(-)
[SeaBIOS] [PATCH 0/8] SeaVGABIOS improvments for coreboot's framebuffer v2
Posted by Patrick Rudolph 7 years ago
This series add several fixes to coreboot's framebuffer implementation 
and it main purpose is to fix Microsoft's Windows as supported OS.

The series fixes the following issues:
* Windows shows no image in text-mode
* Windows NTLDR/bootmgr shows no image in VESA mode
* Windows shows no image in VESA mode
* Windows legacy Intel VGA driver requires VBT in VGA option ROM
* Clear screen broken due to INT 15h replaced by OS

I was able to boot Windows with the following configurations:
* using VgaSave driver in text-mode with a
  fixed display resolution of 640x480 at 4Bpp.
* using VgaSave driver in VESA mode and
  set a display resolution up to 1600x1200 at 24Bpp.
* using VgaSave driver in Windows's "Safe Mode" in VESA mode and
  set a display resolution up to 1600x1200 at 24Bpp.
* using the Intel VGA driver with up to the panel native
  resolution of 1680x1050 at 24Bpp.

Most likely other VESA compatible bootloaders and operating systems
will be fixed, too.

Changes since v1:
* Add crash detection handler for INT 15h modifications.
* Disable VESA modes in cbvga_init
* Make memcpy_high method public
* Copy Intel VBT to VGA option ROM if provided by ASLS

Patrick Rudolph (8):
  SeaVGABios/cbvga: Advertise correct pixel format
  SeaVGABios/cbvga: Assume VGA compatible GPU in text-mode
  SeaVGABIOS/vbe: Query driver for scanline pitch
  SeaVGABios/cbvga: Use active mode to clear screen
  SeaVGABios/cbvga: Advertise compatible VESA modes
  SeaVGABios/vgafb: Make memcpy_high public
  SeaVGABios/cbvga:: Add Intel VBT support
  SeaVGABios/cbvga: Add crash detection handler

 vgasrc/bochsvga.c |   5 +
 vgasrc/bochsvga.h |   1 +
 vgasrc/cbvga.c    | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 vgasrc/clext.c    |   5 +
 vgasrc/stdvga.c   |   5 +
 vgasrc/vbe.c      |   2 +-
 vgasrc/vgaentry.S |   2 +-
 vgasrc/vgafb.c    |   2 +-
 vgasrc/vgafb.h    |   2 +-
 vgasrc/vgahw.h    |  10 ++
 vgasrc/vgautil.h  |   3 +
 11 files changed, 301 insertions(+), 10 deletions(-)

-- 
2.9.3


_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios
[SeaBIOS] [PATCH 1/8] SeaVGABios/cbvga: Advertise correct pixel format
Posted by Patrick Rudolph 7 years ago
Accumulate the pixel format's bits instead relying on coreboot's
bits_per_pixel, which says nothing about the active pixel format.

Allows VBE to correctly advertise XRGB8 and BGRX8 framebuffer formats,
commonly used by coreboot.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>

diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
index b8216a9..39ffdbb 100644
--- a/vgasrc/cbvga.c
+++ b/vgasrc/cbvga.c
@@ -1,6 +1,7 @@
 // Simple framebuffer vgabios for use with coreboot native vga init.
 //
 // Copyright (C) 2014  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2017  Patrick Rudolph <siro@das-labor.org>
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
@@ -164,7 +165,8 @@ cbvga_setup(void)
     }
 
     u64 addr = GET_FARVAR(0, cbfb->physical_address);
-    u8 bpp = GET_FARVAR(0, cbfb->bits_per_pixel);
+    u8 bpp = cbfb->blue_mask_size + cbfb->green_mask_size
+             + cbfb->red_mask_size + cbfb->reserved_mask_size;
     u32 xlines = GET_FARVAR(0, cbfb->x_resolution);
     u32 ylines = GET_FARVAR(0, cbfb->y_resolution);
     u32 linelength = GET_FARVAR(0, cbfb->bytes_per_line);
-- 
2.9.3


_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios
[SeaBIOS] [PATCH 2/8] SeaVGABios/cbvga: Assume VGA compatible GPU in text-mode
Posted by Patrick Rudolph 7 years ago
Assume the GPU is VGA compatible when running in text-mode.
Advertise VGA modes.
Microsoft Windows relies on graphics mode 12 as last resort when
running in text mode. It is used even when not advertised.

Allows to boot Windows 7 in "Safe Mode" and shows the boot splash.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>

diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
index 39ffdbb..49af7f9 100644
--- a/vgasrc/cbvga.c
+++ b/vgasrc/cbvga.c
@@ -21,6 +21,10 @@ static u32 CBlinelength VAR16;
 
 struct vgamode_s *cbvga_find_mode(int mode)
 {
+    /* Assume VGA compatible hardware in text-mode. */
+    if (GET_GLOBAL(CBmode) == 0x3)
+        return stdvga_find_mode(mode);
+
     if (mode == GET_GLOBAL(CBmode))
         return &CBmodeinfo;
     if (mode == 0x03)
@@ -31,11 +35,11 @@ struct vgamode_s *cbvga_find_mode(int mode)
 void
 cbvga_list_modes(u16 seg, u16 *dest, u16 *last)
 {
-    if (dest<last) {
-        SET_FARVAR(seg, *dest, GET_GLOBAL(CBmode));
-        dest++;
+
+    /* Assume VGA compatible hardware in text-mode. */
+    if (GET_GLOBAL(CBmode) == 0x3) {
+        stdvga_list_modes(seg, dest, last);
     }
-    SET_FARVAR(seg, *dest, 0xffff);
 }
 
 int
@@ -98,6 +102,11 @@ int
 cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
 {
     u8 emul = vmode_g == &CBemulinfo || GET_GLOBAL(CBmode) == 0x03;
+
+    /* Assume VGA compatible hardware in text-mode. */
+    if (GET_GLOBAL(CBmode) == 0x03)
+        return stdvga_set_mode(vmode_g, flags);
+
     MASK_BDA_EXT(flags, BF_EMULATE_TEXT, emul ? BF_EMULATE_TEXT : 0);
     if (!(flags & MF_NOCLEARMEM)) {
         if (GET_GLOBAL(CBmodeinfo.memmodel) == MM_TEXT) {
-- 
2.9.3


_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios
[SeaBIOS] [PATCH 4/8] SeaVGABios/cbvga: Use active mode to clear screen
Posted by Patrick Rudolph 7 years ago
As coreboot framebuffer is immutable always use CBmodeinfo.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>

diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
index 6b3233e..ae2bd4a 100644
--- a/vgasrc/cbvga.c
+++ b/vgasrc/cbvga.c
@@ -114,7 +114,7 @@ cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
             return 0;
         }
         struct gfx_op op;
-        init_gfx_op(&op, vmode_g);
+        init_gfx_op(&op, &CBmodeinfo);
         op.x = op.y = 0;
         op.xlen = GET_GLOBAL(CBmodeinfo.width);
         op.ylen = GET_GLOBAL(CBmodeinfo.height);
-- 
2.9.3


_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios
[SeaBIOS] [PATCH 5/8] SeaVGABios/cbvga: Advertise compatible VESA modes
Posted by Patrick Rudolph 7 years ago
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.

v2: Invalidate modes in cbvga_setup.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>

diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
index ae2bd4a..42a50f7 100644
--- a/vgasrc/cbvga.c
+++ b/vgasrc/cbvga.c
@@ -19,8 +19,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);
@@ -29,16 +94,45 @@ struct vgamode_s *cbvga_find_mode(int mode)
         return &CBmodeinfo;
     if (mode == 0x03)
         return &CBemulinfo;
+
+    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)
 {
+    int i;
 
     /* 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);
+            if (mode == 0xffff)
+                continue;
+            SET_FARVAR(seg, *dest, mode);
+            dest++;
+        }
+        if (dest < last) {
+            SET_FARVAR(seg, *dest, GET_GLOBAL(CBmode));
+            dest++;
+        }
+        SET_FARVAR(seg, *dest, 0xffff);
     }
 }
 
@@ -154,6 +248,7 @@ struct cb_framebuffer {
 int
 cbvga_setup(void)
 {
+    int i;
     dprintf(1, "coreboot vga init\n");
 
     if (GET_GLOBAL(HaveRunInit))
@@ -208,5 +303,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;
 }
-- 
2.9.3


_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios
[SeaBIOS] [PATCH 8/8] SeaVGABios/cbvga: Add crash detection handler
Posted by Patrick Rudolph 7 years ago
Add a crash detection handler to detect a crash on mode
change and don't clear the screen on mode change ever again.

This is a workaround for Microsoft Windows doing some magic
to the INT 15 handler, preventing memcpy_high to function properly.

Allows Microsoft's Windows 7 to boot in safe mode.
Some artifacts might stay in the unused part of the framebuffer,
but at least it is possible to use all advertised VESA modes.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>

diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
index bc5b79e..af4b138 100644
--- a/vgasrc/cbvga.c
+++ b/vgasrc/cbvga.c
@@ -195,6 +195,8 @@ cbvga_save_restore(int cmd, u16 seg, void *data)
     return bda_save_restore(cmd, seg, data);
 }
 
+static u16 crash_detect VAR16;
+
 int
 cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
 {
@@ -210,6 +212,18 @@ cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
             memset16_far(SEG_CTEXT, (void*)0, 0x0720, 80*25*2);
             return 0;
         }
+        /* Windows replaced INT 15h handler, resulting in a crash, as
+         * mempcpy_high doesn't work any more.
+         * We can't do anything about that, but try to detect the crash
+         * and don't clear the screen.
+         */
+        if (GET_GLOBAL(crash_detect) == 0xdead) {
+            dprintf(1, "Detected crash, skipping clear screen.\n");
+            return 0;
+        }
+        /* Install crash signal */
+        SET_VGA(crash_detect, 0xdead);
+
         struct gfx_op op;
         init_gfx_op(&op, &CBmodeinfo);
         op.x = op.y = 0;
@@ -217,6 +231,9 @@ cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
         op.ylen = GET_GLOBAL(CBmodeinfo.height);
         op.op = GO_MEMSET;
         handle_gfx_op(&op);
+
+        /* Reset crash signal */
+        SET_VGA(crash_detect, 0);
     }
     return 0;
 }
-- 
2.9.3


_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios
Re: [SeaBIOS] [PATCH 0/8] SeaVGABIOS improvments for coreboot's framebuffer v2
Posted by Kevin O'Connor 7 years ago
On Fri, Mar 24, 2017 at 05:27:19PM +0100, Patrick Rudolph wrote:
> This series add several fixes to coreboot's framebuffer implementation 
> and it main purpose is to fix Microsoft's Windows as supported OS.
> 
> The series fixes the following issues:
> * Windows shows no image in text-mode
> * Windows NTLDR/bootmgr shows no image in VESA mode
> * Windows shows no image in VESA mode
> * Windows legacy Intel VGA driver requires VBT in VGA option ROM
> * Clear screen broken due to INT 15h replaced by OS
> 
> I was able to boot Windows with the following configurations:
> * using VgaSave driver in text-mode with a
>   fixed display resolution of 640x480 at 4Bpp.
> * using VgaSave driver in VESA mode and
>   set a display resolution up to 1600x1200 at 24Bpp.
> * using VgaSave driver in Windows's "Safe Mode" in VESA mode and
>   set a display resolution up to 1600x1200 at 24Bpp.
> * using the Intel VGA driver with up to the panel native
>   resolution of 1680x1050 at 24Bpp.
> 
> Most likely other VESA compatible bootloaders and operating systems
> will be fixed, too.
> 
> Changes since v1:

Thanks, but I didn't see a response to my comments on patches 1 and 2
from the last series.

> * Add crash detection handler for INT 15h modifications.

Can you explain how this works?  If int1587 is disabled, why is it a
priority to not clear the screen?

> * Copy Intel VBT to VGA option ROM if provided by ASLS

As a high level comment, I think it would be great to have further
support for Intel video in SeaVGABIOS, but I wonder if extending cbvga
is the right approach.  Seems like we could make an intel-seavgabios
and it would be a better platfrom for future intel specific features
(like auto-detecting the framebuffer and maybe even switching modes).

Cheers,
-Kevin

_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://www.coreboot.org/mailman/listinfo/seabios