Author: stepan Date: 2009-02-28 00:09:55 +0100 (Sat, 28 Feb 2009) New Revision: 3960
Modified: trunk/coreboot-v2/src/arch/i386/boot/tables.c trunk/coreboot-v2/src/config/Options.lb trunk/coreboot-v2/src/include/boot/tables.h trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/Options.lb trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/acpi_tables.c trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/mainboard.c trunk/coreboot-v2/src/northbridge/intel/i945/northbridge.c Log: 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 stepan@coresystems.de Acked-by: Myles Watson mylesgw@gmail.com
Modified: trunk/coreboot-v2/src/arch/i386/boot/tables.c =================================================================== --- trunk/coreboot-v2/src/arch/i386/boot/tables.c 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/arch/i386/boot/tables.c 2009-02-27 23:09:55 UTC (rev 3960) @@ -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 @@ 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 @@
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 @@ }
// 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 @@ 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(); }
Modified: trunk/coreboot-v2/src/config/Options.lb =================================================================== --- trunk/coreboot-v2/src/config/Options.lb 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/config/Options.lb 2009-02-27 23:09:55 UTC (rev 3960) @@ -1111,6 +1111,18 @@ 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
Modified: trunk/coreboot-v2/src/include/boot/tables.h =================================================================== --- trunk/coreboot-v2/src/include/boot/tables.h 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/include/boot/tables.h 2009-02-27 23:09:55 UTC (rev 3960) @@ -3,6 +3,9 @@
#include <boot/coreboot_tables.h>
+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 */
Modified: trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/Options.lb =================================================================== --- trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/Options.lb 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/Options.lb 2009-02-27 23:09:55 UTC (rev 3960) @@ -29,6 +29,8 @@ 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 @@ ## 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
Modified: trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/acpi_tables.c =================================================================== --- trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/acpi_tables.c 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/acpi_tables.c 2009-02-27 23:09:55 UTC (rev 3960) @@ -289,6 +289,11 @@
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;
Modified: trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/mainboard.c =================================================================== --- trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/mainboard.c 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/mainboard/kontron/986lcd-m/mainboard.c 2009-02-27 23:09:55 UTC (rev 3960) @@ -21,8 +21,30 @@
#include <device/device.h> +#include <console/console.h> +#include <boot/tables.h> #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") };
Modified: trunk/coreboot-v2/src/northbridge/intel/i945/northbridge.c =================================================================== --- trunk/coreboot-v2/src/northbridge/intel/i945/northbridge.c 2009-02-27 17:51:16 UTC (rev 3959) +++ trunk/coreboot-v2/src/northbridge/intel/i945/northbridge.c 2009-02-27 23:09:55 UTC (rev 3960) @@ -93,12 +93,18 @@ 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 @@ 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 @@
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)); + printk_info("Available memory: %dK", (uint32_t)tomk); + printk_info(" (%dM)\n", (uint32_t)(tomk >> 10));
- tolmk = tomk; - /* 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)