[SeaBIOS] [PATCH 5/6] Support call16() calls after entering 32bit mode from call32().

Kevin O'Connor kevin at koconnor.net
Thu Oct 3 03:40:34 CEST 2013


When transitioning to 32bit via call32() track the stack segment
register and support restoring it on call16() requests.  This permits
call16() to work properly.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/romlayout.S | 16 +++++++++++++++-
 src/stacks.c    | 20 ++++++++++++++------
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/src/romlayout.S b/src/romlayout.S
index 8415c9f..9de91a2 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -146,9 +146,23 @@ __call16big:
 
         // Make call.
         .code16gcc
-1:      popl %ecx
+1:      movl $_zonelow_seg, %edx        // Adjust %ds, %ss, and %esp
+        movl %edx, %ds
+        movzwl StackSeg, %edx
+        movl %edx, %ecx
+        shll $4, %ecx
+        movl %edx, %ss
+        subl %ecx, %esp
+        movl %edx, %ds
+
+        popl %ecx                       // Call function
         popl %edx
         calll *%ecx
+
+        movl %ss, %edx                  // Readjust %esp
+        shll $4, %edx
+        addl %edx, %esp
+
         // Return via transition32
         movl $(2f + BUILD_BIOS_ADDR), %edx
         jmp transition32
diff --git a/src/stacks.c b/src/stacks.c
index 563ce1c..78ad65c 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -13,6 +13,8 @@
 #include "stacks.h" // struct mutex_s
 #include "util.h" // useRTC
 
+#define MAIN_STACK_MAX (1024*1024)
+
 
 /****************************************************************
  * Extra 16bit stack
@@ -107,6 +109,8 @@ static inline void lgdt(struct descloc_s *desc) {
     asm("lgdtl %0" : : "m"(*desc) : "memory");
 }
 
+u16 StackSeg VARLOW;
+
 // Call a 32bit SeaBIOS function from a 16bit SeaBIOS function.
 u32 VISIBLE16
 call32(void *func, u32 eax, u32 errret)
@@ -127,6 +131,8 @@ call32(void *func, u32 eax, u32 errret)
     struct descloc_s gdt;
     sgdt(&gdt);
 
+    u16 oldstackseg = GET_LOW(StackSeg);
+    SET_LOW(StackSeg, GET_SEG(SS));
     u32 bkup_ss, bkup_esp;
     asm volatile(
         // Backup ss/esp / set esp to flat stack location
@@ -153,6 +159,8 @@ call32(void *func, u32 eax, u32 errret)
         : "r" (func)
         : "ecx", "edx", "cc", "memory");
 
+    SET_LOW(StackSeg, oldstackseg);
+
     // Restore gdt and fs/gs
     lgdt(&gdt);
     SET_SEG(FS, fs);
@@ -169,7 +177,7 @@ static inline u32
 call16(u32 eax, u32 edx, void *func)
 {
     ASSERT32FLAT();
-    if (getesp() > BUILD_STACK_ADDR)
+    if (getesp() > MAIN_STACK_MAX)
         panic("call16 with invalid stack\n");
     extern u32 __call16(u32 eax, u32 edx, void *func);
     return __call16(eax, edx, func - BUILD_BIOS_ADDR);
@@ -179,7 +187,7 @@ static inline u32
 call16big(u32 eax, u32 edx, void *func)
 {
     ASSERT32FLAT();
-    if (getesp() > BUILD_STACK_ADDR)
+    if (getesp() > MAIN_STACK_MAX)
         panic("call16big with invalid stack\n");
     extern u32 __call16big(u32 eax, u32 edx, void *func);
     return __call16big(eax, edx, func - BUILD_BIOS_ADDR);
@@ -214,14 +222,14 @@ farcall16(struct bregs *callregs)
         return;
     }
     extern void _cfunc16__farcall16(void);
-    call16((u32)callregs, 0, _cfunc16__farcall16);
+    call16((u32)callregs - StackSeg * 16, StackSeg, _cfunc16__farcall16);
 }
 
 inline void
 farcall16big(struct bregs *callregs)
 {
     extern void _cfunc16__farcall16(void);
-    call16big((u32)callregs, 0, _cfunc16__farcall16);
+    call16big((u32)callregs - StackSeg * 16, StackSeg, _cfunc16__farcall16);
 }
 
 // Invoke a 16bit software interrupt.
@@ -265,7 +273,7 @@ struct thread_info *
 getCurThread(void)
 {
     u32 esp = getesp();
-    if (esp <= BUILD_STACK_ADDR)
+    if (esp <= MAIN_STACK_MAX)
         return &MainThread;
     return (void*)ALIGN_DOWN(esp, THREADSTACKSIZE);
 }
@@ -477,7 +485,7 @@ int
 wait_preempt(void)
 {
     if (MODESEGMENT || !CONFIG_THREAD_OPTIONROMS || !CanPreempt
-        || getesp() < 1024*1024)
+        || getesp() < MAIN_STACK_MAX)
         return 0;
     while (CanPreempt)
         yield();
-- 
1.8.3.1




More information about the SeaBIOS mailing list