]> xenbits.xensource.com Git - seabios.git/commitdiff
Fix winxp boot regression introduced in ecdc655a.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 3 Jun 2012 00:30:58 +0000 (20:30 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 3 Jun 2012 00:30:58 +0000 (20:30 -0400)
The winxp boot loader does something curious - it sets an int 0x1c
handler, records the stack location, and then spins in place with irqs
enabled.  The 0x1c handler alters the memory just past the stack
pointer so that when the timer irq returns the code jumps to a new
location and stop spinning.  The winxp code relies on the fact that a
hw irq will always place 6 bytes at a specific location and that it
can alter those bytes.

The ecdc655a patch does a full backup/restore of the register state.
Unfortunately, the restore overwrites the changes made by the winxp
0x1c handler.

This patch reverts much of ecdc655a.  Hardware irqs are still handled
on the extra stack, but only the essential register state is backed up
and restored.

Also, stack_hop_back is changed to only use %sp when changing states -
this enables the entry code to store just %esp instead of both %esp
and %sp.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
src/clock.c
src/disk.c
src/floppy.c
src/misc.c
src/output.c
src/ps2port.c
src/romlayout.S
src/stacks.c
src/util.h

index 55dde2e88569efeb4373e26c07d137af6fb702d4..69e9f178beb73f492951c11d1bcd7ac01cdb6213 100644 (file)
@@ -516,9 +516,9 @@ handle_1a(struct bregs *regs)
 
 // INT 08h System Timer ISR Entry Point
 void VISIBLE16
-handle_08(struct bregs *regs)
+handle_08(void)
 {
-    debug_enter(regs, DEBUG_ISR_08);
+    debug_isr(DEBUG_ISR_08);
 
     floppy_tick();
 
@@ -659,9 +659,9 @@ handle_1583(struct bregs *regs)
 
 // int70h: IRQ8 - CMOS RTC
 void VISIBLE16
-handle_70(struct bregs *regs)
+handle_70(void)
 {
-    debug_enter(regs, DEBUG_ISR_70);
+    debug_isr(DEBUG_ISR_70);
 
     // Check which modes are enabled and have occurred.
     u8 registerB = inb_cmos(CMOS_STATUS_B);
index 3ca56971e31802adb7bcad6a469a2c3d19cc826e..8eff46479cf317f6077902d67868aa769e3e5eeb 100644 (file)
@@ -885,9 +885,9 @@ handle_13(struct bregs *regs)
 
 // record completion in BIOS task complete flag
 void VISIBLE16
-handle_76(struct bregs *regs)
+handle_76(void)
 {
-    debug_enter(regs, DEBUG_ISR_76);
+    debug_isr(DEBUG_ISR_76);
     SET_BDA(disk_interrupt_flag, 0xff);
     eoi_pic2();
 }
index 5400bb02224f0eff37bb384b977290fc87435ad6..72bc79b8f4984638e0d63e04f9acbf4c407d3328 100644 (file)
@@ -582,9 +582,9 @@ process_floppy_op(struct disk_op_s *op)
 
 // INT 0Eh Diskette Hardware ISR Entry Point
 void VISIBLE16
-handle_0e(struct bregs *regs)
+handle_0e(void)
 {
-    debug_enter(regs, DEBUG_ISR_0e);
+    debug_isr(DEBUG_ISR_0e);
     if (! CONFIG_FLOPPY)
         goto done;
 
index d0d66656069a922a2e22071ac0b0f8e10bcabee0..b9487785e4cde34f963c0bada0066a0d71308467 100644 (file)
@@ -55,9 +55,9 @@ handle_10(struct bregs *regs)
 
 // NMI handler
 void VISIBLE16
-handle_02(struct bregs *regs)
+handle_02(void)
 {
-    debug_enter(regs, DEBUG_ISR_02);
+    debug_isr(DEBUG_ISR_02);
 }
 
 void
@@ -71,9 +71,9 @@ mathcp_setup(void)
 
 // INT 75 - IRQ13 - MATH COPROCESSOR EXCEPTION
 void VISIBLE16
-handle_75(struct bregs *regs)
+handle_75(void)
 {
-    debug_enter(regs, DEBUG_ISR_75);
+    debug_isr(DEBUG_ISR_75);
 
     // clear irq13
     outb(0, PORT_MATH_CLEAR);
index 1fe5d919fc57997110a68ad0e0e28136c2fa8d5e..37c4942eddd482828694865d021ff61547359d3f 100644 (file)
@@ -487,6 +487,15 @@ dump_regs(struct bregs *regs)
             , regs->code.seg, regs->code.offset, regs->flags);
 }
 
+// Report entry to an Interrupt Service Routine (ISR).
+void
+__debug_isr(const char *fname)
+{
+    puts_cs(&debuginfo, fname);
+    putc(&debuginfo, '\n');
+    debug_serial_flush();
+}
+
 // Function called on handler startup.
 void
 __debug_enter(struct bregs *regs, const char *fname)
index 601e40d5e997329af470ae66b6e37cde96c4a1d1..d4626d69374fe8ae3de2b1b9f3dc520e9288f630 100644 (file)
@@ -356,12 +356,12 @@ ps2_mouse_command(int command, u8 *param)
 
 // INT74h : PS/2 mouse hardware interrupt
 void VISIBLE16
-handle_74(struct bregs *regs)
+handle_74(void)
 {
     if (! CONFIG_PS2PORT)
         return;
 
-    debug_enter(regs, DEBUG_ISR_74);
+    debug_isr(DEBUG_ISR_74);
 
     u8 v = inb(PORT_PS2_STATUS);
     if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
@@ -383,12 +383,12 @@ done:
 
 // INT09h : Keyboard Hardware Service Entry Point
 void VISIBLE16
-handle_09(struct bregs *regs)
+handle_09(void)
 {
     if (! CONFIG_PS2PORT)
         return;
 
-    debug_enter(regs, DEBUG_ISR_09);
+    debug_isr(DEBUG_ISR_09);
 
     // read key from keyboard controller
     u8 v = inb(PORT_PS2_STATUS);
index aadc9cf2a66fedeee09163ac88d27819b4bf8bc4..8125277158d9da90926e9fef2330ac19fca69d2f 100644 (file)
@@ -394,48 +394,35 @@ entry_elf:
 irqentry_extrastack:
         cli
         cld
-        pushw %ds
+        pushw %ds               // Set %ds:%eax to space on ExtraStack
         pushl %eax
         movl $_datalow_seg, %eax
         movl %eax, %ds
         movl StackPos, %eax
-        subl $BREGS_size+12, %eax
-        popl BREGS_eax(%eax)
-        popw BREGS_ds(%eax)
-        movl %edi, BREGS_edi(%eax)
-        movl %esi, BREGS_esi(%eax)
-        movl %ebp, BREGS_ebp(%eax)
-        movl %ebx, BREGS_ebx(%eax)
-        movl %edx, BREGS_edx(%eax)
-        movl %ecx, BREGS_ecx(%eax)
-        movw %es, BREGS_es(%eax)
+        subl $24, %eax
+        popl 0(%eax)            // Backup %eax, %ds, %es, %ecx, %edx
+        popw 4(%eax)
+        movw %es, 6(%eax)
+        movl %ecx, 8(%eax)
         popl %ecx
-        popl BREGS_code(%eax)
-        popw BREGS_flags(%eax)
-
-        movw %ss, BREGS_size+8(%eax)
-        movzwl %sp, %edx
-        movl %edx, BREGS_size+4(%eax)
-        movl %esp, BREGS_size+0(%eax)
-        movw %ds, %dx
+        movl %edx, 12(%eax)
+        movl %esp, 16(%eax)
+        movzwl %sp, %esp
+        movw %ss, 20(%eax)
+
+        movw %ds, %dx           // Setup %ss/%esp and call function
         movw %dx, %ss
         movl %eax, %esp
         calll *%ecx
 
-        movl %esp, %eax
-        movw BREGS_size+8(%eax), %ss
-        movl BREGS_size+0(%eax), %esp
-        movl BREGS_edi(%eax), %edi
-        movl BREGS_esi(%eax), %esi
-        movl BREGS_ebp(%eax), %ebp
-        movl BREGS_ebx(%eax), %ebx
-        movl BREGS_edx(%eax), %edx
-        movl BREGS_ecx(%eax), %ecx
-        movw BREGS_es(%eax), %es
-        pushw BREGS_flags(%eax)
-        pushl BREGS_code(%eax)
-        pushw BREGS_ds(%eax)
-        pushl BREGS_eax(%eax)
+        movl %esp, %eax         // Restore registers and return
+        movw 20(%eax), %ss
+        movl 16(%eax), %esp
+        movl 12(%eax), %edx
+        movl 8(%eax), %ecx
+        movw 6(%eax), %es
+        pushw 4(%eax)
+        pushl 0(%eax)
         popl %eax
         popw %ds
         iretw
index 2804e478c60ec14228f1489c4953b53c6e0366a3..938172953e0742b95f561f924a880d84a2d1316b 100644 (file)
@@ -74,7 +74,7 @@ stack_hop_back(u32 eax, u32 edx, void *func)
         // Restore original callers' %ss/%esp
         "movl -4(%4), %5\n"
         "movl %5, %%ss\n"
-        "movl %%ds:-8(%4), %%esp\n"
+        "movw %%ds:-8(%4), %%sp\n"
         "movl %5, %%ds\n"
         // Call func
         "calll *%2\n"
index 39350cc912246b75b721e2a6c563dc0d9ed8303f..ba396781ea5d828ee9774ad37ead70a61b57055f 100644 (file)
@@ -243,6 +243,7 @@ char * znprintf(size_t size, const char *fmt, ...)
 void __dprintf(const char *fmt, ...)
     __attribute__ ((format (printf, 1, 2)));
 void __debug_enter(struct bregs *regs, const char *fname);
+void __debug_isr(const char *fname);
 void __debug_stub(struct bregs *regs, int lineno, const char *fname);
 void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
 void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
@@ -264,6 +265,10 @@ void hexdump(const void *d, int len);
         if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL)       \
             __debug_enter((regs), __func__);            \
     } while (0)
+#define debug_isr(lvl) do {                             \
+        if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL)       \
+            __debug_isr(__func__);                      \
+    } while (0)
 #define debug_stub(regs)                        \
     __debug_stub((regs), __LINE__, __func__)
 #define warn_invalid(regs)                      \