]> xenbits.xensource.com Git - seabios.git/commitdiff
Track when entering via call32() and use the same mode for stack_hop_back()
authorKevin O'Connor <kevin@koconnor.net>
Tue, 30 Sep 2014 03:59:47 +0000 (23:59 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 11 Oct 2014 17:41:39 +0000 (13:41 -0400)
If 32bit mode is entered directly via transition32, then use a simple
call16() when hopping back to 16bit mode.  Use only call16big() during
post and when entering 32bit mode via call32().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
src/stacks.c

index 5a2628aed96d5c6a2096330eb6318fa337bb6b68..b91b2160181417ebbd244514769bb7b109476c83 100644 (file)
@@ -22,6 +22,8 @@
  ****************************************************************/
 
 u16 StackSeg VARLOW;
+u8 Call32Method VARLOW;
+#define C32_SLOPPY 1
 
 // Call a 32bit SeaBIOS function from a 16bit SeaBIOS function.
 u32 VISIBLE16
@@ -45,6 +47,7 @@ call32(void *func, u32 eax, u32 errret)
 
     u16 oldstackseg = GET_LOW(StackSeg);
     SET_LOW(StackSeg, GET_SEG(SS));
+    SET_LOW(Call32Method, C32_SLOPPY);
     u32 bkup_ss, bkup_esp;
     asm volatile(
         // Backup ss/esp / set esp to flat stack location
@@ -71,6 +74,7 @@ call32(void *func, u32 eax, u32 errret)
         : "r" (func)
         : "ecx", "edx", "cc", "memory");
 
+    SET_LOW(Call32Method, 0);
     SET_LOW(StackSeg, oldstackseg);
 
     // Restore gdt and fs/gs
@@ -95,6 +99,7 @@ call16(u32 eax, u32 edx, void *func)
     return __call16(eax, edx, func - BUILD_BIOS_ADDR);
 }
 
+// Call a 16bit SeaBIOS function in "big real" mode.
 static inline u32
 call16big(u32 eax, u32 edx, void *func)
 {
@@ -105,6 +110,28 @@ call16big(u32 eax, u32 edx, void *func)
     return __call16big(eax, edx, func - BUILD_BIOS_ADDR);
 }
 
+// Jump back to 16bit mode while in 32bit mode from call32()
+static u32
+call16_sloppy(u32 eax, u32 edx, void *func)
+{
+    Call32Method = 0;
+    u32 ret = call16big(eax, edx, func);
+    Call32Method = C32_SLOPPY;
+    return ret;
+}
+
+// Call a 16bit SeaBIOS function, restoring the mode from last call32().
+static u32
+call16_back(u32 eax, u32 edx, void *func)
+{
+    ASSERT32FLAT();
+    if (Call32Method == C32_SLOPPY)
+        return call16_sloppy(eax, edx, func);
+    if (in_post())
+        return call16big(eax, edx, func);
+    return call16(eax, edx, func);
+}
+
 
 /****************************************************************
  * Extra 16bit stack
@@ -159,7 +186,7 @@ u32
 stack_hop_back(u32 eax, u32 edx, void *func)
 {
     if (!MODESEGMENT)
-        return call16big(eax, edx, func);
+        return call16_back(eax, edx, func);
     if (!on_extra_stack())
         return ((u32 (*)(u32, u32))func)(eax, edx);
     ASSERT16();