[SeaBIOS] [PATCH v2 00/19] SeaBIOS as Compatibility Support Module for UEFI/OVMF

Kevin O'Connor kevin at koconnor.net
Wed Feb 6 05:14:25 CET 2013


On Tue, Feb 05, 2013 at 04:47:39PM +0000, David Woodhouse wrote:
> Changes from v1:
>  - Make CONFIG_CSM a top-level build target in parallel with COREBOOT/QEMU.
>  - More Kconfig cleanup.
>  - Add generic find_pmtimer() function to find the pmtimer from ACPI tables.
>  - Make Xen and coreboot builds both use find_pmtimer().
>  - Merge E820 table one entry at a time instead of wholesale copy.
>  - Add pic_save_mask() and pic_restore_mask() functions.
>  - Less intrusive size reduction for handle_post().
>  - Various other cleanups.

Thanks.  I pushed patches 2, 3, 5, and 11.

I think the reloc_init() change that I wrote (patch 1) may have been a
mistake because of the VISIBLE32INIT proliferation that it causes.  I
put together an alternate approach which requires csm_return().  I
still need to get an OVMF environment up to test this - I'll do that
tomorrow.  The main idea is in the attached patches.

I also rebased the above changes (with just the key csm parts) and
pushed the series to a test location at:
https://github.com/KevinOConnor/seabios/tree/csm-test-20130205
(This also has some changes to patch 14.)

-Kevin
-------------- next part --------------
commit 551cac53c4dd3282b3407c8440c9446e27220f37
Author: Kevin O'Connor <kevin at koconnor.net>
Date:   Tue Feb 5 20:57:10 2013 -0500

    Support calling a function other than maininit() from reloc_preinit().
    
    Pass a function pointer to reloc_preinit() instead of always running
    maininit() after relocating the init code.
    
    Signed-off-by: Kevin O'Connor <kevin at koconnor.net>

diff --git a/src/post.c b/src/post.c
index 4b04740..7df021e 100644
--- a/src/post.c
+++ b/src/post.c
@@ -331,14 +331,15 @@ updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta)
         *((u32*)(dest + *reloc)) += delta;
 }
 
-// Relocate init code and then call maininit() at new address.
-static void
-reloc_preinit(void)
+// Relocate init code and then call a function at its new address.
+// The passed function should be in the "init" section and must not
+// return.
+static void __noreturn
+reloc_preinit(void *f, void *arg)
 {
-    if (!CONFIG_RELOCATE_INIT) {
-        maininit();
-        return;
-    }
+    void (*func)(void *) __noreturn = f;
+    if (!CONFIG_RELOCATE_INIT)
+        func(arg);
     // Symbols populated by the build.
     extern u8 code32flat_start[];
     extern u8 _reloc_min_align;
@@ -368,11 +369,12 @@ reloc_preinit(void)
     updateRelocs(codedest, _reloc_abs_start, _reloc_abs_end, delta);
     updateRelocs(codedest, _reloc_rel_start, _reloc_rel_end, -delta);
     updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta);
+    if (f >= (void*)code32init_start && f < (void*)code32init_end)
+        func = f + delta;
 
-    // Call maininit() in relocated code.
-    void (*func)(void) = (void*)maininit + delta;
+    // Call function in relocated code.
     barrier();
-    func();
+    func(arg);
 }
 
 // Setup for code relocation and then call reloc_init
@@ -387,7 +389,7 @@ dopost(void)
     malloc_preinit();
 
     // Relocate initialization code and call maininit().
-    reloc_preinit();
+    reloc_preinit(maininit, NULL);
 }
 
 // Entry point for Power On Self Test (POST) - the BIOS initilization
-------------- next part --------------
commit 1f5100ec76c4468eab264a594bf8cd452b64a740
Author: Kevin O'Connor <kevin at koconnor.net>
Date:   Tue Feb 5 21:21:26 2013 -0500

    Modify CSM code for non-returning reloc_preinit system.
    
    Signed-off-by: Kevin O'Connor <kevin at koconnor.net>

diff --git a/src/csm.c b/src/csm.c
index c453ebd..473d322 100644
--- a/src/csm.c
+++ b/src/csm.c
@@ -34,8 +34,26 @@ 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;
+
+static void
+csm_maininit(struct bregs *regs)
+{
+    interface_init();
+    timer_setup();
+    pci_probe_devices();
+
+    csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS;
+    csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
+
+    regs->ax = 0;
+
+    // Return directly to UEFI instead of unwinding stack.
+    csm_return(regs);
+}
+
 /* Legacy16InitializeYourself */
-void
+static void
 handle_csm_0000(struct bregs *regs)
 {
     dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es,
@@ -59,19 +77,11 @@ handle_csm_0000(struct bregs *regs)
                        csm_init_table->LowPmmMemorySizeInBytes,
                        csm_init_table->HiPmmMemory,
                        csm_init_table->HiPmmMemorySizeInBytes);
-    reloc_preinit();
-    interface_init();
-    timer_setup();
-    pci_probe_devices();
-
-    csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS;
-    csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
-
-    regs->ax = 0;
+    reloc_preinit(csm_maininit, regs);
 }
 
 /* Legacy16UpdateBbs */
-void VISIBLE32INIT
+static void
 handle_csm_0001(struct bregs *regs)
 {
     dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx);
@@ -97,7 +107,7 @@ handle_csm_0001(struct bregs *regs)
 }
 
 /* PrepareToBoot */
-void VISIBLE32INIT
+static void
 handle_csm_0002(struct bregs *regs)
 {
     dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx);
@@ -151,7 +161,7 @@ handle_csm_0002(struct bregs *regs)
 }
 
 /* Boot */
-void VISIBLE32INIT
+static void
 handle_csm_0003(struct bregs *regs)
 {
     dprintf(3, "Boot\n");
@@ -162,7 +172,7 @@ handle_csm_0003(struct bregs *regs)
 }
 
 /* Legacy16DispatchOprom */
-void VISIBLE32INIT
+static void
 handle_csm_0005(struct bregs *regs)
 {
     EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx);
@@ -191,7 +201,7 @@ handle_csm_0005(struct bregs *regs)
 }
 
 /* Legacy16GetTableAddress */
-void VISIBLE32INIT
+static void
 handle_csm_0006(struct bregs *regs)
 {
     u16 size = regs->cx;
@@ -221,7 +231,7 @@ handle_csm_0006(struct bregs *regs)
     }
 }
 
-void VISIBLE32FLAT
+void VISIBLE32INIT
 handle_csm(struct bregs *regs)
 {
     ASSERT32FLAT();
diff --git a/src/romlayout.S b/src/romlayout.S
index aebe2df..07d1645 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -385,38 +385,53 @@ entry_elf:
         .code16gcc
 
         EXPORTFUNC entry_csm
+        .global csm_return
 entry_csm:
+        // 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_csm
+        movl $2f, %edx
+        jmp transition16big
 
-        // call32(handle_csm32, bregs, -1)
-        movl $_cfunc32flat_handle_csm, %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
 
 


More information about the SeaBIOS mailing list