X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Farch%2Fi386%2Fboot%2Ftables.c;h=f6f7625f75b2008d2c2ef709d2079525f08a6501;hb=8f047de352d26c353c1c6bc9649a4616fa66bbd6;hp=8abac2b748e9357f59816c9ece429e8f8f8b7f23;hpb=4f1cb2342630e806399b2febafc8c215a8bf6059;p=coreboot.git diff --git a/src/arch/i386/boot/tables.c b/src/arch/i386/boot/tables.c index 8abac2b74..f6f7625f7 100644 --- a/src/arch/i386/boot/tables.c +++ b/src/arch/i386/boot/tables.c @@ -1,14 +1,35 @@ +/* + * 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 */ #include #include #include -#include +#include #include #include #include -#include "linuxbios_table.h" +#include +#include +#include "coreboot_table.h" // Global Descriptor Table, defined in c_start.S extern uint8_t gdt; @@ -22,7 +43,7 @@ struct gdtarg { // Copy GDT to new location and reload it // 2003-07 by SONE Takeshi -// Ported from Etherboot to LinuxBIOS 2005-08 by Steve Magnani +// Ported from Etherboot to coreboot 2005-08 by Steve Magnani void move_gdt(unsigned long newgdt) { uint16_t num_gdt_bytes = &gdt_end - &gdt; @@ -36,12 +57,36 @@ 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 low_table_start, low_table_end; unsigned long rom_table_start, rom_table_end; +#if HAVE_MP_TABLE == 1 && HAVE_LOW_TABLES == 1 + unsigned long new_low_table_end; +#endif + +#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=0, high_table_end=0; + + if (high_tables_base) { + printk_debug("High Tables Base is %llx.\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_start = 0xf0000; rom_table_end = 0xf0000; /* Start low addr at 16 bytes instead of 0 because of a buglet * in the generic linux unzip code, as it tests for the a20 line. @@ -51,62 +96,127 @@ 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 linuxbios table out of first 4K if set up in low table area - */ - + * pushes coreboot table out of first 4K if set up in low table area + */ +#if HAVE_ACPI_TABLES == 1 +#if HAVE_HIGH_TABLES == 1 +#if HAVE_LOW_TABLES == 1 + unsigned long high_rsdp=ALIGN(high_table_end, 16); +#endif + if (high_tables_base) { + high_table_end = write_acpi_tables(high_table_end); + high_table_end = (high_table_end+1023) & ~1023; + } +#if HAVE_LOW_TABLES == 1 + unsigned long rsdt_location=(unsigned long*)(((acpi_rsdp_t*)high_rsdp)->rsdt_address); + acpi_write_rsdp(rom_table_end, rsdt_location); + rom_table_end = ALIGN(ALIGN(rom_table_end, 16) + sizeof(acpi_rsdp_t), 16); +#endif +#else +#if HAVE_LOW_TABLES == 1 rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = (rom_table_end+1023) & ~1023; - +#endif +#endif +#endif /* copy the smp block to address 0 */ post_code(0x96); - /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ - new_low_table_end = write_smp_table(low_table_end); +#if HAVE_MP_TABLE == 1 + /* 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 /* 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... */ - if(new_low_table_end>0x467){ - unsigned mptable_size = new_low_table_end - low_table_end - SMP_FLOATING_TABLE_LEN; - /* We can not put mptable here, we need to copy them to somewhere else*/ - if((rom_table_end+mptable_size)<0x100000) { - /* We can copy mptable on rom_table, and leave low space for lbtable */ - printk_debug("move mptable to 0x%0x\n", rom_table_end); - memcpy((unsigned char *)rom_table_end, (unsigned char *)(low_table_end+SMP_FLOATING_TABLE_LEN), mptable_size); - memset((unsigned char *)low_table_end, '\0', mptable_size + SMP_FLOATING_TABLE_LEN); - smp_write_floating_table_physaddr(low_table_end, rom_table_end); - low_table_end += SMP_FLOATING_TABLE_LEN; - rom_table_end += mptable_size; - rom_table_end = (rom_table_end+1023) & ~1023; - } else { - /* We can need to put mptable low and from 0x500 */ - printk_debug("move mptable to 0x%0x\n", 0x500); - memcpy((unsigned char *)0x500, (unsigned char *)(low_table_end+SMP_FLOATING_TABLE_LEN), mptable_size); - memset((unsigned char *)low_table_end, '\0', 0x500-low_table_end); - smp_write_floating_table_physaddr(low_table_end, 0x500); - low_table_end = 0x500 + mptable_size; - } - } - - /* Don't write anything in the traditional x86 BIOS data segment */ + if(new_low_table_end>0x400){ + unsigned mptable_size; + unsigned mpc_start; + low_table_end += SMP_FLOATING_TABLE_LEN; /* keep the mpf in 1k low, so kernel can find it */ + mptable_size = new_low_table_end - low_table_end; + /* We can not put mptable low, we need to copy them to somewhere else*/ + if((rom_table_end+mptable_size)<0x100000) { + /* We can copy mptable on rom_table */ + mpc_start = rom_table_end; + rom_table_end += mptable_size; + rom_table_end = (rom_table_end+1023) & ~1023; + } else { + /* We can need to put mptable before rom_table */ + mpc_start = rom_table_start - mptable_size; + mpc_start &= ~1023; + rom_table_start = mpc_start; + } + printk_debug("move mptable from 0x%0lx to 0x%0x, size 0x%0x\n", low_table_end, mpc_start, mptable_size); + memcpy((unsigned char *)mpc_start, (unsigned char *)low_table_end, mptable_size); + smp_write_floating_table_physaddr(low_table_end - SMP_FLOATING_TABLE_LEN, mpc_start); + memset((unsigned char *)low_table_end, '\0', mptable_size); + } +#endif /* HAVE_LOW_TABLES */ + +#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 +#endif /* HAVE_MP_TABLE */ + if (low_table_end < 0x500) { low_table_end = 0x500; } // Relocate the GDT to reserved memory, so it won't get clobbered - move_gdt(low_table_end); - low_table_end += &gdt_end - &gdt; - - /* The linuxbios table must be in 0-4K or 960K-1M */ - write_linuxbios_table( - low_table_start, low_table_end, +#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 */ + mbi = (struct multiboot_info *)rom_table_end; + rom_table_end = write_multiboot_info( + low_table_start, low_table_end, + rom_table_start, rom_table_end); +#endif + +#if HAVE_HIGH_TABLES == 1 + if (high_tables_base) { + write_coreboot_table(low_table_start, low_table_end, + high_table_start, high_table_end); + } else { + printk_err("ERROR: No high_tables_base.\n"); + write_coreboot_table(low_table_start, low_table_end, rom_table_start, rom_table_end); - + } +#else + /* The coreboot table must be in 0-4K or 960K-1M */ + write_coreboot_table(low_table_start, low_table_end, + rom_table_start, rom_table_end); +#endif + return get_lb_mem(); }