]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
Add INIT_FNs to make sure that librm gets reallocated when needed.
authorMichael Brown <mcb30@etherboot.org>
Sat, 9 Apr 2005 16:42:07 +0000 (16:42 +0000)
committerMichael Brown <mcb30@etherboot.org>
Sat, 9 Apr 2005 16:42:07 +0000 (16:42 +0000)
src/arch/i386/transitions/librm_mgmt.c

index bfe963d4196c2f470f17e654b871e5a46281c5c7..b03716a2028163ac048a5a3332853d876ec97e21 100644 (file)
@@ -12,6 +12,8 @@
 #include "stdint.h"
 #include "stddef.h"
 #include "string.h"
+#include "init.h"
+#include "basemem.h"
 #include "librm.h"
 
 /*
 
 /* 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 */