選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

librm_mgmt.c 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 "init.h"
  14. #include "basemem.h"
  15. #include "librm.h"
  16. /*
  17. * This file provides functions for managing librm.
  18. *
  19. */
  20. /* Current location of librm in base memory */
  21. char *installed_librm = librm;
  22. /* Whether or not we have base memory currently allocated for librm.
  23. * Note that we *can* have a working librm present in unallocated base
  24. * memory; this is the situation at startup for all real-mode
  25. * prefixes.
  26. */
  27. static int allocated_librm = 0;
  28. /*
  29. * Allocate space on the real-mode stack and copy data there.
  30. *
  31. */
  32. uint16_t copy_to_rm_stack ( void *data, size_t size ) {
  33. #ifdef DEBUG_LIBRM
  34. if ( inst_rm_stack.offset <= size ) {
  35. printf ( "librm: out of space in RM stack\n" );
  36. lockup();
  37. }
  38. #endif
  39. inst_rm_stack.offset -= size;
  40. copy_to_real ( inst_rm_stack.segment, inst_rm_stack.offset,
  41. data, size );
  42. return inst_rm_stack.offset;
  43. };
  44. /*
  45. * Deallocate space on the real-mode stack, optionally copying back
  46. * data.
  47. *
  48. */
  49. void remove_from_rm_stack ( void *data, size_t size ) {
  50. if ( data ) {
  51. copy_from_real ( data,
  52. inst_rm_stack.segment, inst_rm_stack.offset,
  53. size );
  54. }
  55. inst_rm_stack.offset += size;
  56. };
  57. /*
  58. * Install librm to base memory
  59. *
  60. */
  61. static void install_librm ( char *addr ) {
  62. librm_base = virt_to_phys ( addr );
  63. memcpy ( addr, librm, librm_size );
  64. installed_librm = addr;
  65. }
  66. /*
  67. * Uninstall librm from base memory. This copies librm back to the
  68. * "master" copy, so that it can be reinstalled to a new location,
  69. * preserving the values for rm_ss and rm_sp from the old installed
  70. * copy.
  71. *
  72. */
  73. static void uninstall_librm ( void ) {
  74. memcpy ( librm, installed_librm, librm_size );
  75. librm_base = 0;
  76. }
  77. /*
  78. * If librm isn't installed (i.e. if we have librm, but weren't
  79. * entered via it), then install librm and a real-mode stack to a
  80. * fixed temporary location, just so that we can e.g. issue printf()
  81. *
  82. * [ If we were entered via librm, then the real_to_prot call will
  83. * have filled in librm_base. ]
  84. */
  85. static void librm_init ( void ) {
  86. if ( ! librm_base ) {
  87. install_librm ( phys_to_virt ( 0x7c00 ) );
  88. inst_rm_stack.segment = 0x7c0;
  89. inst_rm_stack.offset = 0x1000;
  90. }
  91. }
  92. /*
  93. * On exit, we want to leave a copy of librm in *unallocated* base
  94. * memory. It must be there so that we can exit via a 16-bit exit
  95. * path, but it must not be allocated because nothing will ever
  96. * deallocate it once we exit.
  97. *
  98. */
  99. static void librm_exit ( void ) {
  100. /* Free but do not zero the base memory */
  101. if ( allocated_librm ) {
  102. free_base_memory ( installed_librm, librm_size );
  103. allocated_librm = 0;
  104. }
  105. }
  106. /*
  107. * Reset gets called immediately after relocation.
  108. *
  109. */
  110. static void librm_reset ( void ) {
  111. char *new_librm;
  112. /* Point installed_librm back at last known physical location.
  113. * Do this in case we have just relocated and the virtual
  114. * address has therefore changed. */
  115. installed_librm = phys_to_virt ( librm_base );
  116. /* Free allocated base memory, if applicable */
  117. librm_exit();
  118. /* Allocate space for new librm */
  119. new_librm = alloc_base_memory ( librm_size );
  120. allocated_librm = 1;
  121. /* Install new librm */
  122. install_librm ( new_librm );
  123. }
  124. INIT_FN ( INIT_LIBRM, librm_init, librm_reset, librm_exit );
  125. /*
  126. * Increment lock count of librm
  127. *
  128. */
  129. void lock_librm ( void ) {
  130. inst_librm_ref_count++;
  131. }
  132. /*
  133. * Decrement lock count of librm
  134. *
  135. */
  136. void unlock_librm ( void ) {
  137. #ifdef DEBUG_LIBRM
  138. if ( inst_librm_ref_count == 0 ) {
  139. printf ( "librm: ref count gone negative\n" );
  140. lockup();
  141. }
  142. #endif
  143. inst_librm_ref_count--;
  144. }
  145. #endif /* KEEP_IT_REAL */