Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

libkir.S 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * libkir: a transition library for -DKEEP_IT_REAL
  3. *
  4. * Michael Brown <mbrown@fensystems.co.uk>
  5. *
  6. */
  7. /****************************************************************************
  8. * This file defines libkir: an interface between external and
  9. * internal environments when -DKEEP_IT_REAL is used, so that both
  10. * internal and external environments are in real mode. It deals with
  11. * switching data segments and the stack. It provides the following
  12. * functions:
  13. *
  14. * ext_to_kir & switch between external and internal (kir)
  15. * kir_to_ext environments, preserving all non-segment
  16. * registers
  17. *
  18. * kir_call issue a call to an internal routine from external
  19. * code
  20. *
  21. * libkir is written to avoid assuming that segments are anything
  22. * other than opaque data types, and also avoids assuming that the
  23. * stack pointer is 16-bit. This should enable it to run just as well
  24. * in 16:16 or 16:32 protected mode as in real mode.
  25. ****************************************************************************
  26. */
  27. /* Breakpoint for when debugging under bochs */
  28. #define BOCHSBP xchgw %bx, %bx
  29. .text
  30. .arch i386
  31. .section ".text16", "awx", @progbits
  32. .code16
  33. /****************************************************************************
  34. * ext_to_kir (real-mode or 16:xx protected-mode near call)
  35. *
  36. * Switch from external stack and segment registers to internal stack
  37. * and segment registers. %ss:sp is restored from the saved kir_ds
  38. * and kir_sp. %ds, %es, %fs and %gs are all restored from the saved
  39. * kir_ds. All other registers are preserved.
  40. *
  41. * %cs:0000 must point to the start of the runtime image code segment
  42. * on entry.
  43. *
  44. * Note that this routine can be called *without* having first set up
  45. * a stored kir_ds and kir_sp. If you do this, ext_to_kir will return
  46. * without altering the segment registers or stack pointer.
  47. *
  48. * Parameters: none
  49. ****************************************************************************
  50. */
  51. .globl ext_to_kir
  52. ext_to_kir:
  53. /* Record external segment registers */
  54. movw %ds, %cs:ext_ds
  55. pushw %cs
  56. popw %ds /* Set %ds = %cs for easier access to variables */
  57. movw %es, %ds:ext_es
  58. movw %fs, %ds:ext_fs
  59. movw %gs, %ds:ext_fs
  60. /* Preserve registers */
  61. movw %ax, %ds:save_ax
  62. /* Extract near return address from stack */
  63. popw %ds:save_retaddr
  64. /* Record external %ss:esp */
  65. movw %ss, %ds:ext_ss
  66. movl %esp, %ds:ext_esp
  67. /* Load internal segment registers and stack pointer, if available */
  68. movw %ds:kir_ds, %ax
  69. testw %ax, %ax
  70. jz 1f
  71. movw %ax, %ss
  72. movzwl %ds:kir_sp, %esp
  73. movw %ax, %ds
  74. movw %ax, %es
  75. movw %ax, %fs
  76. movw %ax, %gs
  77. 1:
  78. /* Place return address on new stack */
  79. pushw %cs:save_retaddr
  80. /* Restore registers and return */
  81. movw %cs:save_ax, %ax
  82. ret
  83. /****************************************************************************
  84. * kir_to_ext (real-mode or 16:xx protected-mode near call)
  85. *
  86. * Switch from internal stack and segment registers to external stack
  87. * and segment registers. %ss:%esp is restored from the saved ext_ss
  88. * and ext_esp. Other segment registers are restored from the
  89. * corresponding locations. All other registers are preserved.
  90. *
  91. * Note that it is actually %ss that is recorded as kir_ds, on the
  92. * assumption that %ss == %ds when kir_to_ext is called.
  93. *
  94. * Parameters: none
  95. ****************************************************************************
  96. */
  97. .globl kir_to_ext
  98. kir_to_ext:
  99. /* Record near return address */
  100. pushw %cs
  101. popw %ds /* Set %ds = %cs for easier access to variables */
  102. popw %ds:save_retaddr
  103. /* Record internal segment registers and %sp */
  104. movw %ss, %ds:kir_ds
  105. movw %sp, %ds:kir_sp
  106. /* Load external segment registers and stack pointer */
  107. movw %ds:ext_ss, %ss
  108. movl %ds:ext_esp, %esp
  109. movw %ds:ext_gs, %gs
  110. movw %ds:ext_fs, %fs
  111. movw %ds:ext_es, %es
  112. movw %ds:ext_ds, %ds
  113. /* Return */
  114. pushw %cs:save_retaddr
  115. ret
  116. /****************************************************************************
  117. * kir_call (real-mode or 16:xx protected-mode far call)
  118. *
  119. * Call a specific C function in the internal code. The prototype of
  120. * the C function must be
  121. * void function ( struct real_mode_regs *rm_regs );
  122. * rm_regs will point to a struct containing the real-mode registers
  123. * at entry to kir_call.
  124. *
  125. * All registers will be preserved across kir_call(), unless the C
  126. * function explicitly overwrites values in rm_regs. Interrupt status
  127. * will also be preserved.
  128. *
  129. * Parameters:
  130. * function : (16-bit) virtual address of protected-mode function to call
  131. *
  132. * Example usage:
  133. * pushw $pxe_api_call
  134. * lcall $UNDI_CS, $kir_call
  135. * addw $2, %sp
  136. * to call in to the C function
  137. * void pxe_api_call ( struct real_mode_regs *rm_regs );
  138. ****************************************************************************
  139. */
  140. .globl kir_call
  141. kir_call:
  142. /* Preserve flags. Must do this before any operation that may
  143. * affect flags.
  144. */
  145. pushfl
  146. popl %cs:save_flags
  147. /* Disable interrupts. We do funny things with the stack, and
  148. * we're not re-entrant.
  149. */
  150. cli
  151. /* Extract address of internal routine from stack. We must do
  152. * this without using (%bp), because we may be called with
  153. * either a 16-bit or a 32-bit stack segment.
  154. */
  155. popl %cs:save_retaddr /* Scratch location */
  156. popw %cs:save_function
  157. subl $6, %esp /* Restore %esp */
  158. /* Switch to internal stack. Note that the external stack is
  159. * inaccessible once we're running internally (since we have
  160. * no concept of 48-bit far pointers)
  161. */
  162. call ext_to_kir
  163. /* Store external registers on internal stack */
  164. pushl %cs:save_flags
  165. pushal
  166. pushl %cs:ext_fs_and_gs
  167. pushl %cs:ext_ds_and_es
  168. pushl %cs:ext_cs_and_ss
  169. /* Push &rm_regs on stack and call function */
  170. pushl %esp
  171. data32 call *%cs:save_function
  172. popl %eax /* discard */
  173. /* Restore external registers from internal stack */
  174. popl %cs:ext_cs_and_ss
  175. popl %cs:ext_ds_and_es
  176. popl %cs:ext_fs_and_gs
  177. popal
  178. popl %cs:save_flags
  179. /* Switch to external stack */
  180. call kir_to_ext
  181. /* Restore flags */
  182. pushl %cs:save_flags
  183. popfl
  184. /* Return */
  185. lret
  186. /****************************************************************************
  187. * Stored internal and external stack and segment registers
  188. ****************************************************************************
  189. */
  190. ext_cs_and_ss:
  191. ext_cs: .word 0
  192. ext_ss: .word 0
  193. ext_ds_and_es:
  194. ext_ds: .word 0
  195. ext_es: .word 0
  196. ext_fs_and_gs:
  197. ext_fs: .word 0
  198. ext_gs: .word 0
  199. ext_esp: .long 0
  200. .globl kir_ds
  201. kir_ds: .word 0
  202. .globl kir_sp
  203. kir_sp: .word 0
  204. /****************************************************************************
  205. * Temporary variables
  206. ****************************************************************************
  207. */
  208. save_ax: .word 0
  209. save_retaddr: .word 0
  210. save_flags: .long 0
  211. save_function: .long 0