summaryrefslogtreecommitdiff
path: root/vgasrc
diff options
context:
space:
mode:
authorPatrick Rudolph <siro@das-labor.org>2017-05-29 19:25:14 +0200
committerKevin O'Connor <kevin@koconnor.net>2017-06-12 15:25:12 -0400
commite30d51cc58065513279cbe3288108555240e7c44 (patch)
tree0bd32a84772ef644f1d39201c1fccdb241b05395 /vgasrc
parent6b69446de71a6f8a472798a38c08881ec42a8518 (diff)
downloadqemu-seabios-e30d51cc58065513279cbe3288108555240e7c44.tar.gz
SeaVGABios/cbvga: Advertise compatible VESA modes
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>
Diffstat (limited to 'vgasrc')
-rw-r--r--vgasrc/cbvga.c104
1 files changed, 103 insertions, 1 deletions
diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
index 4b7cd0e..f85989a 100644
--- a/vgasrc/cbvga.c
+++ b/vgasrc/cbvga.c
@@ -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;
}