[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