[SeaBIOS] [PATCH 04/13] post: Export functions which will be used individually by CSM
Kevin O'Connor
kevin at koconnor.net
Tue Feb 5 08:53:42 CET 2013
On Tue, Feb 05, 2013 at 12:52:50AM -0500, Kevin O'Connor wrote:
> 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.
This may be slightly nicer (still totally untested).
-Kevin
diff --git a/src/csm.c b/src/csm.c
index a773f0d..d5ed8ad 100644
--- a/src/csm.c
+++ b/src/csm.c
@@ -36,6 +36,8 @@ EFI_COMPATIBILITY16_TABLE csm_compat_table VAR32FLATVISIBLE __aligned(16) = {
EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table;
EFI_TO_COMPATIBILITY16_BOOT_TABLE *csm_boot_table;
+extern void csm_return(struct bregs *regs) __noreturn;
+
/* Legacy16InitializeYourself */
void handle_csm_0000(struct bregs *regs)
{
@@ -67,6 +69,9 @@ 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.
+ csm_return(regs);
}
/* Legacy16UpdateBbs */
diff --git a/src/romlayout.S b/src/romlayout.S
index 420bf4e..42aeaff 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -469,38 +469,53 @@ irqentryarg:
DECL_IRQ_ENTRY hwpic2
EXPORTFUNC entry_csm16
+ .global csm_return
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 and convert to a "flat pointer"
+ movl %ss, %ebx
+ movw %bx, BREGS_code+2(%esp) // Store %ss in bregs->code.seg
+ shll $4, %ebx
+ addl %esp, %ebx
+ // Change to BUILD_STACK_ADDR stack
xorl %eax, %eax
movw %ax, %ss
- movw %ax, %ds
movl $BUILD_STACK_ADDR, %esp
- pushl %ecx // EFI's SS
- pushl %edx // EFI's SP
-
- // Turn %edx into a flat pointer (including segment base)
- shll $4, %ecx
- addl %ecx, %edx
+ // Jump to 32bit mode and call handle_csm32(bregs)
+ movl $(1f + BUILD_BIOS_ADDR), %edx
+ jmp transition32
+ .code32
+1: movl %ebx, %eax
+ calll _cfunc32flat_handle_csm32
+ movl $2f, %edx
+ jmp transition16big
- // call32(handle_csm32, bregs, -1)
- movl $_cfunc32flat_handle_csm32, %eax
- movl $-1, %ecx
- calll call32
+csm_return:
+ movl %eax, %ebx
+ movl $2f, %edx
+ jmp transition16big
+ .code16gcc
- // Switch back to EFI's stack and return
- popl %edx
- popl %ecx
- movw %cx, %ss
- movw %cx, %ds
- movl %edx, %esp
+ // Switch back to original stack
+2: movzwl BREGS_code+2(%ebx), %eax
+ movl %eax, %ecx
+ shll $4, %ecx
+ subl %ecx, %ebx
+ movl %eax, %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