diff options
-rw-r--r-- | src/acpi.c | 311 | ||||
-rw-r--r-- | src/config.h | 4 | ||||
-rw-r--r-- | src/coreboot.c | 42 | ||||
-rw-r--r-- | src/memmap.c | 103 | ||||
-rw-r--r-- | src/memmap.h | 6 | ||||
-rw-r--r-- | src/misc.c | 3 | ||||
-rw-r--r-- | src/mptable.c | 15 | ||||
-rw-r--r-- | src/post.c | 4 | ||||
-rw-r--r-- | src/smbios.c | 48 |
9 files changed, 307 insertions, 229 deletions
@@ -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 @@ -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); } @@ -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); } |