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
I was able to boot Windows using VgaSave driver in text-mode with a fixed display resolution of 640x480@4Bpp.
I was able to boot Windows using VgaSave driver in VESA mode and set a display resolution up to 1600x1200@24Bpp.
Most likely other VESA compatible bootloaders and operating systems will be fixed, too.
While most issues are fixed, one critical remains: Windows replaces int 15h at the start of the boot process, but SeaVGABios relies on it to clear the screen. It would be great if you could help me to implement a 32bit memcpy method that doesn't rely on bios calls to copy memory. All test in VESA mode had the clear screen feature disabled.
Patrick Rudolph (4): 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
vgasrc/bochsvga.c | 5 ++ vgasrc/bochsvga.h | 1 + vgasrc/cbvga.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- vgasrc/clext.c | 5 ++ vgasrc/stdvga.c | 5 ++ vgasrc/vbe.c | 2 +- vgasrc/vgahw.h | 10 ++++ vgasrc/vgautil.h | 3 ++ 8 files changed, 161 insertions(+), 6 deletions(-)
Assume the GPU is VGA compatible when running in text-mode. Advertise VGA modes using SeaVGABios' stdvga driver. Microsoft Windows relies on graphics mode 12 as last resort when running in text mode, even when not advertised.
Allows Windows 7 to boot in 640x480 and 16 colors mode using the VgaSave driver. Allows Windows 7 to show the loading bar splash screen.
Known issues: The palette seems wrong, as colors are swapped ( blue is red, ... ).
Signed-off-by: Patrick Rudolph siro@das-labor.org --- vgasrc/cbvga.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c index ebd17b0..87ec77e 100644 --- a/vgasrc/cbvga.c +++ b/vgasrc/cbvga.c @@ -20,6 +20,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) @@ -30,11 +34,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 @@ -97,6 +101,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) {
On Fri, Mar 17, 2017 at 05:49:39PM +0100, Patrick Rudolph wrote:
Assume the GPU is VGA compatible when running in text-mode. Advertise VGA modes using SeaVGABios' stdvga driver. Microsoft Windows relies on graphics mode 12 as last resort when running in text mode, even when not advertised.
Allows Windows 7 to boot in 640x480 and 16 colors mode using the VgaSave driver. Allows Windows 7 to show the loading bar splash screen.
Known issues: The palette seems wrong, as colors are swapped ( blue is red, ... ).
What graphics hardware did you test this on?
If stdvga_set_mode() works on the hardware, why not use stdvga seavgabios and get the rest of the vgabios functionality? (That is, why use cbvga seavgabios at all?)
-Kevin
Query the driver for the real scanline pitch in bytes.
As cbvga doesn't change the pitch on mode change, always return the same pitch, that might exceed width times Bytes-per-pixel.
Signed-off-by: Patrick Rudolph siro@das-labor.org --- vgasrc/bochsvga.c | 5 +++++ vgasrc/bochsvga.h | 1 + vgasrc/cbvga.c | 7 +++++++ vgasrc/clext.c | 5 +++++ vgasrc/stdvga.c | 5 +++++ vgasrc/vbe.c | 2 +- vgasrc/vgahw.h | 10 ++++++++++ vgasrc/vgautil.h | 3 +++ 8 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index ec5d101..458b3a8 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -310,6 +310,11 @@ bochsvga_save_restore(int cmd, u16 seg, void *data) return ret + (VBE_DISPI_INDEX_Y_OFFSET-VBE_DISPI_INDEX_XRES+1)*sizeof(u16); }
+int +bochsvga_get_linesize(struct vgamode_s *vmode_g) +{ + return DIV_ROUND_UP(vmode_g->width * vga_bpp(vmode_g), 8); +}
/**************************************************************** * Mode setting diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index ae5f75d..40ce6f1 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -52,6 +52,7 @@ int bochsvga_get_dacformat(struct vgamode_s *vmode_g); int bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val); int bochsvga_save_restore(int cmd, u16 seg, void *data); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags); +int bochsvga_get_linesize(struct vgamode_s *vmode_g); int bochsvga_setup(void);
#endif // bochsvga.h diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c index 87ec77e..50e6e69 100644 --- a/vgasrc/cbvga.c +++ b/vgasrc/cbvga.c @@ -123,6 +123,13 @@ cbvga_set_mode(struct vgamode_s *vmode_g, int flags) return 0; }
+int +cbvga_get_linesize(struct vgamode_s *vmode_g) +{ + /* Can't change mode, always report active pitch. */ + return GET_GLOBAL(CBlinelength); +} + #define CB_TAG_FRAMEBUFFER 0x0012 struct cb_framebuffer { u32 tag; diff --git a/vgasrc/clext.c b/vgasrc/clext.c index da8b790..08bc9b5 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -376,6 +376,11 @@ clext_save_restore(int cmd, u16 seg, void *data) return stdvga_save_restore(cmd, seg, data); }
+int +clext_get_linesize(struct vgamode_s *vmode_g) +{ + return DIV_ROUND_UP(vmode_g->width * vga_bpp(vmode_g), 8); +}
/**************************************************************** * Mode setting diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 886deca..0e24297 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -321,6 +321,11 @@ stdvga_set_dacformat(struct vgamode_s *vmode_g, int val) return -1; }
+int +stdvga_get_linesize(struct vgamode_s *vmode_g) +{ + return DIV_ROUND_UP(vmode_g->width * vga_bpp(vmode_g), 8); +}
/**************************************************************** * Save/Restore state diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index facad19..724c1ba 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -107,7 +107,7 @@ vbe_104f01(struct bregs *regs) // Basic information about mode. int width = GET_GLOBAL(vmode_g->width); int height = GET_GLOBAL(vmode_g->height); - int linesize = DIV_ROUND_UP(width * vga_bpp(vmode_g), 8); + int linesize = vgahw_get_linesize(vmode_g); SET_FARVAR(seg, info->bytes_per_scanline, linesize); SET_FARVAR(seg, info->xres, width); SET_FARVAR(seg, info->yres, height); diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index dab2b4d..5839643 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -139,4 +139,14 @@ static inline int vgahw_save_restore(int cmd, u16 seg, void *data) { return stdvga_save_restore(cmd, seg, data); }
+static inline int vgahw_get_linesize(struct vgamode_s *vmode_g) { + if (CONFIG_VGA_CIRRUS) + return clext_get_linesize(vmode_g); + if (CONFIG_VGA_BOCHS) + return bochsvga_get_linesize(vmode_g); + if (CONFIG_VGA_COREBOOT) + return cbvga_get_linesize(vmode_g); + return stdvga_get_linesize(vmode_g); +} + #endif // vgahw.h diff --git a/vgasrc/vgautil.h b/vgasrc/vgautil.h index 08c4e8d..4b6f5b9 100644 --- a/vgasrc/vgautil.h +++ b/vgasrc/vgautil.h @@ -17,6 +17,7 @@ int cbvga_get_dacformat(struct vgamode_s *vmode_g); int cbvga_set_dacformat(struct vgamode_s *vmode_g, int val); int cbvga_save_restore(int cmd, u16 seg, void *data); int cbvga_set_mode(struct vgamode_s *vmode_g, int flags); +int cbvga_get_linesize(struct vgamode_s *vmode_g); int cbvga_setup(void);
// clext.c @@ -30,6 +31,7 @@ int clext_get_displaystart(struct vgamode_s *vmode_g); int clext_set_displaystart(struct vgamode_s *vmode_g, int val); int clext_save_restore(int cmd, u16 seg, void *data); int clext_set_mode(struct vgamode_s *vmode_g, int flags); +int clext_get_linesize(struct vgamode_s *vmode_g); struct bregs; void clext_1012(struct bregs *regs); int clext_setup(void); @@ -63,6 +65,7 @@ void stdvga_list_modes(u16 seg, u16 *dest, u16 *last); void stdvga_build_video_param(void); void stdvga_override_crtc(int mode, u8 *crtc); int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); +int stdvga_get_linesize(struct vgamode_s *vmode_g); void stdvga_set_packed_palette(void);
// swcursor.c
On Fri, Mar 17, 2017 at 05:49:40PM +0100, Patrick Rudolph wrote:
Query the driver for the real scanline pitch in bytes.
As cbvga doesn't change the pitch on mode change, always return the same pitch, that might exceed width times Bytes-per-pixel.
Signed-off-by: Patrick Rudolph siro@das-labor.org
vgasrc/bochsvga.c | 5 +++++ vgasrc/bochsvga.h | 1 + vgasrc/cbvga.c | 7 +++++++ vgasrc/clext.c | 5 +++++ vgasrc/stdvga.c | 5 +++++ vgasrc/vbe.c | 2 +- vgasrc/vgahw.h | 10 ++++++++++ vgasrc/vgautil.h | 3 +++ 8 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index ec5d101..458b3a8 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -310,6 +310,11 @@ bochsvga_save_restore(int cmd, u16 seg, void *data) return ret + (VBE_DISPI_INDEX_Y_OFFSET-VBE_DISPI_INDEX_XRES+1)*sizeof(u16); }
+int +bochsvga_get_linesize(struct vgamode_s *vmode_g) +{
- return DIV_ROUND_UP(vmode_g->width * vga_bpp(vmode_g), 8);
+}
/****************************************************************
- Mode setting
diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index ae5f75d..40ce6f1 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -52,6 +52,7 @@ int bochsvga_get_dacformat(struct vgamode_s *vmode_g); int bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val); int bochsvga_save_restore(int cmd, u16 seg, void *data); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags); +int bochsvga_get_linesize(struct vgamode_s *vmode_g); int bochsvga_setup(void);
#endif // bochsvga.h diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c index 87ec77e..50e6e69 100644 --- a/vgasrc/cbvga.c +++ b/vgasrc/cbvga.c @@ -123,6 +123,13 @@ cbvga_set_mode(struct vgamode_s *vmode_g, int flags) return 0; }
+int +cbvga_get_linesize(struct vgamode_s *vmode_g) +{
- /* Can't change mode, always report active pitch. */
- return GET_GLOBAL(CBlinelength);
+}
#define CB_TAG_FRAMEBUFFER 0x0012 struct cb_framebuffer { u32 tag; diff --git a/vgasrc/clext.c b/vgasrc/clext.c index da8b790..08bc9b5 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -376,6 +376,11 @@ clext_save_restore(int cmd, u16 seg, void *data) return stdvga_save_restore(cmd, seg, data); }
+int +clext_get_linesize(struct vgamode_s *vmode_g) +{
- return DIV_ROUND_UP(vmode_g->width * vga_bpp(vmode_g), 8);
+}
/****************************************************************
- Mode setting
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 886deca..0e24297 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -321,6 +321,11 @@ stdvga_set_dacformat(struct vgamode_s *vmode_g, int val) return -1; }
+int +stdvga_get_linesize(struct vgamode_s *vmode_g) +{
- return DIV_ROUND_UP(vmode_g->width * vga_bpp(vmode_g), 8);
+}
/****************************************************************
- Save/Restore state
diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index facad19..724c1ba 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -107,7 +107,7 @@ vbe_104f01(struct bregs *regs) // Basic information about mode. int width = GET_GLOBAL(vmode_g->width); int height = GET_GLOBAL(vmode_g->height);
- int linesize = DIV_ROUND_UP(width * vga_bpp(vmode_g), 8);
- int linesize = vgahw_get_linesize(vmode_g); SET_FARVAR(seg, info->bytes_per_scanline, linesize); SET_FARVAR(seg, info->xres, width); SET_FARVAR(seg, info->yres, height);
diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index dab2b4d..5839643 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -139,4 +139,14 @@ static inline int vgahw_save_restore(int cmd, u16 seg, void *data) { return stdvga_save_restore(cmd, seg, data); }
+static inline int vgahw_get_linesize(struct vgamode_s *vmode_g) {
- if (CONFIG_VGA_CIRRUS)
return clext_get_linesize(vmode_g);
- if (CONFIG_VGA_BOCHS)
return bochsvga_get_linesize(vmode_g);
- if (CONFIG_VGA_COREBOOT)
return cbvga_get_linesize(vmode_g);
- return stdvga_get_linesize(vmode_g);
+}
Minor nit - I think it would be preferable if this was:
static inline int vgahw_get_linesize(struct vgamode_s *vmode_g) { if (CONFIG_VGA_COREBOOT) return cbvga_get_linesize(vmode_g); return stdvga_get_linesize(vmode_g); }
to reduce the duplicate code in the cirrus/bochs implementations.
Thanks. -Kevin
As coreboot framebuffer is immutable always use CBmodeinfo.
Signed-off-by: Patrick Rudolph siro@das-labor.org --- vgasrc/cbvga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c index 50e6e69..4c349c5 100644 --- a/vgasrc/cbvga.c +++ b/vgasrc/cbvga.c @@ -113,7 +113,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);
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@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); } }
Hi Patrick,
On 03/17/2017 01:49 PM, 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.
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@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
static "const" 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);
}
}
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