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.

start16.S 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*****************************************************************************
  2. *
  3. * THIS FILE IS NOW OBSOLETE.
  4. *
  5. * The functions of this file are now placed in init.S.
  6. *
  7. *****************************************************************************
  8. */
  9. #ifndef PCBIOS
  10. #error "16bit code is only supported with the PCBIOS"
  11. #endif
  12. #define CODE_SEG 0x08
  13. #define DATA_SEG 0x10
  14. #define EXEC_IN_SITU_MAGIC 0x45524548 /* 'HERE' */
  15. .equ CR0_PE, 1
  16. #ifdef GAS291
  17. #define DATA32 data32;
  18. #define ADDR32 addr32;
  19. #define LJMPI(x) ljmp x
  20. #else
  21. #define DATA32 data32
  22. #define ADDR32 addr32
  23. /* newer GAS295 require #define LJMPI(x) ljmp *x */
  24. #define LJMPI(x) ljmp x
  25. #endif
  26. /*****************************************************************************
  27. *
  28. * start16 : move payload to desired area of memory, set up for exit
  29. * back to prefix, set up for 32-bit code.
  30. *
  31. * Enter (from prefix) with es:di = 0x4552:0x4548 if you want to
  32. * prevent start16 from moving the payload. There are three
  33. * motivations for moving the payload:
  34. *
  35. * 1. It may be in ROM, in which case we need to move it to RAM.
  36. * 2. Whatever loaded us probably didn't know about our memory usage
  37. * beyond the end of the image file. We should claim this memory
  38. * before using it.
  39. *
  40. * Unless the prefix instructs us otherwise we will move the payload to:
  41. *
  42. * An area of memory claimed from the BIOS via 40:13.
  43. *
  44. * We use the main Etherboot stack (within the image target) as our
  45. * stack; we don't rely on the prefix passing us a stack usable for
  46. * anything other than the prefix's return address. The (first 512
  47. * bytes of the) prefix code segment is copied to a safe archive
  48. * location.
  49. *
  50. * When we return to the prefix (from start32), we copy this code back
  51. * to a new area of memory, restore the prefix's ss:sp and ljmp back
  52. * to the copy of the prefix. The prefix will see a return from
  53. * start16 *but* may be executing at a new location. Code following
  54. * the lcall to start16 must therefore be position-independent and
  55. * must also be within [cs:0000,cs:01ff]. We make absolutely no
  56. * guarantees about the stack contents when the prefix regains
  57. * control.
  58. *
  59. * Trashes just about all registers, including all the segment
  60. * registers.
  61. *
  62. *****************************************************************************
  63. */
  64. .text
  65. .code16
  66. .arch i386
  67. .org 0
  68. .globl _start16
  69. _start16:
  70. /*****************************************************************************
  71. * Work out where we are going to place our image (image = optional
  72. * decompressor + runtime). Exit this stage with %ax containing the
  73. * runtime target address divided by 16 (i.e. a real-mode segment
  74. * address).
  75. *****************************************************************************
  76. */
  77. movw %es, %ax
  78. cmpw $(EXEC_IN_SITU_MAGIC >> 16), %ax
  79. jne exec_moved
  80. cmpw $(EXEC_IN_SITU_MAGIC & 0xffff), %di
  81. jne exec_moved
  82. exec_in_situ:
  83. /* Prefix has warned us not to move the payload. Simply
  84. * calculate where the image is going to end up, so we can
  85. * work out where to put our stack.
  86. */
  87. movw %cs, %ax
  88. addw $((payload-_start16)/16), %ax
  89. jmp 99f
  90. exec_moved:
  91. /* Claim an area of base memory from the BIOS and put the
  92. * payload there. arch_relocated_to() will deal with freeing
  93. * up this memory once we've relocated to high memory.
  94. */
  95. movw $0x40, %ax
  96. movw %ax, %es
  97. movw %es:(0x13), %ax /* FBMS in kb to %ax */
  98. shlw $6, %ax /* ... in paragraphs */
  99. subw $__image_size_pgh, %ax /* Subtract space for image */
  100. shrw $6, %ax /* Round down to nearest kb */
  101. movw %ax, %es:(0x13) /* ...and claim memory from BIOS */
  102. shlw $6, %ax
  103. 99:
  104. /* At this point %ax contains the segment address for the
  105. * start of the image (image = optional decompressor + runtime).
  106. */
  107. /*****************************************************************************
  108. * Set up stack in start32's stack space within the place we're going
  109. * to copy Etherboot to, reserve space for GDT, copy return address
  110. * from prefix stack, store prefix stack address
  111. *****************************************************************************
  112. */
  113. popl %esi /* Return address */
  114. mov %ss, %bx /* %es:di = prefix stack address */
  115. mov %bx, %es /* (*after* pop of return address) */
  116. movw %sp, %di
  117. movw $__offset_stack_pgh, %bx /* Set up Etherboot stack */
  118. addw %ax, %bx
  119. movw %bx, %ss
  120. movw $__stack_size, %sp
  121. subw $(_gdt_end - _gdt), %sp /* Reserve space for GDT */
  122. movw %sp, %bp /* Record GDT location */
  123. /* Set up i386_rm_in_call_data_t structure on stack. This is
  124. * the same structure as is set up by rm_in_call.
  125. */
  126. pushl $0 /* Dummy opcode */
  127. pushl %esi /* Prefix return address */
  128. pushfw /* Flags */
  129. pushw %di /* Prefix %sp */
  130. pushw %gs /* Segment registers */
  131. pushw %fs
  132. pushw %es
  133. pushw %ds
  134. pushw %es /* Prefix %ss */
  135. pushw %cs
  136. /* Stack is now 32-bit aligned */
  137. /* %ax still contains image target segment address */
  138. /*****************************************************************************
  139. * Calculate image target and prefix code physical addresses, store on stack
  140. * for use in copy routine.
  141. *****************************************************************************
  142. */
  143. movzwl %es:-2(%di), %ebx /* Prefix code segment */
  144. shll $4, %ebx
  145. pushl %ebx /* Prefix code physical address */
  146. movzwl %ax, %edi /* Image target segment */
  147. shll $4, %edi
  148. pushl %edi /* Image target physical address */
  149. /*****************************************************************************
  150. * Transition to 32-bit protected mode. Set up all segment
  151. * descriptors to use flat physical addresses.
  152. *****************************************************************************
  153. */
  154. /* Copy gdt to area reserved on stack
  155. */
  156. push %cs /* GDT source location -> %ds:%si */
  157. pop %ds
  158. mov $(_gdt - _start16), %si
  159. push %ss /* GDT target location -> %es:%di */
  160. pop %es
  161. mov %bp, %di
  162. mov $(_gdt_end - _gdt), %cx
  163. cld
  164. rep movsb /* Copy GDT to stack */
  165. movl %ss, %eax
  166. shll $4, %eax
  167. movzwl %bp, %ebx
  168. addl %eax, %ebx /* Physical addr of GDT copy -> %ebx */
  169. movl %ebx, 2(%bp) /* Fill in addr field in GDT */
  170. /* Compute the offset I am running at.
  171. */
  172. movl %cs, %ebx
  173. shll $4, %ebx /* %ebx = offset for start16 symbols */
  174. /* Switch to 32bit protected mode.
  175. */
  176. cli /* Disable interrupts */
  177. lgdt (%bp) /* Load GDT from stack */
  178. movl %cr0, %eax /* Set protected mode bit */
  179. orb $CR0_PE, %al
  180. movl %eax, %cr0
  181. movl %ss, %eax /* Convert stack pointer to 32bit */
  182. shll $4, %eax
  183. movzwl %sp, %esp
  184. addl %eax, %esp
  185. movl $DATA_SEG, %eax /* Reload the segment registers */
  186. movl %eax, %ds
  187. movl %eax, %es
  188. movl %eax, %ss
  189. movl %eax, %fs
  190. movl %eax, %gs
  191. /* Flush prefetch queue, and reload %cs:%eip by effectively ljmping
  192. * to code32_start. Do the jump via pushl and lret because the text
  193. * may not be writable/
  194. */
  195. pushl $CODE_SEG
  196. ADDR32 leal (code32_start-_start16)(%ebx), %eax
  197. pushl %eax
  198. DATA32 lret /* DATA32 needed, because we're still in 16-bit mode */
  199. _gdt:
  200. gdtarg:
  201. .word _gdt_end - _gdt - 1 /* limit */
  202. .long 0 /* addr */
  203. .word 0
  204. _pmcs:
  205. /* 32 bit protected mode code segment */
  206. .word 0xffff, 0
  207. .byte 0, 0x9f, 0xcf, 0
  208. _pmds:
  209. /* 32 bit protected mode data segment */
  210. .word 0xffff,0
  211. .byte 0,0x93,0xcf,0
  212. _gdt_end:
  213. .code32
  214. code32_start:
  215. /*****************************************************************************
  216. * Copy payload to target location. Do the copy backwards, since if
  217. * there's overlap with a forward copy then it means start16 is going
  218. * to get trashed during the copy anyway...
  219. *****************************************************************************
  220. */
  221. popl %edi /* Image target physical address */
  222. pushl %edi
  223. leal (payload-_start16)(%ebx), %esi /* Image source physical addr */
  224. movl $__payload_size, %ecx /* Payload size (not image size) */
  225. addl %ecx, %edi /* Start at last byte (length - 1) */
  226. decl %edi
  227. addl %ecx, %esi
  228. decl %esi
  229. std /* Backward copy of image */
  230. rep movsb
  231. cld
  232. popl %edi /* Restore image target physical address */
  233. leal __decompressor_uncompressed(%edi), %ebx
  234. subl $_text, %ebx /* %ebx = offset for runtime symbols */
  235. /*****************************************************************************
  236. * Copy prefix to storage area within Etherboot image.
  237. *****************************************************************************
  238. */
  239. popl %esi /* Prefix source physical address */
  240. pushl %edi
  241. leal _prefix_copy(%ebx), %edi /* Prefix copy phys. addr. */
  242. leal _eprefix_copy(%ebx), %ecx
  243. subl %edi, %ecx /* Prefix copy size */
  244. rep movsb /* Forward copy of prefix */
  245. popl %edi /* Restore image target physical address */
  246. /*****************************************************************************
  247. * Record base memory used by Etherboot image
  248. *****************************************************************************
  249. */
  250. movl %edi, _prefix_image_basemem (%ebx)
  251. /*****************************************************************************
  252. * Jump to start of the image (i.e. the decompressor, or start32 if
  253. * non-compressed).
  254. *****************************************************************************
  255. */
  256. pushl $0 /* Inform start32 that exit path is 16-bit */
  257. jmpl *%edi /* Jump to image */
  258. .balign 16
  259. /* Etherboot needs to be 16byte aligned or data that
  260. * is virtually aligned is no longer physically aligned
  261. * which is just nasty in general. 16byte alignment
  262. * should be sufficient though.
  263. */
  264. payload: