You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

libkir.S 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. * init_libkir (real-mode or 16:xx protected-mode far call)
  35. *
  36. * Initialise libkir ready for transitions to the kir environment
  37. *
  38. * Parameters:
  39. * %cs : .text16 segment
  40. * %ds : .data16 segment
  41. ****************************************************************************
  42. */
  43. .globl init_libkir
  44. init_libkir:
  45. /* Record segment registers */
  46. pushw %ds
  47. popw %cs:kir_ds
  48. lret
  49. /****************************************************************************
  50. * ext_to_kir (real-mode or 16:xx protected-mode near call)
  51. *
  52. * Switch from external stack and segment registers to internal stack
  53. * and segment registers. %ss:sp is restored from the saved kir_ds
  54. * and kir_sp. %ds, %es, %fs and %gs are all restored from the saved
  55. * kir_ds. All other registers are preserved.
  56. *
  57. * %cs:0000 must point to the start of the runtime image code segment
  58. * on entry.
  59. *
  60. * Parameters: none
  61. ****************************************************************************
  62. */
  63. .globl ext_to_kir
  64. ext_to_kir:
  65. /* Record external segment registers */
  66. movw %ds, %cs:ext_ds
  67. pushw %cs
  68. popw %ds /* Set %ds = %cs for easier access to variables */
  69. movw %es, %ds:ext_es
  70. movw %fs, %ds:ext_fs
  71. movw %gs, %ds:ext_fs
  72. /* Preserve registers */
  73. movw %ax, %ds:save_ax
  74. /* Extract near return address from stack */
  75. popw %ds:save_retaddr
  76. /* Record external %ss:esp */
  77. movw %ss, %ds:ext_ss
  78. movl %esp, %ds:ext_esp
  79. /* Load internal segment registers and stack pointer */
  80. movw %ds:kir_ds, %ax
  81. movw %ax, %ss
  82. movzwl %ds:kir_sp, %esp
  83. movw %ax, %ds
  84. movw %ax, %es
  85. movw %ax, %fs
  86. movw %ax, %gs
  87. 1:
  88. /* Place return address on new stack */
  89. pushw %cs:save_retaddr
  90. /* Restore registers and return */
  91. movw %cs:save_ax, %ax
  92. ret
  93. /****************************************************************************
  94. * kir_to_ext (real-mode or 16:xx protected-mode near call)
  95. *
  96. * Switch from internal stack and segment registers to external stack
  97. * and segment registers. %ss:%esp is restored from the saved ext_ss
  98. * and ext_esp. Other segment registers are restored from the
  99. * corresponding locations. All other registers are preserved.
  100. *
  101. * Note that it is actually %ss that is recorded as kir_ds, on the
  102. * assumption that %ss == %ds when kir_to_ext is called.
  103. *
  104. * Parameters: none
  105. ****************************************************************************
  106. */
  107. .globl kir_to_ext
  108. kir_to_ext:
  109. /* Record near return address */
  110. pushw %cs
  111. popw %ds /* Set %ds = %cs for easier access to variables */
  112. popw %ds:save_retaddr
  113. /* Record internal segment registers and %sp */
  114. movw %ss, %ds:kir_ds
  115. movw %sp, %ds:kir_sp
  116. /* Load external segment registers and stack pointer */
  117. movw %ds:ext_ss, %ss
  118. movl %ds:ext_esp, %esp
  119. movw %ds:ext_gs, %gs
  120. movw %ds:ext_fs, %fs
  121. movw %ds:ext_es, %es
  122. movw %ds:ext_ds, %ds
  123. /* Return */
  124. pushw %cs:save_retaddr
  125. ret
  126. /****************************************************************************
  127. * kir_call (real-mode or 16:xx protected-mode far call)
  128. *
  129. * Call a specific C function in the internal code. The prototype of
  130. * the C function must be
  131. * void function ( struct i386_all_resg *ix86 );
  132. * ix86 will point to a struct containing the real-mode registers
  133. * at entry to kir_call.
  134. *
  135. * All registers will be preserved across kir_call(), unless the C
  136. * function explicitly overwrites values in ix86. Interrupt status
  137. * will also be preserved.
  138. *
  139. * Parameters:
  140. * function : (32-bit) virtual address of C function to call
  141. *
  142. * Example usage:
  143. * pushl $pxe_api_call
  144. * lcall $UNDI_CS, $kir_call
  145. * addw $4, %sp
  146. * to call in to the C function
  147. * void pxe_api_call ( struct i386_all_regs *ix86 );
  148. ****************************************************************************
  149. */
  150. .globl kir_call
  151. kir_call:
  152. /* Preserve flags. Must do this before any operation that may
  153. * affect flags.
  154. */
  155. pushfl
  156. popl %cs:save_flags
  157. /* Disable interrupts. We do funny things with the stack, and
  158. * we're not re-entrant.
  159. */
  160. cli
  161. /* Extract address of internal routine from stack. We must do
  162. * this without using (%bp), because we may be called with
  163. * either a 16-bit or a 32-bit stack segment.
  164. */
  165. popl %cs:save_retaddr /* Scratch location */
  166. popl %cs:save_function
  167. subl $8, %esp /* Restore %esp */
  168. /* Switch to internal stack. Note that the external stack is
  169. * inaccessible once we're running internally (since we have
  170. * no concept of 48-bit far pointers)
  171. */
  172. call ext_to_kir
  173. /* Store external registers on internal stack */
  174. pushl %cs:save_flags
  175. pushal
  176. pushl %cs:ext_fs_and_gs
  177. pushl %cs:ext_ds_and_es
  178. pushl %cs:ext_cs_and_ss
  179. /* Push &ix86 on stack and call function */
  180. sti
  181. pushl %esp
  182. data32 call *%cs:save_function
  183. popl %eax /* discard */
  184. /* Restore external registers from internal stack */
  185. popl %cs:ext_cs_and_ss
  186. popl %cs:ext_ds_and_es
  187. popl %cs:ext_fs_and_gs
  188. popal
  189. popl %cs:save_flags
  190. /* Switch to external stack */
  191. call kir_to_ext
  192. /* Restore flags */
  193. pushl %cs:save_flags
  194. popfl
  195. /* Return */
  196. lret
  197. /****************************************************************************
  198. * Stored internal and external stack and segment registers
  199. ****************************************************************************
  200. */
  201. ext_cs_and_ss:
  202. ext_cs: .word 0
  203. ext_ss: .word 0
  204. ext_ds_and_es:
  205. ext_ds: .word 0
  206. ext_es: .word 0
  207. ext_fs_and_gs:
  208. ext_fs: .word 0
  209. ext_gs: .word 0
  210. ext_esp: .long 0
  211. .globl kir_ds
  212. kir_ds: .word 0
  213. .globl kir_sp
  214. kir_sp: .word _estack
  215. /****************************************************************************
  216. * Temporary variables
  217. ****************************************************************************
  218. */
  219. save_ax: .word 0
  220. save_retaddr: .long 0
  221. save_flags: .long 0
  222. save_function: .long 0