aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/acpi.c311
-rw-r--r--src/config.h4
-rw-r--r--src/coreboot.c42
-rw-r--r--src/memmap.c103
-rw-r--r--src/memmap.h6
-rw-r--r--src/misc.c3
-rw-r--r--src/mptable.c15
-rw-r--r--src/post.c4
-rw-r--r--src/smbios.c48
9 files changed, 307 insertions, 229 deletions
diff --git a/src/acpi.c b/src/acpi.c
index 72977b12..bafdd6b9 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -1,13 +1,13 @@
// Support for generating ACPI tables (on emulators)
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2006 Fabrice Bellard
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "acpi.h" // struct rsdp_descriptor
#include "util.h" // memcpy
-#include "memmap.h" // bios_table_cur_addr
+#include "memmap.h" // malloc_fseg
#include "pci.h" // pci_find_device
#include "biosvar.h" // GET_EBDA
#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
@@ -44,7 +44,7 @@ struct acpi_table_header /* ACPI common table header */
struct rsdt_descriptor_rev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 table_offset_entry [3]; /* Array of pointers to other */
+ u32 table_offset_entry[3]; /* Array of pointers to other */
/* ACPI tables */
} PACKED;
@@ -224,8 +224,9 @@ static inline u32 cpu_to_le32(u32 x)
return x;
}
-static void acpi_build_table_header(struct acpi_table_header *h,
- u32 sig, int len, u8 rev)
+static void
+build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev
+ , struct rsdt_descriptor_rev1 *rsdt)
{
h->signature = sig;
h->length = cpu_to_le32(len);
@@ -237,30 +238,144 @@ static void acpi_build_table_header(struct acpi_table_header *h,
h->oem_revision = cpu_to_le32(1);
h->asl_compiler_revision = cpu_to_le32(1);
h->checksum -= checksum(h, len);
+
+ // Add to rsdt table
+ if (!rsdt)
+ return;
+ if (rsdt->length >= sizeof(*rsdt)) {
+ dprintf(1, "No more room for rsdt entry!\n");
+ return;
+ }
+ u32 *p = (void*)rsdt + rsdt->length;
+ *p = (u32)h;
+ rsdt->length += sizeof(*p);
}
-#define SSDT_SIGNATURE 0x54445353// SSDT
-static int
-acpi_build_processor_ssdt(u8 *ssdt)
+static void
+build_fadt(struct rsdt_descriptor_rev1 *rsdt, int bdf)
+{
+ struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
+ struct facs_descriptor_rev1 *facs = malloc_high(sizeof(*facs) + 63);
+ void *dsdt = malloc_high(sizeof(AmlCode));
+
+ if (!fadt || !facs || !dsdt) {
+ dprintf(1, "Not enough memory for fadt!\n");
+ return;
+ }
+
+ /* FACS */
+ facs = (void*)ALIGN((u32)facs, 64);
+ memset(facs, 0, sizeof(*facs));
+ facs->signature = FACS_SIGNATURE;
+ facs->length = cpu_to_le32(sizeof(*facs));
+
+ /* DSDT */
+ memcpy(dsdt, AmlCode, sizeof(AmlCode));
+
+ /* FADT */
+ memset(fadt, 0, sizeof(*fadt));
+ fadt->firmware_ctrl = cpu_to_le32((u32)facs);
+ fadt->dsdt = cpu_to_le32((u32)dsdt);
+ fadt->model = 1;
+ fadt->reserved1 = 0;
+ int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
+ fadt->sci_int = cpu_to_le16(pm_sci_int);
+ fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
+ fadt->acpi_enable = 0xf1;
+ fadt->acpi_disable = 0xf0;
+ fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
+ fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
+ fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm_tmr_len = 4;
+ fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
+ fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
+ /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
+ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
+
+ build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1, rsdt);
+}
+
+static void
+build_madt(struct rsdt_descriptor_rev1 *rsdt)
+{
+ int smp_cpus = CountCPUs;
+ int madt_size = (sizeof(struct multiple_apic_table)
+ + sizeof(struct madt_processor_apic) * smp_cpus
+ + sizeof(struct madt_io_apic)
+ + sizeof(struct madt_intsrcovr) * 16);
+ struct multiple_apic_table *madt = malloc_high(madt_size);
+ if (!madt) {
+ dprintf(1, "Not enough memory for madt!\n");
+ return;
+ }
+ memset(madt, 0, madt_size);
+ madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
+ madt->flags = cpu_to_le32(1);
+ struct madt_processor_apic *apic = (void*)&madt[1];
+ int i;
+ for (i=0; i<smp_cpus; i++) {
+ apic->type = APIC_PROCESSOR;
+ apic->length = sizeof(*apic);
+ apic->processor_id = i;
+ apic->local_apic_id = i;
+ apic->flags = cpu_to_le32(1);
+ apic++;
+ }
+ struct madt_io_apic *io_apic = (void*)apic;
+ io_apic->type = APIC_IO;
+ io_apic->length = sizeof(*io_apic);
+ io_apic->io_apic_id = smp_cpus;
+ io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
+ io_apic->interrupt = cpu_to_le32(0);
+
+ struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
+ for (i = 0; i < 16; i++) {
+ if (!(PCI_ISA_IRQ_MASK & (1 << i)))
+ /* No need for a INT source override structure. */
+ continue;
+ memset(intsrcovr, 0, sizeof(*intsrcovr));
+ intsrcovr->type = APIC_XRUPT_OVERRIDE;
+ intsrcovr->length = sizeof(*intsrcovr);
+ intsrcovr->source = i;
+ intsrcovr->gsi = i;
+ intsrcovr->flags = 0xd; /* active high, level triggered */
+ intsrcovr++;
+ }
+
+ build_header((void*)madt, APIC_SIGNATURE, (void*)intsrcovr - (void*)madt
+ , 1, rsdt);
+}
+
+#define SSDT_SIGNATURE 0x54445353 // SSDT
+static void
+build_ssdt(struct rsdt_descriptor_rev1 *rsdt)
{
- u8 *ssdt_ptr = ssdt;
- int i, length;
int smp_cpus = CountCPUs;
int acpi_cpus = smp_cpus > 0xff ? 0xff : smp_cpus;
+ // calculate the length of processor block and scope block
+ // excluding PkgLength
+ int cpu_length = 13 * acpi_cpus + 4;
+
+ int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
+ u8 *ssdt = malloc_high(length);
+ if (! ssdt) {
+ dprintf(1, "No space for ssdt!\n");
+ return;
+ }
+ u8 *ssdt_ptr = ssdt;
ssdt_ptr[9] = 0; // checksum;
ssdt_ptr += sizeof(struct acpi_table_header);
- // caluculate the length of processor block and scope block excluding PkgLength
- length = 0x0d * acpi_cpus + 4;
-
// build processor scope header
*(ssdt_ptr++) = 0x10; // ScopeOp
- if (length <= 0x3e) {
- *(ssdt_ptr++) = length + 1;
+ if (cpu_length <= 0x3e) {
+ *(ssdt_ptr++) = cpu_length + 1;
} else {
*(ssdt_ptr++) = 0x7F;
- *(ssdt_ptr++) = (length + 2) >> 6;
+ *(ssdt_ptr++) = (cpu_length + 2) >> 6;
}
*(ssdt_ptr++) = '_'; // Name
*(ssdt_ptr++) = 'P';
@@ -268,7 +383,8 @@ acpi_build_processor_ssdt(u8 *ssdt)
*(ssdt_ptr++) = '_';
// build object for each processor
- for(i=0;i<acpi_cpus;i++) {
+ int i;
+ for (i=0; i<acpi_cpus; i++) {
*(ssdt_ptr++) = 0x5B; // ProcessorOp
*(ssdt_ptr++) = 0x83;
*(ssdt_ptr++) = 0x0B; // Length
@@ -287,16 +403,13 @@ acpi_build_processor_ssdt(u8 *ssdt)
*(ssdt_ptr++) = 6; // Processor block length
}
- acpi_build_table_header((struct acpi_table_header *)ssdt,
- SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
-
- return ssdt_ptr - ssdt;
+ build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1, rsdt);
}
struct rsdp_descriptor *RsdpAddr;
-/* base_addr must be a multiple of 4KB */
-void acpi_bios_init(void)
+void
+acpi_bios_init(void)
{
if (! CONFIG_ACPI)
return;
@@ -310,145 +423,35 @@ void acpi_bios_init(void)
// Device not found
return;
- struct rsdp_descriptor *rsdp;
- struct rsdt_descriptor_rev1 *rsdt;
- struct fadt_descriptor_rev1 *fadt;
- struct facs_descriptor_rev1 *facs;
- struct multiple_apic_table *madt;
- u8 *dsdt, *ssdt;
- u32 base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
- u32 acpi_tables_size, madt_addr, madt_size;
- int i;
-
- /* reserve memory space for tables */
- bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
- rsdp = (void *)bios_table_cur_addr;
- bios_table_cur_addr += sizeof(*rsdp);
-
- addr = base_addr = RamSize - CONFIG_ACPI_DATA_SIZE;
- add_e820(addr, CONFIG_ACPI_DATA_SIZE, E820_ACPI);
- rsdt_addr = addr;
- rsdt = (void *)(addr);
- addr += sizeof(*rsdt);
-
- fadt_addr = addr;
- fadt = (void *)(addr);
- addr += sizeof(*fadt);
-
- addr = ALIGN(addr, 64);
- facs_addr = addr;
- facs = (void *)(addr);
- addr += sizeof(*facs);
+ // Create initial rsdt table
+ struct rsdt_descriptor_rev1 *rsdt = malloc_high(sizeof(*rsdt));
+ if (!rsdt) {
+ dprintf(1, "Not enough memory for acpi rsdt table!\n");
+ return;
+ }
+ memset(rsdt, 0, sizeof(*rsdt));
+ rsdt->length = offsetof(struct rsdt_descriptor_rev1, table_offset_entry[0]);
- dsdt_addr = addr;
- dsdt = (void *)(addr);
- addr += sizeof(AmlCode);
+ // Add tables
+ build_fadt(rsdt, bdf);
+ build_ssdt(rsdt);
+ build_madt(rsdt);
- ssdt_addr = addr;
- ssdt = (void *)(addr);
- addr += acpi_build_processor_ssdt(ssdt);
+ build_header((void*)rsdt, RSDT_SIGNATURE, rsdt->length, 1, NULL);
- int smp_cpus = CountCPUs;
- addr = ALIGN(addr, 8);
- madt_addr = addr;
- madt_size = sizeof(*madt) +
- sizeof(struct madt_processor_apic) * smp_cpus +
- sizeof(struct madt_io_apic);
- madt = (void *)(addr);
- addr += madt_size;
-
- acpi_tables_size = addr - base_addr;
-
- dprintf(1, "ACPI tables: RSDP addr=0x%08lx"
- " ACPI DATA addr=0x%08lx size=0x%x\n",
- (unsigned long)rsdp,
- (unsigned long)rsdt, acpi_tables_size);
-
- /* RSDP */
+ // Build rsdp pointer table
+ struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp));
+ if (!rsdp) {
+ dprintf(1, "Not enough memory for acpi rsdp!\n");
+ return;
+ }
memset(rsdp, 0, sizeof(*rsdp));
rsdp->signature = RSDP_SIGNATURE;
memcpy(rsdp->oem_id, CONFIG_APPNAME6, 6);
- rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
+ rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt);
rsdp->checksum -= checksum(rsdp, 20);
RsdpAddr = rsdp;
-
- /* RSDT */
- memset(rsdt, 0, sizeof(*rsdt));
- rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
- rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
- rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
- acpi_build_table_header((struct acpi_table_header *)rsdt,
- RSDT_SIGNATURE, sizeof(*rsdt), 1);
-
- /* FADT */
- memset(fadt, 0, sizeof(*fadt));
- fadt->firmware_ctrl = cpu_to_le32(facs_addr);
- fadt->dsdt = cpu_to_le32(dsdt_addr);
- fadt->model = 1;
- fadt->reserved1 = 0;
- int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
- fadt->sci_int = cpu_to_le16(pm_sci_int);
- fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
- fadt->acpi_enable = 0xf1;
- fadt->acpi_disable = 0xf0;
- fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
- fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
- fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
- fadt->pm1_evt_len = 4;
- fadt->pm1_cnt_len = 2;
- fadt->pm_tmr_len = 4;
- fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
- fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
- /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
- acpi_build_table_header((struct acpi_table_header *)fadt, FACP_SIGNATURE,
- sizeof(*fadt), 1);
-
- /* FACS */
- memset(facs, 0, sizeof(*facs));
- facs->signature = FACS_SIGNATURE;
- facs->length = cpu_to_le32(sizeof(*facs));
-
- /* DSDT */
- memcpy(dsdt, AmlCode, sizeof(AmlCode));
-
- /* MADT */
- memset(madt, 0, madt_size);
- madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
- madt->flags = cpu_to_le32(1);
- struct madt_processor_apic *apic = (void *)&madt[1];
- for(i=0;i<smp_cpus;i++) {
- apic->type = APIC_PROCESSOR;
- apic->length = sizeof(*apic);
- apic->processor_id = i;
- apic->local_apic_id = i;
- apic->flags = cpu_to_le32(1);
- apic++;
- }
- struct madt_io_apic *io_apic = (void *)apic;
- io_apic->type = APIC_IO;
- io_apic->length = sizeof(*io_apic);
- io_apic->io_apic_id = smp_cpus;
- io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
- io_apic->interrupt = cpu_to_le32(0);
-
- struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
- for (i = 0; i < 16; i++) {
- if (!(PCI_ISA_IRQ_MASK & (1 << i)))
- /* No need for a INT source override structure. */
- continue;
- memset(intsrcovr, 0, sizeof(*intsrcovr));
- intsrcovr->type = APIC_XRUPT_OVERRIDE;
- intsrcovr->length = sizeof(*intsrcovr);
- intsrcovr->source = i;
- intsrcovr->gsi = i;
- intsrcovr->flags = 0xd; /* active high, level triggered */
- intsrcovr++;
- madt_size += sizeof(struct madt_intsrcovr);
- }
-
- acpi_build_table_header((struct acpi_table_header *)madt,
- APIC_SIGNATURE, madt_size, 1);
+ dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt);
}
u32
diff --git a/src/config.h b/src/config.h
index cba7ac4b..3b4b5fee 100644
--- a/src/config.h
+++ b/src/config.h
@@ -98,12 +98,12 @@
#define CONFIG_MAX_E820 32
// Space to reserve in f-segment for run-time built bios tables.
#define CONFIG_MAX_BIOSTABLE 2048
+// Space to reserve in high-memory for tables
+#define CONFIG_MAX_HIGHTABLE (64*1024)
#define CONFIG_MAX_ATA_INTERFACES 4
#define CONFIG_MAX_ATA_DEVICES (CONFIG_MAX_ATA_INTERFACES*2)
-#define CONFIG_ACPI_DATA_SIZE 0x00010000L
-
#define CONFIG_MODEL_ID 0xFC
#define CONFIG_SUBMODEL_ID 0x00
#define CONFIG_BIOS_REVISION 0x01
diff --git a/src/coreboot.c b/src/coreboot.c
index a7604141..f99146e4 100644
--- a/src/coreboot.c
+++ b/src/coreboot.c
@@ -1,6 +1,6 @@
// Coreboot interface support.
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -11,6 +11,7 @@
#include "mptable.h" // MPTABLE_SIGNATURE
#include "biosvar.h" // GET_EBDA
#include "lzmadecode.h" // LzmaDecode
+#include "memmap.h" // malloc_fseg
/****************************************************************
@@ -29,15 +30,14 @@ copy_pir(void *pos)
return;
if (checksum(pos, p->size) != 0)
return;
- bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
- if (bios_table_cur_addr + p->size > bios_table_end_addr) {
+ void *newpos = malloc_fseg(p->size);
+ if (!newpos) {
dprintf(1, "No room to copy PIR table!\n");
return;
}
- dprintf(1, "Copying PIR from %p to %x\n", pos, bios_table_cur_addr);
- memcpy((void*)bios_table_cur_addr, pos, p->size);
- PirOffset = bios_table_cur_addr - BUILD_BIOS_ADDR;
- bios_table_cur_addr += p->size;
+ dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
+ memcpy(newpos, pos, p->size);
+ PirOffset = (u32)newpos - BUILD_BIOS_ADDR;
}
static void
@@ -51,20 +51,17 @@ copy_mptable(void *pos)
if (checksum(pos, sizeof(*p)) != 0)
return;
u32 length = p->length * 16;
- bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
- if (bios_table_cur_addr + length + mpclength > bios_table_end_addr) {
+ struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
+ if (!newpos) {
dprintf(1, "No room to copy MPTABLE!\n");
return;
}
- dprintf(1, "Copying MPTABLE from %p/%x to %x\n"
- , pos, p->physaddr, bios_table_cur_addr);
- memcpy((void*)bios_table_cur_addr, pos, length);
- struct mptable_floating_s *newp = (void*)bios_table_cur_addr;
- newp->physaddr = bios_table_cur_addr + length;
- newp->checksum -= checksum(newp, sizeof(*newp));
- memcpy((void*)bios_table_cur_addr + length, (void*)p->physaddr, mpclength);
- bios_table_cur_addr += length + mpclength;
+ dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
+ memcpy(newpos, pos, length);
+ newpos->physaddr = (u32)newpos + length;
+ newpos->checksum -= checksum(newpos, sizeof(*newpos));
+ memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
}
static void
@@ -83,15 +80,14 @@ copy_acpi_rsdp(void *pos)
if (checksum(pos, length) != 0)
return;
}
- bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
- if (bios_table_cur_addr + length > bios_table_end_addr) {
+ void *newpos = malloc_fseg(length);
+ if (!newpos) {
dprintf(1, "No room to copy ACPI RSDP table!\n");
return;
}
- dprintf(1, "Copying ACPI RSDP from %p to %x\n", pos, bios_table_cur_addr);
- RsdpAddr = (void*)bios_table_cur_addr;
- memcpy(RsdpAddr, pos, length);
- bios_table_cur_addr += length;
+ dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
+ memcpy(newpos, pos, length);
+ RsdpAddr = newpos;
}
// Attempt to find (and relocate) any standard bios tables found in a
diff --git a/src/memmap.c b/src/memmap.c
index 65c9cd72..b8072ac9 100644
--- a/src/memmap.c
+++ b/src/memmap.c
@@ -1,6 +1,6 @@
// Support for building memory maps suitable for int 15 e820 calls.
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -8,6 +8,11 @@
#include "util.h" // dprintf.h
#include "biosvar.h" // SET_EBDA
+
+/****************************************************************
+ * e820 memory map
+ ****************************************************************/
+
// Remove an entry from the e820_list.
static void
remove_e820(int i)
@@ -118,12 +123,6 @@ add_e820(u64 start, u64 size, u32 type)
void
memmap_setup()
{
- memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
- bios_table_cur_addr = (u32)BiosTableSpace;
- bios_table_end_addr = bios_table_cur_addr + CONFIG_MAX_BIOSTABLE;
- dprintf(1, "bios_table_addr: 0x%08x end=0x%08x\n",
- bios_table_cur_addr, bios_table_end_addr);
-
e820_count = 0;
}
@@ -132,11 +131,89 @@ void
memmap_finalize()
{
dump_map();
+}
+
+
+/****************************************************************
+ * malloc
+ ****************************************************************/
+
+#define MINALIGN 16
+
+struct zone_s {
+ u32 top, bottom, cur;
+};
+
+static struct zone_s ZoneHigh, ZoneFSeg;
+
+static void *
+__malloc(struct zone_s *zone, u32 size)
+{
+ u32 newpos = (zone->cur - size) / MINALIGN * MINALIGN;
+ if (newpos < zone->bottom)
+ // No space
+ return NULL;
+ zone->cur = newpos;
+ return (void*)newpos;
+}
+
+// Allocate memory at the top of ram.
+void *
+malloc_high(u32 size)
+{
+ return __malloc(&ZoneHigh, size);
+}
+
+// Allocate memory in the 0xf0000-0x100000 area of ram.
+void *
+malloc_fseg(u32 size)
+{
+ return __malloc(&ZoneFSeg, size);
+}
+
+void
+malloc_setup()
+{
+ // Memory in 0xf0000 area.
+ memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
+ ZoneFSeg.bottom = (u32)BiosTableSpace;
+ ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE;
+
+ // Find memory at the top of ram.
+ u32 top = 0;
+ int i;
+ for (i=e820_count-1; i>=0; i--) {
+ struct e820entry *e = &e820_list[i];
+ u64 end = e->start + e->size;
+ if (e->type != E820_RAM || end > 0xffffffff)
+ continue;
+ top = end;
+ break;
+ }
+ if (top < 1024*1024 + CONFIG_MAX_HIGHTABLE) {
+ // No memory above 1Meg
+ memset(&ZoneHigh, 0, sizeof(ZoneHigh));
+ return;
+ }
+ ZoneHigh.bottom = top - CONFIG_MAX_HIGHTABLE;
+ ZoneHigh.top = ZoneHigh.cur = ZoneHigh.bottom + CONFIG_MAX_HIGHTABLE;
+ add_e820(ZoneHigh.bottom, CONFIG_MAX_HIGHTABLE, E820_RESERVED);
+}
+
+void
+malloc_finalize()
+{
+ // Give back unused high ram.
+ u32 giveback = (ZoneHigh.cur - ZoneHigh.bottom) / 4096 * 4096;
+ add_e820(ZoneHigh.bottom, giveback, E820_RAM);
- dprintf(1, "final bios_table_addr: 0x%08x (used %d%%)\n"
- , bios_table_cur_addr
- , (100 * (bios_table_cur_addr - (u32)&BiosTableSpace)
- / CONFIG_MAX_BIOSTABLE));
- if (bios_table_cur_addr > bios_table_end_addr)
- panic("bios_table_end_addr overflow!\n");
+ // Report statistics
+ u32 used = ZoneFSeg.top - ZoneFSeg.cur;
+ u32 avail = ZoneFSeg.top - ZoneFSeg.bottom;
+ dprintf(1, "malloc_fseg used=%d (%d%%)\n"
+ , used, (100 * used) / avail);
+ used = ZoneHigh.top - ZoneHigh.cur;
+ avail = ZoneHigh.top - ZoneHigh.bottom;
+ dprintf(1, "malloc_high used=%d (%d%%) (returned %d)\n"
+ , used, (100 * used) / avail, giveback);
}
diff --git a/src/memmap.h b/src/memmap.h
index 8338c430..8df9ed09 100644
--- a/src/memmap.h
+++ b/src/memmap.h
@@ -20,12 +20,16 @@ void add_e820(u64 start, u64 size, u32 type);
void memmap_setup();
void memmap_finalize();
+void *malloc_high(u32 size);
+void *malloc_fseg(u32 size);
+void malloc_setup();
+void malloc_finalize();
+
// e820 map storage (defined in system.c)
extern struct e820entry e820_list[];
extern int e820_count;
// Space for exported bios tables (defined in misc.c)
-extern u32 bios_table_cur_addr, bios_table_end_addr;
extern char BiosTableSpace[];
#endif // e820map.h
diff --git a/src/misc.c b/src/misc.c
index bece61e6..956e545d 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,6 +1,6 @@
// Code for misc 16bit handlers and variables.
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2002 MandrakeSoft S.A.
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -15,7 +15,6 @@ u32 RamSize VAR16_32;
// Amount of continuous ram >4Gig
u64 RamSizeOver4G;
// Space for bios tables built an run-time.
-u32 bios_table_cur_addr, bios_table_end_addr;
char BiosTableSpace[CONFIG_MAX_BIOSTABLE] VAR16_32;
diff --git a/src/mptable.c b/src/mptable.c
index e81bd62c..5758b28d 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -1,12 +1,12 @@
// MPTable generation (on emulators)
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2006 Fabrice Bellard
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "util.h" // dprintf
-#include "memmap.h" // bios_table_cur_addr
+#include "memmap.h" // malloc_fseg
#include "config.h" // CONFIG_*
#include "mptable.h" // MPTABLE_SIGNATURE
@@ -23,21 +23,20 @@ mptable_init(void)
// Building an mptable on uniprocessor machines confuses some OSes.
return;
- u32 start = ALIGN(bios_table_cur_addr, 16);
int length = (sizeof(struct mptable_floating_s)
+ sizeof(struct mptable_config_s)
+ sizeof(struct mpt_cpu) * smp_cpus
+ sizeof(struct mpt_bus)
+ sizeof(struct mpt_ioapic)
+ sizeof(struct mpt_intsrc) * 16);
- if (start + length > bios_table_end_addr) {
+ void *start = malloc_fseg(length);
+ if (!start) {
dprintf(1, "No room for MPTABLE!\n");
return;
}
- bios_table_cur_addr = start + length;
/* floating pointer structure */
- struct mptable_floating_s *floating = (void*)start;
+ struct mptable_floating_s *floating = start;
memset(floating, 0, sizeof(*floating));
struct mptable_config_s *config = (void*)&floating[1];
floating->signature = MPTABLE_SIGNATURE;
@@ -108,6 +107,6 @@ mptable_init(void)
// Set checksum.
config->checksum -= checksum(config, config->length);
- dprintf(1, "MP table addr=0x%x MPC table addr=0x%x size=0x%x\n",
- (u32)floating, (u32)config, length);
+ dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n",
+ floating, config, length);
}
diff --git a/src/post.c b/src/post.c
index aa7b83f9..052edb57 100644
--- a/src/post.c
+++ b/src/post.c
@@ -1,6 +1,6 @@
// 32bit code to Power On Self Test (POST) a machine.
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2002 MandrakeSoft S.A.
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -166,6 +166,7 @@ post()
ram_probe();
mtrr_setup();
smp_probe();
+ malloc_setup();
pnp_setup();
vga_setup();
@@ -179,6 +180,7 @@ post()
smm_init();
init_bios_tables();
+ malloc_finalize();
memmap_finalize();
boot_setup();
diff --git a/src/smbios.c b/src/smbios.c
index e9a4b31b..fb036711 100644
--- a/src/smbios.c
+++ b/src/smbios.c
@@ -1,12 +1,12 @@
// smbios table generation (on emulators)
//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2006 Fabrice Bellard
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "util.h" // dprintf
-#include "memmap.h" // bios_table_cur_addr
+#include "memmap.h" // malloc_fseg
#include "biosvar.h" // GET_EBDA
@@ -222,13 +222,16 @@ struct smbios_type_127 {
****************************************************************/
static void
-smbios_entry_point_init(void *start,
- u16 max_structure_size,
+smbios_entry_point_init(u16 max_structure_size,
u16 structure_table_length,
- u32 structure_table_address,
+ void *structure_table_address,
u16 number_of_structures)
{
- struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
+ struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep));
+ if (! ep) {
+ dprintf(1, "No space for smbios entry table!\n");
+ return;
+ }
memcpy(ep->anchor_string, "_SM_", 4);
ep->length = 0x1f;
@@ -240,13 +243,15 @@ smbios_entry_point_init(void *start,
memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
ep->structure_table_length = structure_table_length;
- ep->structure_table_address = structure_table_address;
+ ep->structure_table_address = (u32)structure_table_address;
ep->number_of_structures = number_of_structures;
ep->smbios_bcd_revision = 0x24;
- ep->checksum -= checksum(start, 0x10);
+ ep->checksum -= checksum(ep, 0x10);
+
+ ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10);
- ep->intermediate_checksum -= checksum(start + 0x10, ep->length - 0x10);
+ dprintf(1, "SMBIOS ptr=%p table=%p\n", ep, structure_table_address);
}
/* Type 0 -- BIOS Information */
@@ -537,13 +542,14 @@ smbios_init(void)
dprintf(3, "init SMBIOS tables\n");
- unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
- char *start, *p, *q;
-
- bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
- start = (void *)(bios_table_cur_addr);
+ char *start = malloc_high(2048); // XXX - determine real size
+ if (! start) {
+ dprintf(1, "No memory for smbios tables\n");
+ return;
+ }
- p = (char *)start + sizeof(struct smbios_entry_point);
+ u32 nr_structs = 0, max_struct_size = 0;
+ char *q, *p = start;
#define add_struct(fn) { \
q = (fn); \
@@ -556,7 +562,7 @@ smbios_init(void)
add_struct(smbios_type_0_init(p));
add_struct(smbios_type_1_init(p));
add_struct(smbios_type_3_init(p));
- int smp_cpus = CountCPUs;
+ int cpu_num, smp_cpus = CountCPUs;
for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
add_struct(smbios_type_4_init(p, cpu_num));
add_struct(smbios_type_16_init(p));
@@ -568,13 +574,5 @@ smbios_init(void)
#undef add_struct
- smbios_entry_point_init(
- start, max_struct_size,
- (p - (char *)start) - sizeof(struct smbios_entry_point),
- (u32)(start + sizeof(struct smbios_entry_point)),
- nr_structs);
-
- bios_table_cur_addr += (p - (char *)start);
-
- dprintf(1, "SMBIOS table addr=0x%08lx\n", (unsigned long)start);
+ smbios_entry_point_init(max_struct_size, p - start, start, nr_structs);
}