aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-09-25 11:34:06 -0400
committerKevin O'Connor <kevin@koconnor.net>2010-09-25 11:34:06 -0400
commit7f55fd306854cc305cce6f8d8738a14e4ed01999 (patch)
treed4ba42ac013214c6fb42c9cebc68d20c251423d4
parent025cabd2caa41d567d06a7c43f910621b99e64a4 (diff)
downloadseabios-hppa-7f55fd306854cc305cce6f8d8738a14e4ed01999.zip
seabios-hppa-7f55fd306854cc305cce6f8d8738a14e4ed01999.tar.gz
seabios-hppa-7f55fd306854cc305cce6f8d8738a14e4ed01999.tar.bz2
Move the 32bit init code to high memory at runtime.
Add support for moving the 32bit init code out of the e/f-segments and into temporary ram. Update the relocations in the code so that it can live at its new address. This frees up memory for other uses in the e/f segments.
-rw-r--r--src/config.h2
-rw-r--r--src/post.c58
2 files changed, 58 insertions, 2 deletions
diff --git a/src/config.h b/src/config.h
index 4572ee5..f9bf3b8 100644
--- a/src/config.h
+++ b/src/config.h
@@ -26,6 +26,8 @@
#define CONFIG_THREADS 1
// Allow hardware init to run in parallel with optionrom execution
#define CONFIG_THREAD_OPTIONROMS 0
+// Support relocating the one time initialization code to high memory
+#define CONFIG_RELOCATE_INIT 1
// Support int13 disk/floppy drive functions
#define CONFIG_DRIVES 1
// Support floppy drive access
diff --git a/src/post.c b/src/post.c
index 4d99935..4a75f51 100644
--- a/src/post.c
+++ b/src/post.c
@@ -183,7 +183,7 @@ init_hw(void)
}
// Begin the boot process by invoking an int0x19 in 16bit mode.
-static void
+void VISIBLE32FLAT
startBoot(void)
{
// Clear low-memory allocations (required by PMM spec).
@@ -268,9 +268,63 @@ maininit(void)
startBoot();
}
+
+/****************************************************************
+ * Code relocation
+ ****************************************************************/
+
+// Update given relocs for the code at 'dest' with a given 'delta'
+static void
+updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta)
+{
+ u32 *reloc;
+ for (reloc = rstart; reloc < rend; reloc++)
+ *((u32*)(dest + *reloc)) += delta;
+}
+
+// Start of Power On Self Test - the BIOS initilization. This
+// function sets up for and attempts relocation of the init code.
+static void
+reloc_init(void)
+{
+ if (!CONFIG_RELOCATE_INIT) {
+ maininit();
+ return;
+ }
+ // Symbols populated by the build.
+ extern u8 code32flat_start[];
+ extern u8 _reloc_min_align[];
+ extern u32 _reloc_abs_start[], _reloc_abs_end[];
+ extern u32 _reloc_rel_start[], _reloc_rel_end[];
+ extern u32 _reloc_init_start[], _reloc_init_end[];
+ extern u8 code32init_start[], code32init_end[];
+
+ // Allocate space for init code.
+ u32 initsize = code32init_end - code32init_start;
+ u32 align = (u32)&_reloc_min_align;
+ void *dest = memalign_tmp(align, initsize);
+ if (!dest)
+ panic("No space for init relocation.\n");
+
+ // Copy code and update relocs (init absolute, init relative, and runtime)
+ dprintf(1, "Relocating init from %p to %p (size %d)\n"
+ , code32init_start, dest, initsize);
+ s32 delta = dest - (void*)code32init_start;
+ memcpy(dest, code32init_start, initsize);
+ updateRelocs(dest, _reloc_abs_start, _reloc_abs_end, delta);
+ updateRelocs(dest, _reloc_rel_start, _reloc_rel_end, -delta);
+ updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta);
+
+ // Call maininit() in relocated code.
+ void (*func)(void) = (void*)maininit + delta;
+ barrier();
+ func();
+}
+
static int HaveRunPost;
// Start of Power On Self Test (POST) - the BIOS initilization phase.
+// This function sets up for and attempts relocation of the init code.
void VISIBLE32INIT
post(void)
{
@@ -285,7 +339,7 @@ post(void)
ram_probe();
malloc_setup();
- maininit();
+ reloc_init();
}