#include "memsizes.h"
#include "osdep.h"
#include "etherboot.h"
+#include "init.h"
#include "relocate.h"
#ifndef KEEP_IT_REAL
/* 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
#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
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 */
#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