summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2005-04-10 20:18:37 +0200
committerMichael Brown2005-04-10 20:18:37 +0200
commitf06e8c9707ed93d9dd98bdbfc498ddf86d8d13c8 (patch)
tree72020fa0d1223409225f367196fb6378b2709343 /src
parentRemoved obsolete initialisation calls. (diff)
downloadipxe-f06e8c9707ed93d9dd98bdbfc498ddf86d8d13c8.tar.gz
ipxe-f06e8c9707ed93d9dd98bdbfc498ddf86d8d13c8.tar.xz
ipxe-f06e8c9707ed93d9dd98bdbfc498ddf86d8d13c8.zip
Added post-relocation function table.
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/core/relocate.c25
-rw-r--r--src/arch/i386/include/relocate.h20
-rw-r--r--src/arch/i386/scripts/i386.lds5
3 files changed, 40 insertions, 10 deletions
diff --git a/src/arch/i386/core/relocate.c b/src/arch/i386/core/relocate.c
index 98734535a..3a2702a1f 100644
--- a/src/arch/i386/core/relocate.c
+++ b/src/arch/i386/core/relocate.c
@@ -2,6 +2,7 @@
#include "memsizes.h"
#include "osdep.h"
#include "etherboot.h"
+#include "init.h"
#include "relocate.h"
#ifndef KEEP_IT_REAL
@@ -38,6 +39,8 @@ extern char _max_align[];
/* Linker symbols */
extern char _text[];
extern char _end[];
+extern struct post_reloc_fn post_reloc_fns[];
+extern struct post_reloc_fn post_reloc_fns_end[];
#undef DBG
#ifdef DEBUG_RELOCATE
@@ -46,9 +49,10 @@ extern char _end[];
#define DBG(...)
#endif
-void relocate ( void ) {
+static void relocate ( void ) {
unsigned long addr, eaddr, size;
unsigned i;
+ struct post_reloc_fn *post_reloc_fn;
/* Walk through the memory map and find the highest address
* below 4GB that etherboot will fit into. Ensure etherboot
@@ -186,12 +190,23 @@ void relocate ( void ) {
relocate_to ( addr );
/* Note that we cannot make real-mode calls
- * (e.g. printf) at this point, because the pointer
- * installed_librm uses a virtual address (in order
- * that it can have a valid initialiser) and so is
- * currently invalid.
+ * (e.g. printf) at this point, because librm has just
+ * been moved to high memory.
*/
+
+ /* Call any registered post-relocation functions.
+ * librm has a post-relocation function to install a
+ * new librm into base memory.
+ */
+ for ( post_reloc_fn = post_reloc_fns;
+ post_reloc_fn < post_reloc_fns_end ; post_reloc_fn++ ) {
+ if ( post_reloc_fn->post_reloc )
+ post_reloc_fn->post_reloc ();
+ }
+
}
}
+INIT_FN ( INIT_RELOCATE, relocate, NULL, NULL );
+
#endif /* ! KEEP_IT_REAL */
diff --git a/src/arch/i386/include/relocate.h b/src/arch/i386/include/relocate.h
index 4aec54e48..31965d4fb 100644
--- a/src/arch/i386/include/relocate.h
+++ b/src/arch/i386/include/relocate.h
@@ -1,14 +1,24 @@
#ifndef RELOCATE_H
#define RELOCATE_H
-#ifdef KEEP_IT_REAL
-
/* relocate() is conceptually impossible with KEEP_IT_REAL */
-#define relocate()
+#ifndef KEEP_IT_REAL
+
+/* An entry in the post-relocation function table */
+struct post_reloc_fn {
+ void ( *post_reloc ) ( void );
+};
-#else
+/* Use double digits to avoid problems with "10" < "9" on alphabetic sort */
+#define POST_RELOC_LIBRM "00"
-extern void relocate ( void );
+/* Macro for creating a post-relocation function table entry */
+#define POST_RELOC_FN( post_reloc_order, post_reloc_func ) \
+ static struct post_reloc_fn post_reloc_functions \
+ __attribute__ (( used, __section__( ".post_reloc_fns." \
+ post_reloc_order ) )) = { \
+ .post_reloc = post_reloc_func, \
+ };
#endif
diff --git a/src/arch/i386/scripts/i386.lds b/src/arch/i386/scripts/i386.lds
index 4f9df5619..6888da364 100644
--- a/src/arch/i386/scripts/i386.lds
+++ b/src/arch/i386/scripts/i386.lds
@@ -140,6 +140,8 @@ SECTIONS {
__data = .;
*(.data)
*(.data.*)
+
+ /* Various tables */
pci_drivers = .;
*(.drivers.pci)
pci_drivers_end = .;
@@ -149,6 +151,9 @@ SECTIONS {
console_drivers = .;
*(.drivers.console)
console_drivers_end = .;
+ post_reloc_fns = .;
+ *(SORT(.post_reloc_fns.*))
+ post_reloc_fns_end = .;
init_fns = .;
*(SORT(.init_fns.*))
init_fns_end = .;