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.9KB

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