[SeaBIOS] [WIP PATCH 3/3] Add initial CSM support

David Woodhouse dwmw2 at infradead.org
Thu Jan 17 22:50:45 CET 2013


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...

Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 Makefile        |   2 +-
 src/Kconfig     |   7 +++
 src/csm.c       | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/post.c      |   3 ++
 src/romlayout.S |   7 +++
 src/shadow.c    |   6 +--
 6 files changed, 163 insertions(+), 4 deletions(-)
 create mode 100644 src/csm.c

diff --git a/Makefile b/Makefile
index f28d86c..cb8ecdf 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ SRCBOTH=misc.c stacks.c pmm.c output.c util.c block.c floppy.c ata.c mouse.c \
     pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \
     usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \
     virtio-ring.c virtio-pci.c virtio-blk.c virtio-scsi.c apm.c ahci.c \
-    usb-uas.c lsi-scsi.c esp-scsi.c megasas.c
+    usb-uas.c lsi-scsi.c esp-scsi.c megasas.c csm.c
 SRC16=$(SRCBOTH) system.c disk.c font.c
 SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
     acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
diff --git a/src/Kconfig b/src/Kconfig
index 0b112ed..f35b0f5 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -27,6 +27,13 @@ endchoice
         help
             Configure to be used by xen hvmloader, for a HVM guest.
 
+    config CSM
+       bool "Build as Compatibilty Support Module for EFI BIOS"
+       default n
+       help
+           Configure to be used by EFI firmware as Compatibility Support
+           module (CSM) to provide legacy BIOS services.
+
     config THREADS
         bool "Parallelize hardware init"
         default y
diff --git a/src/csm.c b/src/csm.c
new file mode 100644
index 0000000..7ff173b
--- /dev/null
+++ 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"
+#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
+
+extern void handle_post(void);
+extern void _cfunc32flat_handle_csm16(struct bregs *);
+
+EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table;
+EFI_TO_COMPATIBILITY16_BOOT_TABLE *csm_boot_table;
+
+/* 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);
+	dprintf(3, "HiPmmMemorySize %08x\n", csm_init_table->HiPmmMemorySizeInBytes);
+	dprintf(3, "ReverseThunk    %04x:%04x\n", csm_init_table->ReverseThunkCallSegment,
+		csm_init_table->ReverseThunkCallOffset);
+	dprintf(3, "NumE820Entries  %08x\n", csm_init_table->NumberE820Entries);
+	dprintf(3, "OsMemoryAbove1M %08x\n", csm_init_table->OsMemoryAbove1Mb);
+	dprintf(3, "ThunkStart      %08x\n", csm_init_table->ThunkStart);
+	dprintf(3, "ThunkSize       %08x\n", csm_init_table->ThunkSizeInBytes);
+	dprintf(3, "LoPmmMemory     %08x\n", csm_init_table->LowPmmMemory);
+	dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes);
+
+	handle_post();
+	regs->ax = 0;
+}
+
+/* Legacy16UpdateBbs */
+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);
+//	dprintf(3, "SioData %08x\n", csm_boot_table->SioData);
+	dprintf(3, "DevicePathType %04x\n", csm_boot_table->DevicePathType);
+	dprintf(3, "PciIrqMask %04x\n", csm_boot_table->PciIrqMask);
+	dprintf(3, "NumberE820Entries %08x\n", csm_boot_table->NumberE820Entries);
+//	dprintf(3, "HddInfo %08x\n", csm_boot_table->HddInfo);
+	dprintf(3, "NumberBbsEntries %08x\n", csm_boot_table->NumberBbsEntries);
+	dprintf(3, "BBsTable %08x\n", csm_boot_table->BbsTable);
+	dprintf(3, "SmmTable %08x\n", csm_boot_table->SmmTable);
+	dprintf(3, "OsMemoryAbove1Mb %08x\n", csm_boot_table->OsMemoryAbove1Mb);
+	dprintf(3, "UnconventionalDeviceTable %08x\n", csm_boot_table->UnconventionalDeviceTable);
+
+	regs->ax = 0;
+}
+
+/* Legacy16DispatchOprom */
+void handle_csm_0005(struct bregs *regs)
+{
+	EFI_DISPATCH_OPROM_TABLE *rom = MAKE_FLATPTR(regs->es, regs->bx);
+
+	dprintf(3, "Legacy16DispatchOprom rom %p\n", rom);
+
+	dprintf(3, "OpromSegment   %04x\n", rom->OpromSegment);
+	dprintf(3, "RuntimeSegment %04x\n", rom->RuntimeSegment);
+
+	/* FIXME: Actually do it! */
+
+	regs->ax = 0;
+}
+
+/* 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);
+	dprintf(3, "Legacy16GetTableAddress size %x align %x region %d yields %p\n",
+		size, align, region, chunk);
+	if (chunk) {
+		regs->ds = FLATPTR_TO_SEG(chunk);
+		regs->bx = FLATPTR_TO_OFFSET(chunk);
+		regs->ax = 0;
+	} else {
+		regs->ax = 1;
+	}
+}
+
+void __VISIBLE
+handle_csm16(struct bregs *regs)
+{
+	if (MODESEGMENT) {
+		void *flatptr = MAKE_FLATPTR(GET_SEG(SS), regs);
+		call32(_cfunc32flat_handle_csm16, (u32)flatptr, 0);
+		return;
+	}
+	dprintf(3, "handle_csm16 AX=%04x\n", regs->ax);
+
+	switch(regs->ax) {
+	case 0000: handle_csm_0000(regs); break;
+	case 0001: handle_csm_0001(regs); break;
+//	case 0002: handle_csm_0002(regs); break;
+//	case 0003: handle_csm_0003(regs); break;
+//	case 0004: handle_csm_0004(regs); break;
+	case 0005: handle_csm_0005(regs); break;
+	case 0006: handle_csm_0006(regs); break;
+//	case 0007: handle_csm_0007(regs); break;
+//	case 0008: hamdle_csm_0008(regs); break;
+	default: regs->al = 1;
+	}
+
+	dprintf(3, "handle_csm16 returning AX=%04x\n", regs->ax);
+}
diff --git a/src/post.c b/src/post.c
index f3b56b8..dc07e8b 100644
--- a/src/post.c
+++ b/src/post.c
@@ -225,6 +225,9 @@ maininit(void)
     init_ivt();
     init_bda();
 
+    if (CONFIG_CSM)
+	    return;
+
     // Init base pc hardware.
     pic_setup();
     timer_setup();
diff --git a/src/romlayout.S b/src/romlayout.S
index 8125277..f1a276e 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -468,6 +468,13 @@ irqentryarg:
         DECL_IRQ_ENTRY hwpic1
         DECL_IRQ_ENTRY hwpic2
 
+#if CONFIG_CSM
+	EXPORTFUNC entry_csm16
+entry_csm16:
+        ENTRY_ARG handle_csm16
+	iretw
+#endif
+
         // int 18/19 are special - they reset stack and call into 32bit mode.
         DECLFUNC entry_19
 entry_19:
diff --git a/src/shadow.c b/src/shadow.c
index a2195da..881d5a6 100644
--- a/src/shadow.c
+++ b/src/shadow.c
@@ -119,7 +119,7 @@ static const struct pci_device_id dram_controller_make_readonly_tbl[] = {
 void
 make_bios_writable(void)
 {
-    if (CONFIG_COREBOOT || usingXen())
+    if (CONFIG_COREBOOT || CONFIG_CSM || usingXen())
         return;
 
     dprintf(3, "enabling shadow ram\n");
@@ -148,7 +148,7 @@ make_bios_writable(void)
 void
 make_bios_readonly(void)
 {
-    if (CONFIG_COREBOOT || usingXen())
+    if (CONFIG_COREBOOT || CONFIG_CSM || usingXen())
         return;
 
     dprintf(3, "locking shadow ram\n");
@@ -161,7 +161,7 @@ make_bios_readonly(void)
 void
 qemu_prep_reset(void)
 {
-    if (CONFIG_COREBOOT)
+    if (CONFIG_COREBOOT || CONFIG_CSM )
         return;
     // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
     // reset, so do that manually before invoking a hard reset.
-- 
1.8.0.2


-- 
dwmw2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 6171 bytes
Desc: not available
URL: <http://www.seabios.org/pipermail/seabios/attachments/20130117/47003512/attachment.bin>


More information about the SeaBIOS mailing list