summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven J. Magnani <steve@digidescorp.com>2005-09-12 18:41:30 +0000
committerSteven J. Magnani <steve@digidescorp.com>2005-09-12 18:41:30 +0000
commitd94e1d6e9dc794401041e0eb4de20c741d3ac71b (patch)
treee32145666cf7ec4f59d32c9aa31fa392b9def580
parent9b945c7cd8a5cc7dab9fdded8172cd575b6129c9 (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.c30
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,