From 3c7f46b42215502ecaee54c85f6d08dce9e21279 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Fri, 27 Feb 2009 23:09:55 +0000 Subject: Generic approach of putting BIOS tables at the end of memory (in addition to their low locations) This adds the kontron 986LCD-M and the i945 as a sample. Signed-off-by: Stefan Reinauer Acked-by: Myles Watson git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3960 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/boot/tables.c | 99 ++++++++++++++++++++++++++-- src/config/Options.lb | 12 ++++ src/include/boot/tables.h | 3 + src/mainboard/kontron/986lcd-m/Options.lb | 4 ++ src/mainboard/kontron/986lcd-m/acpi_tables.c | 5 ++ src/mainboard/kontron/986lcd-m/mainboard.c | 22 +++++++ src/northbridge/intel/i945/northbridge.c | 32 ++++++--- 7 files changed, 164 insertions(+), 13 deletions(-) diff --git a/src/arch/i386/boot/tables.c b/src/arch/i386/boot/tables.c index efe6dee383..e8de68a88a 100644 --- a/src/arch/i386/boot/tables.c +++ b/src/arch/i386/boot/tables.c @@ -1,3 +1,22 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) .... others + * Copyright (C) 2008-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ /* 2006.1 yhlu add mptable cross 0x467 processing */ @@ -38,11 +57,32 @@ void move_gdt(unsigned long newgdt) printk_debug("ok\n"); } +#if HAVE_HIGH_TABLES == 1 +uint64_t high_tables_base = 0; +uint64_t high_tables_size; +#endif + struct lb_memory *write_tables(void) { unsigned long low_table_start, low_table_end, new_low_table_end; unsigned long rom_table_start, rom_table_end; +#if HAVE_HIGH_TABLES == 1 + /* Even if high tables are configured, all tables are copied both to the + * low and the high area, so payloads and OSes don't need to know about + * the high tables. + */ + unsigned long high_table_start, high_table_end=0; + + if (high_tables_base) { + printk_debug("High Tables Base is %lx.\n", high_tables_base); + high_table_start = high_tables_base; + high_table_end = high_tables_base; + } else { + printk_debug("High Tables Base is not set.\n"); + } +#endif + rom_table_start = 0xf0000; rom_table_end = 0xf0000; /* Start low addr at 16 bytes instead of 0 because of a buglet @@ -53,24 +93,47 @@ struct lb_memory *write_tables(void) post_code(0x9a); +#if HAVE_LOW_TABLES == 1 /* This table must be betweeen 0xf0000 & 0x100000 */ rom_table_end = write_pirq_routing_table(rom_table_end); rom_table_end = (rom_table_end + 1023) & ~1023; +#endif +#if HAVE_HIGH_TABLES == 1 + if (high_tables_base) { + high_table_end = write_pirq_routing_table(high_table_end); + high_table_end = (high_table_end + 1023) & ~1023; + } +#endif /* Write ACPI tables */ /* write them in the rom area because DSDT can be large (8K on epia-m) which * pushes coreboot table out of first 4K if set up in low table area */ +#if HAVE_LOW_TABLES == 1 rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = (rom_table_end+1023) & ~1023; - +#endif +#if HAVE_HIGH_TABLES == 1 + if (high_tables_base) { + high_table_end = write_acpi_tables(high_table_end); + high_table_end = (high_table_end+1023) & ~1023; + } +#endif /* copy the smp block to address 0 */ post_code(0x96); /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ +#if HAVE_LOW_TABLES == 1 new_low_table_end = write_smp_table(low_table_end); // low_table_end is 0x10 at this point +#endif +#if HAVE_HIGH_TABLES == 1 + if (high_tables_base) { + high_table_end = write_smp_table(high_table_end); + high_table_end = (high_table_end+1023) & ~1023; + } +#endif -#if HAVE_MP_TABLE==1 +#if HAVE_MP_TABLE == 1 /* Don't write anything in the traditional x86 BIOS data segment, * for example the linux kernel smp need to use 0x467 to pass reset vector * or use 0x40e/0x413 for EBDA finding... @@ -104,8 +167,18 @@ struct lb_memory *write_tables(void) } // Relocate the GDT to reserved memory, so it won't get clobbered - move_gdt(low_table_end); - low_table_end += &gdt_end - &gdt; +#if HAVE_HIGH_TABLES == 1 + if (high_tables_base) { + move_gdt(high_table_end); + high_table_end += &gdt_end - &gdt; + high_table_end = (high_table_end+1023) & ~1023; + } else { +#endif + move_gdt(low_table_end); + low_table_end += &gdt_end - &gdt; +#if HAVE_HIGH_TABLES == 1 + } +#endif #if CONFIG_MULTIBOOT /* The Multiboot information structure */ @@ -119,5 +192,23 @@ struct lb_memory *write_tables(void) write_coreboot_table(low_table_start, low_table_end, rom_table_start, rom_table_end); +#if 0 && HAVE_HIGH_TABLES == 1 + /* This is currently broken and should be severely refactored. Ideally + * we only have a pointer to the coreboot table in the low memory, so + * anyone can find the real position. + * write_coreboot_table does a lot more than just writing the coreboot + * table. It magically decides where the table should go, and therefore + * it consumes two base addresses. If we call write_coreboot_table like + * below, we get weird effects. + */ + /* And we want another copy in high area because the low area might be + * corrupted + */ + if (high_tables_base) { + write_coreboot_table(high_table_start, high_table_end, + high_table_start, high_table_end); + } +#endif + return get_lb_mem(); } diff --git a/src/config/Options.lb b/src/config/Options.lb index bb141d008e..46b52c180b 100644 --- a/src/config/Options.lb +++ b/src/config/Options.lb @@ -1111,6 +1111,18 @@ define HAVE_MAINBOARD_RESOURCES comment "Enable if the mainboard/chipset requires extra entries in the memory map" end +define HAVE_LOW_TABLES + default 1 + export always + comment "Enable if ACPI, PIRQ, MP tables are supposed to live in the low megabyte" +end + +define HAVE_HIGH_TABLES + default 0 + export always + comment "Enable if ACPI, PIRQ, MP tables are supposed to live at top of memory" +end + define CONFIG_SPLASH_GRAPHIC default 0 export used diff --git a/src/include/boot/tables.h b/src/include/boot/tables.h index f9e91a4e18..afd72b4ae9 100644 --- a/src/include/boot/tables.h +++ b/src/include/boot/tables.h @@ -3,6 +3,9 @@ #include +void lb_add_memory_range(struct lb_memory *mem, + uint32_t type, uint64_t start, uint64_t size); + struct lb_memory *write_tables(void); #endif /* BOOT_TABLES_H */ diff --git a/src/mainboard/kontron/986lcd-m/Options.lb b/src/mainboard/kontron/986lcd-m/Options.lb index dbf21d5801..40a8a796fb 100644 --- a/src/mainboard/kontron/986lcd-m/Options.lb +++ b/src/mainboard/kontron/986lcd-m/Options.lb @@ -29,6 +29,8 @@ uses LB_CKS_RANGE_START uses LB_CKS_RANGE_END uses LB_CKS_LOC uses HAVE_ACPI_TABLES +uses HAVE_MAINBOARD_RESOURCES +uses HAVE_HIGH_TABLES # SMP uses CONFIG_SMP uses CONFIG_LOGICAL_CPUS @@ -160,6 +162,8 @@ default HAVE_MP_TABLE=1 ## Build code to provide ACPI support ## default HAVE_ACPI_TABLES=1 +default HAVE_MAINBOARD_RESOURCES=1 +default HAVE_HIGH_TABLES=0 ## ## Build code to export a CMOS option table diff --git a/src/mainboard/kontron/986lcd-m/acpi_tables.c b/src/mainboard/kontron/986lcd-m/acpi_tables.c index 2e1b0b4346..16e5bd9b7e 100644 --- a/src/mainboard/kontron/986lcd-m/acpi_tables.c +++ b/src/mainboard/kontron/986lcd-m/acpi_tables.c @@ -289,6 +289,11 @@ unsigned long write_acpi_tables(unsigned long start) printk_debug("ACPI: * DMI (Linux workaround)\n"); memcpy((void *)0xfff80, dmi_table, DMI_TABLE_SIZE); +#if HAVE_HIGH_TABLES == 1 + memcpy((void *)current, dmi_table, DMI_TABLE_SIZE); + current += DMI_TABLE_SIZE; + ALIGN_CURRENT; +#endif printk_info("ACPI: done.\n"); return current; diff --git a/src/mainboard/kontron/986lcd-m/mainboard.c b/src/mainboard/kontron/986lcd-m/mainboard.c index e66777cc96..cec477318f 100644 --- a/src/mainboard/kontron/986lcd-m/mainboard.c +++ b/src/mainboard/kontron/986lcd-m/mainboard.c @@ -21,8 +21,30 @@ #include +#include +#include #include "chip.h" +/* in arch/i386/boot/tables.c */ +extern uint64_t high_tables_base, high_tables_size; + +/* in northbridge/intel/i945/northbridge.c */ +extern uint64_t uma_memory_base, uma_memory_size; + +int add_mainboard_resources(struct lb_memory *mem) +{ +#if HAVE_HIGH_TABLES == 1 + printk_debug("Adding high table area\n"); + lb_add_memory_range(mem, LB_MEM_TABLE, + high_tables_base, high_tables_size); +#endif + printk_debug("Adding UMA memory area\n"); + lb_add_memory_range(mem, LB_MEM_RESERVED, + uma_memory_base, uma_memory_size); + + return 0; +} + struct chip_operations mainboard_ops = { CHIP_NAME("Kontron 986LCD-M Mainboard") }; diff --git a/src/northbridge/intel/i945/northbridge.c b/src/northbridge/intel/i945/northbridge.c index 6aa9f2d545..9cb5cefe62 100644 --- a/src/northbridge/intel/i945/northbridge.c +++ b/src/northbridge/intel/i945/northbridge.c @@ -93,12 +93,18 @@ static uint32_t find_pci_tolm(struct bus *bus) return tolm; } +#if HAVE_HIGH_TABLES==1 +#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB +extern uint64_t high_tables_base, high_tables_size; +#endif +uint64_t uma_memory_base=0, uma_memory_size=0; + static void pci_domain_set_resources(device_t dev) { uint32_t pci_tolm; uint8_t tolud, reg8; uint16_t reg16; - unsigned long long tomk, tolmk; + unsigned long long tomk; pci_tolm = find_pci_tolm(&dev->link[0]); @@ -120,13 +126,13 @@ static void pci_domain_set_resources(device_t dev) switch (reg8) { case 0: tseg_size = 1024; - break; + break; /* TSEG = 1M */ case 1: tseg_size = 2048; - break; + break; /* TSEG = 2M */ case 2: tseg_size = 8192; - break; + break; /* TSEG = 8M */ } printk_debug("%dM\n", tseg_size >> 10); @@ -150,24 +156,32 @@ static void pci_domain_set_resources(device_t dev) printk_debug("%dM UMA\n", uma_size >> 10); tomk -= uma_size; + + /* For reserving UMA memory in the memory map */ + uma_memory_base = tomk * 1024ULL; + uma_memory_size = uma_size * 1024ULL; } /* The following needs to be 2 lines, otherwise the second * number is always 0 */ - printk_info("Available memory: %dK", tomk); - printk_info(" (%dM)\n", (tomk >> 10)); - - tolmk = tomk; + printk_info("Available memory: %dK", (uint32_t)tomk); + printk_info(" (%dM)\n", (uint32_t)(tomk >> 10)); /* Report the memory regions */ ram_resource(dev, 3, 0, 640); - ram_resource(dev, 4, 768, (tolmk - 768)); + ram_resource(dev, 4, 768, (tomk - 768)); if (tomk > 4 * 1024 * 1024) { ram_resource(dev, 5, 4096 * 1024, tomk - 4 * 1024 * 1024); } assign_resources(&dev->link[0]); + +#if HAVE_HIGH_TABLES==1 + /* Leave some space for ACPI, PIRQ and MP tables */ + high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024; + high_tables_size = HIGH_TABLES_SIZE * 1024; +#endif } static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max) -- cgit v1.2.3