summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2005-04-09 18:42:07 +0200
committerMichael Brown2005-04-09 18:42:07 +0200
commit6a4ac358f3f655eb054041ca989d4138d5dbf2f4 (patch)
treee4cdf0fce21e7fb95f363fd61540de579d410393 /src
parentDon't zero freed base memory; one block will contain librm. (diff)
downloadipxe-6a4ac358f3f655eb054041ca989d4138d5dbf2f4.tar.gz
ipxe-6a4ac358f3f655eb054041ca989d4138d5dbf2f4.tar.xz
ipxe-6a4ac358f3f655eb054041ca989d4138d5dbf2f4.zip
Add INIT_FNs to make sure that librm gets reallocated when needed.
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/transitions/librm_mgmt.c138
1 files changed, 109 insertions, 29 deletions
diff --git a/src/arch/i386/transitions/librm_mgmt.c b/src/arch/i386/transitions/librm_mgmt.c
index bfe963d4..b03716a2 100644
--- a/src/arch/i386/transitions/librm_mgmt.c
+++ b/src/arch/i386/transitions/librm_mgmt.c
@@ -12,6 +12,8 @@
#include "stdint.h"
#include "stddef.h"
#include "string.h"
+#include "init.h"
+#include "basemem.h"
#include "librm.h"
/*
@@ -21,37 +23,14 @@
/* Current location of librm in base memory */
char *installed_librm = librm;
+static uint32_t installed_librm_phys;
-/*
- * Install librm to base memory
- *
+/* Whether or not we have base memory currently allocated for librm.
+ * Note that we *can* have a working librm present in unallocated base
+ * memory; this is the situation at startup for all real-mode
+ * prefixes.
*/
-void install_librm ( void *addr ) {
- memcpy ( addr, librm, librm_size );
- installed_librm = addr;
-}
-
-/*
- * Increment lock count of librm
- *
- */
-void lock_librm ( void ) {
- inst_librm_ref_count++;
-}
-
-/*
- * Decrement lock count of librm
- *
- */
-void unlock_librm ( void ) {
-#ifdef DEBUG_LIBRM
- if ( inst_librm_ref_count == 0 ) {
- printf ( "librm: ref count gone negative\n" );
- lockup();
- }
-#endif
- inst_librm_ref_count--;
-}
+static int allocated_librm = 0;
/*
* Allocate space on the real-mode stack and copy data there.
@@ -84,4 +63,105 @@ void remove_from_rm_stack ( void *data, size_t size ) {
inst_rm_stack.offset += size;
};
+/*
+ * Install librm to base memory
+ *
+ */
+static inline void install_librm ( char *addr ) {
+ memcpy ( addr, librm, librm_size );
+ installed_librm = addr;
+}
+
+/*
+ * Uninstall librm from base memory. This copies librm back to the
+ * "master" copy, so that it can be reinstalled to a new location,
+ * preserving the values for rm_ss and rm_sp from the old installed
+ * copy.
+ *
+ */
+static inline void uninstall_librm ( void ) {
+ memcpy ( librm, installed_librm, librm_size );
+}
+
+/*
+ * On entry, record the physical location of librm. Do this so that
+ * we can update installed_librm after relocation.
+ *
+ * Doing this is probably more efficient than making installed_librm
+ * be a physical address, because of the number of times that
+ * installed_librm gets referenced in the remainder of the code.
+ *
+ */
+static void librm_init ( void ) {
+ installed_librm_phys = virt_to_phys ( installed_librm );
+}
+
+/*
+ * On exit, we want to leave a copy of librm in *unallocated* base
+ * memory. It must be there so that we can exit via a 16-bit exit
+ * path, but it must not be allocated because nothing will ever
+ * deallocate it once we exit.
+ *
+ */
+static void librm_exit ( void ) {
+ /* Free but do not zero the base memory */
+ if ( allocated_librm ) {
+ free_base_memory ( installed_librm, librm_size );
+ allocated_librm = 0;
+ }
+}
+
+/*
+ * On reset, we want to free up our old installed copy of librm, if
+ * any, then allocate a new base memory block and install there.
+ *
+ */
+
+static void librm_reset ( void ) {
+ char *new_librm;
+
+ /* Point installed_librm back at last known physical location */
+ installed_librm = phys_to_virt ( installed_librm_phys );
+
+ /* Uninstall old librm */
+ uninstall_librm();
+
+ /* Free allocated base memory, if applicable */
+ librm_exit();
+
+ /* Allocate space for new librm */
+ new_librm = alloc_base_memory ( librm_size );
+ allocated_librm = 1;
+
+ /* Install new librm */
+ install_librm ( new_librm );
+}
+
+INIT_FN ( INIT_LIBRM, librm_init, librm_reset, librm_exit );
+
+
+
+
+/*
+ * Increment lock count of librm
+ *
+ */
+void lock_librm ( void ) {
+ inst_librm_ref_count++;
+}
+
+/*
+ * Decrement lock count of librm
+ *
+ */
+void unlock_librm ( void ) {
+#ifdef DEBUG_LIBRM
+ if ( inst_librm_ref_count == 0 ) {
+ printf ( "librm: ref count gone negative\n" );
+ lockup();
+ }
+#endif
+ inst_librm_ref_count--;
+}
+
#endif /* KEEP_IT_REAL */