diff options
author | Steven J. Magnani <steve@digidescorp.com> | 2005-09-12 18:41:30 +0000 |
---|---|---|
committer | Steven J. Magnani <steve@digidescorp.com> | 2005-09-12 18:41:30 +0000 |
commit | d94e1d6e9dc794401041e0eb4de20c741d3ac71b (patch) | |
tree | e32145666cf7ec4f59d32c9aa31fa392b9def580 | |
parent | 9b945c7cd8a5cc7dab9fdded8172cd575b6129c9 (diff) |
Relocate the GDT to reserved memory, so it won't get clobbered by elfboot(), etc.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2024 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r-- | src/arch/i386/boot/tables.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/arch/i386/boot/tables.c b/src/arch/i386/boot/tables.c index e22530e503..d470abbd27 100644 --- a/src/arch/i386/boot/tables.c +++ b/src/arch/i386/boot/tables.c @@ -7,6 +7,32 @@ #include <arch/acpi.h> #include "linuxbios_table.h" +// Global Descriptor Table, defined in c_start.S +extern uint8_t gdt; +extern uint8_t gdt_end; + +/* i386 lgdt argument */ +struct gdtarg { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +// Copy GDT to new location and reload it +// 2003-07 by SONE Takeshi +// Ported from Etherboot to LinuxBIOS 2005-08 by Steve Magnani +void move_gdt(unsigned long newgdt) +{ + uint16_t num_gdt_bytes = &gdt_end - &gdt; + struct gdtarg gdtarg; + + printk_debug("Moving GDT to %#lx...", newgdt); + memcpy((void*)newgdt, &gdt, num_gdt_bytes); + gdtarg.base = newgdt; + gdtarg.limit = num_gdt_bytes - 1; + __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); + printk_debug("ok\n"); +} + struct lb_memory *write_tables(void) { unsigned long low_table_start, low_table_end; @@ -45,6 +71,10 @@ struct lb_memory *write_tables(void) 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, |