[SeaBIOS] [PATCH 04/13] post: Export functions which will be used individually by CSM

Kevin O'Connor kevin at koconnor.net
Tue Feb 5 06:52:50 CET 2013


On Sat, Feb 02, 2013 at 07:32:42PM -0500, Kevin O'Connor wrote:
> I'm not sure how to best address this.  One way is to go forward and
> sprinkle VISIBLE32INIT.  Another way would be to revert patch 1, pass
> a function pointer to reloc_preinit() instead of hard-coding maininit,
> and teach the CSM code how to "longjmp" back to UEFI after relocation
> so it doesn't have to unwind the stack.  I'm not sure that would be
> any less "ugly" though.

FYI, below is one way to "longjmp" back to UEFI without unwinding the
stack (based on your latest git tree and totally untested).  This
assumes it is okay to clobber %fs, %gs and the gdt.

-Kevin


diff --git a/src/csm.c b/src/csm.c
index a773f0d..ee14486 100644
--- a/src/csm.c
+++ b/src/csm.c
@@ -67,6 +67,14 @@ void handle_csm_0000(struct bregs *regs)
     csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
 
     regs->ax = 0;
+
+    // Return directly to UEFI instead of unwinding stack.
+    extern void csm_return();
+    asm volatile(
+        "  jmp transition16"
+        : : "d"((u32)csm_return - BUILD_BIOS_ADDR), "S"(regs->code.seg)
+          , "b"((u32)regs - (regs->code.seg << 4))
+        : "memory");
 }
 
 /* Legacy16UpdateBbs */
diff --git a/src/romlayout.S b/src/romlayout.S
index 420bf4e..98f2b11 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -470,37 +470,48 @@ irqentryarg:
 
         EXPORTFUNC entry_csm16
 entry_csm16:
+        // Backup register state
+        pushfw
+        cli
+        cld
+        pushl %eax                      // dummy
         PUSHBREGS
 
-        // Reset stack and store EFI's old SS:SP on it
-        movl %esp, %edx
-        movw %ss, %cx
+        // Backup stack location
+        movl %ss, %esi
+        movl %esp, %ebx
+        movl %esi, BREGS_code+2(%esp)   // Also store %ss in bregs->code.seg
 
+        // Change to BUILD_STACK_ADDR stack
         xorl %eax, %eax
-        movw %ax, %ss
         movw %ax, %ds
+        movw %ax, %ss
         movl $BUILD_STACK_ADDR, %esp
 
-        pushl %ecx // EFI's SS
-        pushl %edx // EFI's SP
+        // Turn %eax into a flat pointer of struct bregs
+        movl %esi, %eax
+        shll $4, %eax
+        addl %ebx, %eax
 
-        // Turn %edx into a flat pointer (including segment base)
-        shll $4, %ecx
-        addl %ecx, %edx
-
-        // call32(handle_csm32, bregs, -1)
-        movl $_cfunc32flat_handle_csm32, %eax
-        movl $-1, %ecx
-        calll call32
+        // Jump to 32bit mode and call handle_csm32(bregs)
+        movl $(1f + BUILD_BIOS_ADDR), %edx
+        jmp transition32
+        .code32
+1:      calll _cfunc32flat_handle_csm32
+        movl $csm_return, %edx
+        jmp transition16
+        .code16gcc
 
-        // Switch back to EFI's stack and return
-        popl %edx
-        popl %ecx
-        movw %cx, %ss
-        movw %cx, %ds
-        movl %edx, %esp
+        .global csm_return
+csm_return:
+        // Switch back to original stack
+        movl %esi, %ss
+        movl %ebx, %esp
 
+        // Restore register state and return.
         POPBREGS
+        addw $4, %sp                    // pop dummy
+        popfw
         lretw
 
         // int 18/19 are special - they reset stack and call into 32bit mode.



More information about the SeaBIOS mailing list