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.