[SeaBIOS] [PATCH 10/11] Move the 32bit init code to high memory at runtime.
Kevin O'Connor
kevin at koconnor.net
Thu Sep 16 04:40:55 CEST 2010
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.
---
src/config.h | 2 ++
src/post.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 52 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..a93affc 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,57 @@ maininit(void)
startBoot();
}
+
+/****************************************************************
+ * Code relocation
+ ****************************************************************/
+
+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;
+ }
+ 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[];
+
+ 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");
+
+ 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);
+ 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 +333,7 @@ post(void)
ram_probe();
malloc_setup();
- maininit();
+ reloc_init();
}
--
1.7.2.3
More information about the SeaBIOS
mailing list