Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

librm_mgmt.c 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * librm: a library for interfacing to real-mode code
  3. *
  4. * Michael Brown <mbrown@fensystems.co.uk>
  5. *
  6. */
  7. #ifdef KEEP_IT_REAL
  8. /* Build a null object under -DKEEP_IT_REAL */
  9. #else
  10. #include "stdint.h"
  11. #include "stddef.h"
  12. #include "string.h"
  13. #include "basemem.h"
  14. #include "relocate.h"
  15. #include <gpxe/init.h>
  16. #include "librm.h"
  17. /*
  18. * This file provides functions for managing librm.
  19. *
  20. */
  21. /* Current location of librm in base memory */
  22. char *installed_librm = librm;
  23. /* Whether or not we have base memory currently allocated for librm.
  24. * Note that we *can* have a working librm present in unallocated base
  25. * memory; this is the situation at startup for all real-mode
  26. * prefixes.
  27. */
  28. static int allocated_librm = 0;
  29. /*
  30. * Allocate space on the real-mode stack and copy data there.
  31. *
  32. */
  33. uint16_t copy_to_rm_stack ( void *data, size_t size ) {
  34. #ifdef DEBUG_LIBRM
  35. if ( inst_rm_stack.offset <= size ) {
  36. printf ( "librm: out of space in RM stack\n" );
  37. lockup();
  38. }
  39. #endif
  40. inst_rm_stack.offset -= size;
  41. copy_to_real ( inst_rm_stack.segment, inst_rm_stack.offset,
  42. data, size );
  43. return inst_rm_stack.offset;
  44. };
  45. /*
  46. * Deallocate space on the real-mode stack, optionally copying back
  47. * data.
  48. *
  49. */
  50. void remove_from_rm_stack ( void *data, size_t size ) {
  51. if ( data ) {
  52. copy_from_real ( data,
  53. inst_rm_stack.segment, inst_rm_stack.offset,
  54. size );
  55. }
  56. inst_rm_stack.offset += size;
  57. };
  58. /*
  59. * Install librm to base memory
  60. *
  61. */
  62. static void install_librm ( char *addr ) {
  63. librm_base = virt_to_phys ( addr );
  64. memcpy ( addr, librm, librm_size );
  65. installed_librm = addr;
  66. }
  67. /*
  68. * Uninstall librm from base memory. This copies librm back to the
  69. * "master" copy, so that it can be reinstalled to a new location,
  70. * preserving the values for rm_ss and rm_sp from the old installed
  71. * copy.
  72. *
  73. * We deliberately leave the old copy intact and effectively installed
  74. * (apart from being in unallocated memory) so that we can use it for
  75. * any real-mode calls required when allocating memory for the new
  76. * copy, or for the real-mode exit path.
  77. */
  78. static void uninstall_librm ( void ) {
  79. /* Copy installed librm back to master copy */
  80. memcpy ( librm, installed_librm, librm_size );
  81. /* Free but do not zero the base memory */
  82. if ( allocated_librm ) {
  83. free_base_memory ( installed_librm, librm_size );
  84. allocated_librm = 0;
  85. }
  86. }
  87. /*
  88. * If librm isn't installed (i.e. if we have librm, but weren't
  89. * entered via it), then install librm and a real-mode stack to a
  90. * fixed temporary location, just so that we can e.g. issue printf()
  91. *
  92. * [ If we were entered via librm, then the real_to_prot call will
  93. * have filled in librm_base. ]
  94. */
  95. static void librm_init ( void ) {
  96. if ( ! librm_base ) {
  97. install_librm ( phys_to_virt ( 0x7c00 ) );
  98. inst_rm_stack.segment = 0x7c0;
  99. inst_rm_stack.offset = 0x1000;
  100. }
  101. }
  102. /*
  103. * librm_post_reloc gets called immediately after relocation.
  104. *
  105. */
  106. static void librm_post_reloc ( void ) {
  107. /* Point installed_librm back at last known physical location.
  108. */
  109. installed_librm = phys_to_virt ( librm_base );
  110. /* Allocate base memory for librm and place a copy there */
  111. if ( ! allocated_librm ) {
  112. char *new_librm = alloc_base_memory ( librm_size );
  113. uninstall_librm ();
  114. install_librm ( new_librm );
  115. allocated_librm = 1;
  116. }
  117. }
  118. INIT_FN ( INIT_LIBRM, librm_init, NULL, uninstall_librm );
  119. POST_RELOC_FN ( POST_RELOC_LIBRM, librm_post_reloc );
  120. /*
  121. * Wrapper for initialise() when librm is being used. We have to
  122. * install a copy of librm to allocated base memory and return the
  123. * pointer to this new librm's entry point via es:di.
  124. *
  125. */
  126. void initialise_via_librm ( struct i386_all_regs *ix86 ) {
  127. /* Hand off to initialise() */
  128. initialise ();
  129. /* Point es:di to new librm's entry point. Fortunately, di is
  130. * already set up by setup16, so all we need to do is point
  131. * es:0000 to the start of the new librm.
  132. */
  133. ix86->segs.es = librm_base >> 4;
  134. }
  135. /*
  136. * Increment lock count of librm
  137. *
  138. */
  139. void lock_librm ( void ) {
  140. inst_librm_ref_count++;
  141. }
  142. /*
  143. * Decrement lock count of librm
  144. *
  145. */
  146. void unlock_librm ( void ) {
  147. #ifdef DEBUG_LIBRM
  148. if ( inst_librm_ref_count == 0 ) {
  149. printf ( "librm: ref count gone negative\n" );
  150. lockup();
  151. }
  152. #endif
  153. inst_librm_ref_count--;
  154. }
  155. #endif /* KEEP_IT_REAL */