On Thu, Jan 17, 2013 at 09:50:45PM +0000, David Woodhouse wrote:
Not particularly functional, but it's a start...
Build with CONFIG_CSM enabled (and CONFIG_RELOCATE_INIT disabled) and drop the resulting bios.bin into OvmfPkg/Csm/Csm16/Csm16.bin in your EDK-II build tree, then build with 'build -D CSM_ENABLE'.
You'll see it initialise SeaBIOS as a CSM as it's starting up, and then crash in a storm of what Qemu's debug log says is 'hardware INT=0x68'... which I suppose is what I have to debug next...
Very interesting.
BTW, we're about to make a SeaBIOS release - this patch and your other patches would be something to look at for the next release.
[...]
+++ b/src/csm.c @@ -0,0 +1,142 @@ +// CSM table generation (for providing legacy BIOS support to EFI) +// +// Copyright © 2012 Intel Corporation +// +// This file may be distributed under the terms of the GNU LGPLv3 license.
+#include "config.h" // CONFIG_* +#include "csm.h"
Looks like you forgot to include csm.h in the patch.
+#include "util.h" // checksum +#include "bregs.h"
+#if CONFIG_CSM +extern void entry_csm16(void); +EFI_COMPATIBILITY16_TABLE csm_compat_table VAR16EXPORT __aligned(16) = {
- .Signature = 0x24454649,
- .TableChecksum = 0 /* Filled in by checkrom.py */,
- .TableLength = sizeof(csm_compat_table),
- .Compatibility16CallSegment = SEG_BIOS,
- .Compatibility16CallOffset = 0 /* Filled in by checkrom.py */,
- .OemIdStringPointer = (u32)"SeaBIOS",
+}; +#endif
Does this table have to be in the f-segment, or can it be anywhere in the binary? BTW, how does OVMF know where to place the seabios blob in memory?
+/* Legacy16InitializeYourself */ +void handle_csm_0000(struct bregs *regs) +{
dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es,
regs->bx);
csm_init_table = MAKE_FLATPTR(regs->es, regs->bx);
dprintf(3, "BiosLessThan1MB %08x\n", csm_init_table->BiosLessThan1MB);
dprintf(3, "HiPmmMemory %08x\n", csm_init_table->HiPmmMemory);
[...] +void handle_csm_0001(struct bregs *regs) +{ + dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx); + + csm_boot_table = MAKE_FLATPTR(regs->es, regs->bx); + dprintf(3, "MajorVersion %04x\n", csm_boot_table->MajorVersion); + dprintf(3, "MinorVersion %04x\n", csm_boot_table->MinorVersion); + dprintf(3, "AcpiTable %08x\n", csm_boot_table->AcpiTable); + dprintf(3, "SmbiosTable %08x\n", csm_boot_table->SmbiosTable); + dprintf(3, "SmbiosTableLength %08x\n", csm_boot_table->SmbiosTableLength);
Are these values that SeaBIOS is expected to fill, or values from EFI that SeaBIOS is expected to utilize? In either case it shouldn't be difficult to wire them into SeaBIOS' existing structures. I'd need to see csm.h to confirm, but it mostly looks like it requires some function calls and variable assignments.
[...]
+/* Legacy16GetTableAddress */ +void handle_csm_0006(struct bregs *regs) +{
- u16 size = regs->cx;
- u16 align = regs->dx;
- u16 region = regs->bx; // (1 for F000 seg, 2 for E000 seg, 0 for either)
- void *chunk;
- /* FIXME: I don't know if we can allocate in the E000 segment at all. */
- dprintf(3, "Legacy16GetTableAddress size %x align %x region %d\n",
size, align, region);
- chunk = pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, align);
This is the same as malloc_fseg(). Allocating in the e-segment is done by calling malloc_low(). Is the align guarenteed to be a power of 2 - if not it may mess up SeaBIOS' allocator.
+void __VISIBLE +handle_csm16(struct bregs *regs) +{
- if (MODESEGMENT) {
void *flatptr = MAKE_FLATPTR(GET_SEG(SS), regs);
call32(_cfunc32flat_handle_csm16, (u32)flatptr, 0);
BTW, SeaBIOS uses 4 space indentation and no tabs.
-Kevin