[SeaBIOS] [PATCH 12/13] Add CSM support

David Woodhouse dwmw2 at infradead.org
Mon Jan 28 17:23:45 CET 2013


From: David Woodhouse <David.Woodhouse at intel.com>

Not-yet-signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 Makefile        |   2 +-
 README.CSM      |  20 ++++
 src/Kconfig     |   7 ++
 src/boot.c      |   6 ++
 src/boot.h      |   5 +
 src/csm.c       | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/csm.h       |  13 +++
 src/pirtable.c  |   6 +-
 src/pmm.c       |  19 ++++
 src/romlayout.S |  37 +++++++
 src/util.h      |   1 +
 11 files changed, 425 insertions(+), 4 deletions(-)
 create mode 100644 README.CSM
 create mode 100644 src/csm.c
 create mode 100644 src/csm.h

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/README.CSM b/README.CSM
new file mode 100644
index 0000000..fb4973c
--- /dev/null
+++ b/README.CSM
@@ -0,0 +1,20 @@
+Enabling CONFIG_CSM allows SeaBIOS to be built as a Compatibility Support
+Module for use with the OMVF/EDK-II UEFI firmware.
+
+It will provide "legacy" BIOS services for booting non-EFI operating
+systems and will also allow OVMF to display on otherwise unsupported
+video hardware by using the traditional VGA BIOS.
+
+Windows 2008r2 is known to use INT 10h BIOS calls even when booted via
+EFI, and the presence of a CSM makes this work as expected too.
+
+Having built SeaBIOS with CONFIG_CSM, you should be able to drop the
+result into your OVMF build tree at OvmfPkg/Csm/Csm16/Csm16.bin and
+then build OVMF with 'build -D CSM_ENABLE'. The SeaBIOS binary will be
+included as a discrete file within the 'Flash Volume' which is
+created, and there are tools which will extract it and allow it to be
+replaced; satisfying the requirements of the LGPL licence.
+
+A patch to OVMF is required; see
+http://www.sourceforge.net/mailarchive/forum.php?thread_name=50FD7290.9060003%40redhat.com&forum_name=edk2-devel
+
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/boot.c b/src/boot.c
index 3bafa5a..8899c0b 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -120,6 +120,8 @@ build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
 
 int bootprio_find_pci_device(struct pci_device *pci)
 {
+    if (CONFIG_CSM)
+        return csm_bootprio_pci(pci);
     if (!CONFIG_BOOTORDER)
         return -1;
     // Find pci device - for example: /pci at i0cf8/ethernet at 5
@@ -144,6 +146,8 @@ int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun)
 
 int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
 {
+    if (CONFIG_CSM)
+        return csm_bootprio_ata(pci, chanid, slave);
     if (!CONFIG_BOOTORDER)
         return -1;
     if (!pci)
@@ -158,6 +162,8 @@ int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
 
 int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid)
 {
+    if (CONFIG_CSM)
+        return csm_bootprio_fdc(pci, port, fdid);
     if (!CONFIG_BOOTORDER)
         return -1;
     if (!pci)
diff --git a/src/boot.h b/src/boot.h
index 4d4943b..9c532df 100644
--- a/src/boot.h
+++ b/src/boot.h
@@ -23,4 +23,9 @@ int bootprio_find_named_rom(const char *name, int instance);
 struct usbdevice_s;
 int bootprio_find_usb(struct usbdevice_s *usbdev, int lun);
 
+// csm.c
+int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid);
+int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave);
+int csm_bootprio_pci(struct pci_device *pci);
+
 #endif // __BOOT_H
diff --git a/src/csm.c b/src/csm.c
new file mode 100644
index 0000000..92b2e84
--- /dev/null
+++ b/src/csm.c
@@ -0,0 +1,313 @@
+// Compatibility Support Module (CSM) for UEFI / EDK-II
+//
+// Copyright © 2013 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"
+#include "optionroms.h"
+#include "pci.h"
+#include "memmap.h"
+#include "biosvar.h"
+#include "post.h"
+#include "acpi.h"
+#include "boot.h"
+#include "smbios.h"
+#include "pic.h"
+
+#if CONFIG_CSM
+#define MAX_ACPI2_RSDP_SIZE 36
+
+struct rsdp_descriptor VAR32FLATVISIBLE __aligned(16) csm_rsdp;
+
+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",
+    .AcpiRsdPtrPointer = (u32)&csm_rsdp,
+    .UmbStart = 0xe0,
+    .UmbEnd = 0xf0,
+};
+
+
+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);
+
+    csm_malloc_setup(csm_init_table->LowPmmMemory, 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;
+}
+
+/* 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;
+}
+
+/* PrepareToBoot */
+void handle_csm_0002(struct bregs *regs)
+{
+    dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx);
+
+    /* La la la */
+    dprintf(3, "%d e820 entries (%d bytes)`n", csm_compat_table.E820Length / sizeof(struct e820entry), csm_compat_table.E820Length);
+    memcpy(e820_list, (void *)csm_compat_table.E820Pointer, csm_compat_table.E820Length);
+    e820_count = csm_compat_table.E820Length / sizeof(struct e820entry);
+
+    if (csm_init_table->HiPmmMemorySizeInBytes > CONFIG_MAX_HIGHTABLE) {
+        u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes;
+        add_e820(hi_pmm_end - CONFIG_MAX_HIGHTABLE, CONFIG_MAX_HIGHTABLE, E820_RESERVED);
+    }
+
+    // For PCIBIOS 1ab10e
+    if (csm_compat_table.IrqRoutingTablePointer &&
+        csm_compat_table.IrqRoutingTableLength) {
+        PirAddr = (void *)csm_compat_table.IrqRoutingTablePointer;
+        dprintf(3, "CSM PIRQ table at %p\n", PirAddr);
+    }
+
+    // For find_resume_vector()
+    if (csm_rsdp.signature == RSDP_SIGNATURE) {
+        RsdpAddr = &csm_rsdp;
+        dprintf(3, "CSM ACPI RSDP at %p\n", PirAddr);
+
+        // Find PM timer from ACPI tables provided by UEFI
+        // XXX: Theoretically, we should use XSDT and X_PM_TMR_BLK.
+        if (csm_rsdp.rsdt_physical_address) {
+	    u32 *rsdt = (u32 *)csm_rsdp.rsdt_physical_address;
+            int i;
+
+	    for (i = 9; i < rsdt[1] / 4; i++) {
+                struct fadt_descriptor_rev1 *fadt = (void *)rsdt[i];
+		u32 pm_tmr;
+
+		if (fadt->signature != FACP_SIGNATURE)
+                    continue;
+
+		pm_tmr = fadt->pm_tmr_blk;
+		if (!pm_tmr)
+                    break;
+
+		pmtimer_setup(PORT_ACPI_PM_BASE + 0x08, 3579);
+	    }
+	}
+    }
+
+    // SMBIOS table needs to be copied into the f-seg
+    // XX: OVMF doesn't seem to set SmbiosTableLength so don't check it
+    if (csm_boot_table->SmbiosTable && !SMBiosAddr)
+        copy_smbios((void *)csm_boot_table->SmbiosTable);
+
+    // MPTABLE is just there; we don't care where.
+
+    // EFI may have reinitialised the video using its *own* driver.
+    enable_vga_console();
+
+    // EFI fills this in for us. Zero it for now...
+    struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
+    bda->hdcount = 0;
+
+    device_hardware_setup();
+    wait_threads();
+
+    interactive_bootmenu();
+    wait_threads();
+
+    prepareboot();
+
+    regs->ax = 0;
+}
+
+/* Boot */
+void handle_csm_0003(struct bregs *regs)
+{
+    dprintf(3, "Boot\n");
+
+    startBoot();
+
+    regs->ax = 1;
+}
+
+/* Legacy16DispatchOprom */
+void handle_csm_0005(struct bregs *regs)
+{
+    EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx);
+    struct rom_header *rom;
+    u16 bdf;
+
+    dprintf(3, "Legacy16DispatchOprom rom %p\n", table);
+
+    dprintf(3, "OpromSegment   %04x\n", table->OpromSegment);
+    dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
+    dprintf(3, "PnPInstallationCheck %04x:%04x\n",
+            table->PnPInstallationCheckSegment,
+            table->PnPInstallationCheckOffset);
+    dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
+
+    rom = MAKE_FLATPTR(table->OpromSegment, 0);
+    bdf = pci_bus_devfn_to_bdf(table->PciBus, table->PciDeviceFunction);
+
+    rom_confirm(rom->size * 512);
+
+    // XX PnP seg/ofs should never be other than default
+    callrom(rom, bdf);
+
+    regs->bx = 0; // FIXME
+    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 = NULL;
+
+    if (!region)
+        region = 3;
+
+    dprintf(3, "Legacy16GetTableAddress size %x align %x region %d\n",
+        size, align, region);
+
+    if (region & 2)
+        chunk = pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
+    if (!chunk && (region & 1))
+        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;
+    }
+}
+
+static u8 pic_mask[2] = { ~PIC1_IRQ2, ~0 };
+
+void VISIBLE32FLAT
+handle_csm32(struct bregs *regs)
+{
+    ASSERT32FLAT();
+
+    dprintf(3, "handle_csm16 regs %p AX=%04x (PIC %02x%02x)\n", regs, regs->ax,
+	    pic_mask[0], pic_mask[1]);
+
+    outb(pic_mask[0], PORT_PIC1_DATA);
+    outb(pic_mask[1], PORT_PIC2_DATA);
+
+    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;
+    }
+    wait_threads();
+
+    pic_mask[0] = inb(PORT_PIC1_DATA);
+    pic_mask[1] = inb(PORT_PIC2_DATA);
+
+    dprintf(3, "handle_csm16 returning AX=%04x (PIC %02x%02x)\n", regs->ax,
+	    pic_mask[0], pic_mask[1]);
+}
+
+int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave)
+{
+    if (!csm_boot_table)
+        return -1;
+    BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
+    int index = 1 + (chanid * 2) + slave;
+    dprintf(3, "CSM bootprio for ATA%d,%d (index %d) is %d\n", chanid, slave,
+	    index, bbs[index].BootPriority);
+    return bbs[index].BootPriority;
+}
+
+int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid)
+{
+    if (!csm_boot_table)
+        return -1;
+    BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
+    dprintf(3, "CSM bootprio for FDC is %d\n", bbs[0].BootPriority);
+    return bbs[0].BootPriority;
+}
+
+int csm_bootprio_pci(struct pci_device *pci)
+{
+    if (!csm_boot_table)
+        return -1;
+    BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
+    int i;
+
+    for (i = 5; i < csm_boot_table->NumberBbsEntries; i++) {
+        if (pci->bdf == pci_to_bdf(bbs[i].Bus, bbs[i].Device, bbs[i].Function)) {
+            dprintf(3, "CSM bootprio for PCI(%d,%d,%d) is %d\n", bbs[i].Bus,
+                    bbs[i].Device, bbs[i].Function, bbs[i].BootPriority);
+            return bbs[i].BootPriority;
+	    }
+    }
+    return -1;
+}
+#endif /* CONFIG_CSM */
diff --git a/src/csm.h b/src/csm.h
new file mode 100644
index 0000000..31504fd
--- /dev/null
+++ b/src/csm.h
@@ -0,0 +1,13 @@
+// Compatibility Support Module (CSM) for UEFI / EDK-II
+//
+// Copyright © 2013 Intel Corporation
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "types.h"
+
+#define UINT8 u8
+#define UINT16 u16
+#define UINT32 u32
+
+#include "LegacyBios.h"
diff --git a/src/pirtable.c b/src/pirtable.c
index 62b62b8..2ba70ee 100644
--- a/src/pirtable.c
+++ b/src/pirtable.c
@@ -17,7 +17,7 @@ struct pir_table {
 } PACKED;
 
 extern struct pir_table PIR_TABLE;
-#if CONFIG_PIRTABLE && !CONFIG_COREBOOT
+#if CONFIG_PIRTABLE && !CONFIG_COREBOOT && !CONFIG_CSM
 struct pir_table PIR_TABLE __aligned(16) VAR16EXPORT = {
     .pir = {
         .version = 0x0100,
@@ -89,12 +89,12 @@ struct pir_table PIR_TABLE __aligned(16) VAR16EXPORT = {
         },
     }
 };
-#endif // CONFIG_PIRTABLE && !CONFIG_COREBOOT
+#endif // CONFIG_PIRTABLE && !CONFIG_COREBOOT && !CONFIG_CSM
 
 void
 pirtable_setup(void)
 {
-    if (! CONFIG_PIRTABLE)
+    if (! CONFIG_PIRTABLE || CONFIG_CSM)
         return;
 
     dprintf(3, "init PIR table\n");
diff --git a/src/pmm.c b/src/pmm.c
index 0dbc86e..f36b7c8 100644
--- a/src/pmm.c
+++ b/src/pmm.c
@@ -256,6 +256,25 @@ malloc_preinit(void)
     }
 }
 
+void
+csm_malloc_setup(u32 low_pmm, u32 low_pmm_size, u32 hi_pmm, u32 hi_pmm_size)
+{
+    ASSERT32FLAT();
+
+    if (hi_pmm_size > CONFIG_MAX_HIGHTABLE) {
+        void *hi_pmm_end = (void *)hi_pmm + hi_pmm_size;
+        addSpace(&ZoneTmpHigh, (void *)hi_pmm, hi_pmm_end - CONFIG_MAX_HIGHTABLE);
+        addSpace(&ZoneHigh, hi_pmm_end - CONFIG_MAX_HIGHTABLE, hi_pmm_end);
+    } else {
+        addSpace(&ZoneTmpHigh, (void *)hi_pmm, (void *)hi_pmm + hi_pmm_size);
+    }
+    addSpace(&ZoneTmpLow, (void *)low_pmm, (void *)low_pmm + low_pmm_size);
+    addSpace(&ZoneFSeg, BiosTableSpace, &BiosTableSpace[CONFIG_MAX_BIOSTABLE]);
+    extern u8 final_datalow_start[];
+    addSpace(&ZoneLow, datalow_base + OPROM_HEADER_RESERVE, final_datalow_start);
+    RomBase = findLast(&ZoneLow);
+}
+
 // Update pointers after code relocation.
 void
 malloc_fixupreloc_init(void)
diff --git a/src/romlayout.S b/src/romlayout.S
index 8125277..0c1cfb4 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -468,6 +468,43 @@ irqentryarg:
         DECL_IRQ_ENTRY hwpic1
         DECL_IRQ_ENTRY hwpic2
 
+#if CONFIG_CSM
+        EXPORTFUNC entry_csm16
+entry_csm16:
+        PUSHBREGS
+
+        // Reset stack and store EFI's old SS:SP on it
+        movl %esp, %edx
+        movw %ss, %cx
+
+        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
+
+        // call32(handle_csm32, bregs, -1)
+        movl $_cfunc32flat_handle_csm32, %eax
+        movl $-1, %ecx
+        calll call32
+
+        // Switch back to EFI's stack and return
+        popl %edx
+        popl %ecx
+        movw %cx, %ss
+        movw %cx, %ds
+        movl %edx, %esp
+
+        POPBREGS
+        iretw
+#endif
+
         // int 18/19 are special - they reset stack and call into 32bit mode.
         DECLFUNC entry_19
 entry_19:
diff --git a/src/util.h b/src/util.h
index 84915ed..6846bb9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -368,6 +368,7 @@ u32 rom_get_top(void);
 u32 rom_get_last(void);
 struct rom_header *rom_reserve(u32 size);
 int rom_confirm(u32 size);
+void csm_malloc_setup(u32 low_pmm, u32 low_pmm_size, u32 hi_pmm, u32 hi_pmm_size);
 void malloc_preinit(void);
 void malloc_fixupreloc_init(void);
 void malloc_prepboot(void);
-- 
1.8.0.2




More information about the SeaBIOS mailing list