aboutsummaryrefslogtreecommitdiff
path: root/src/stacks.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2014-09-29 23:59:47 -0400
committerKevin O'Connor <kevin@koconnor.net>2014-10-11 13:41:39 -0400
commitdcacfa08b2a26e9aac17c52d4015100935bbcb9a (patch)
tree855f49d3f46767515b8bfd9a8655c7183520d054 /src/stacks.c
parent80568256057827956abfd6254a78f11d818ab344 (diff)
downloadseabios-hppa-dcacfa08b2a26e9aac17c52d4015100935bbcb9a.zip
seabios-hppa-dcacfa08b2a26e9aac17c52d4015100935bbcb9a.tar.gz
seabios-hppa-dcacfa08b2a26e9aac17c52d4015100935bbcb9a.tar.bz2
Track when entering via call32() and use the same mode for stack_hop_back()
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>
Diffstat (limited to 'src/stacks.c')
-rw-r--r--src/stacks.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/stacks.c b/src/stacks.c
index 5a2628a..b91b216 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -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();