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