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.

libprefix.S 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. */
  19. #define CR0_PE 1
  20. .arch i386
  21. .section ".prefix.lib", "awx", @progbits
  22. .section ".data16", "aw", @progbits
  23. /****************************************************************************
  24. * install_block (real-mode near call)
  25. *
  26. * Install block to specified address
  27. *
  28. * Parameters:
  29. * %esi : byte offset within loaded image (must be a multiple of 16)
  30. * %es:edi : destination address
  31. * %ecx : length of (decompressed) data
  32. * %edx : total length of block (including any uninitialised data portion)
  33. * Returns:
  34. * none
  35. * Corrupts:
  36. * %esi, %edi, %ecx, %edx
  37. ****************************************************************************
  38. */
  39. .section ".prefix.lib"
  40. .code16
  41. install_block:
  42. /* Preserve registers */
  43. pushw %ds
  44. pushl %eax
  45. /* Starting segment => %ds */
  46. movw %cs, %ax
  47. shrl $4, %esi
  48. addw %si, %ax
  49. movw %ax, %ds
  50. xorl %esi, %esi
  51. /* Calculate start and length of uninitialised data portion */
  52. leal (%edi,%ecx), %eax
  53. subl %ecx, %edx
  54. /* Do the copy */
  55. cld
  56. rep addr32 movsb /* or "call decompress16" */
  57. /* Zero remaining space */
  58. movl %eax, %edi
  59. movl %edx, %ecx
  60. xorb %al, %al
  61. rep addr32 stosb
  62. /* Restore registers */
  63. popl %eax
  64. popw %ds
  65. ret
  66. .size install_block, . - install_block
  67. /****************************************************************************
  68. * alloc_basemem (real-mode near call)
  69. *
  70. * Allocate space for .text16 and .data16 from top of base memory.
  71. * Memory is allocated using the BIOS free base memory counter at
  72. * 0x40:13.
  73. *
  74. * Parameters:
  75. * none
  76. * Returns:
  77. * %ax : .text16 segment address
  78. * %bx : .data16 segment address
  79. * Corrupts:
  80. * none
  81. ****************************************************************************
  82. */
  83. .section ".prefix.lib"
  84. .code16
  85. alloc_basemem:
  86. /* FBMS => %ax as segment address */
  87. movw $0x40, %ax
  88. movw %ax, %fs
  89. movw %fs:0x13, %ax
  90. shlw $6, %ax
  91. /* .data16 segment address */
  92. subw $_data16_size, %ax
  93. pushw %ax
  94. /* .text16 segment address */
  95. subw $_text16_size, %ax
  96. pushw %ax
  97. /* Update FBMS */
  98. shrw $6, %ax
  99. movw %ax, %fs:0x13
  100. /* Return */
  101. popw %ax
  102. popw %bx
  103. ret
  104. .size alloc_basemem, . - alloc_basemem
  105. /****************************************************************************
  106. * install_basemem (real-mode near call)
  107. *
  108. * Install .text16 and .data16 into base memory
  109. *
  110. * Parameters:
  111. * %ax : .text16 segment address
  112. * %bx : .data16 segment address
  113. * Returns:
  114. * none
  115. * Corrupts:
  116. * none
  117. ****************************************************************************
  118. */
  119. .section ".prefix.lib"
  120. .code16
  121. install_basemem:
  122. /* Preserve registers */
  123. pushw %es
  124. pushl %esi
  125. pushl %edi
  126. pushl %ecx
  127. pushl %edx
  128. /* Install .text16 */
  129. movw %ax, %es
  130. xorl %edi, %edi
  131. movl $_text16_load_offset, %esi
  132. movl $_text16_size, %ecx
  133. movl %ecx, %edx
  134. call install_block
  135. /* Install .data16 */
  136. movw %bx, %es
  137. xorl %edi, %edi
  138. movl $_data16_load_offset, %esi
  139. movl $_data16_progbits_size, %ecx
  140. movl $_data16_size, %edx
  141. call install_block
  142. /* Restore registers */
  143. popl %edx
  144. popl %ecx
  145. popl %edi
  146. popl %esi
  147. popw %es
  148. ret
  149. .size install_basemem, . - install_basemem
  150. /****************************************************************************
  151. * install_highmem (flat real-mode near call)
  152. *
  153. * Install .text and .data into high memory
  154. *
  155. * Parameters:
  156. * %es:edi : address in high memory
  157. * Returns:
  158. * none
  159. * Corrupts:
  160. * none
  161. ****************************************************************************
  162. */
  163. #ifndef KEEP_IT_REAL
  164. .section ".prefix.lib"
  165. .code16
  166. install_highmem:
  167. /* Preserve registers */
  168. pushl %esi
  169. pushl %edi
  170. pushl %ecx
  171. pushl %edx
  172. /* Install .text and .data to specified address */
  173. movl $_textdata_load_offset, %esi
  174. movl $_textdata_progbits_size, %ecx
  175. movl $_textdata_size, %edx
  176. call install_block
  177. /* Restore registers and interrupt status */
  178. popl %edx
  179. popl %ecx
  180. popl %edi
  181. popl %esi
  182. ret
  183. .size install_highmem, . - install_highmem
  184. #endif /* KEEP_IT_REAL */
  185. /****************************************************************************
  186. * GDT for flat real mode
  187. *
  188. * We only ever use this GDT to set segment limits; the bases are
  189. * unused. Also, we only flatten data segments, so we don't need to
  190. * worry about the code or stack segments. This makes everything much
  191. * simpler.
  192. ****************************************************************************
  193. */
  194. #ifndef KEEP_IT_REAL
  195. .section ".prefix.lib"
  196. .align 16
  197. gdt:
  198. gdt_limit: .word gdt_length - 1
  199. gdt_base: .long 0
  200. .word 0 /* padding */
  201. flat_ds: /* Flat real mode data segment */
  202. .equ FLAT_DS, flat_ds - gdt
  203. .word 0xffff, 0
  204. .byte 0, 0x93, 0xcf, 0
  205. gdt_end:
  206. .equ gdt_length, gdt_end - gdt
  207. .size gdt, . - gdt
  208. #endif /* KEEP_IT_REAL */
  209. /****************************************************************************
  210. * flatten_real_mode (real-mode near call)
  211. *
  212. * Sets 4GB limits on the data segments %ds and %es.
  213. *
  214. * Parameters:
  215. * none
  216. ****************************************************************************
  217. */
  218. #ifndef KEEP_IT_REAL
  219. .section ".prefix.lib"
  220. .code16
  221. flatten_real_mode:
  222. /* Preserve real-mode segment values and temporary registers */
  223. pushw %es
  224. pushw %ds
  225. pushl %eax
  226. /* Set GDT base and load GDT */
  227. xorl %eax, %eax
  228. movw %cs, %ax
  229. shll $4, %eax
  230. addl $gdt, %eax
  231. movl %eax, %cs:gdt_base
  232. lgdt %cs:gdt
  233. /* Switch to protected mode */
  234. movl %cr0, %eax
  235. orb $CR0_PE, %al
  236. movl %eax, %cr0
  237. /* Set flat segment limits */
  238. movw $FLAT_DS, %ax
  239. movw %ax, %ds
  240. movw %ax, %es
  241. /* Switch back to real mode */
  242. movl %cr0, %eax
  243. andb $0!CR0_PE, %al
  244. movl %eax, %cr0
  245. /* Restore real-mode segment values and temporary registers */
  246. popl %eax
  247. popw %ds
  248. popw %es
  249. ret
  250. .size flatten_real_mode, . - flatten_real_mode
  251. #endif /* KEEP_IT_REAL */
  252. /****************************************************************************
  253. * install (real-mode near call)
  254. * install_prealloc (real-mode near call)
  255. *
  256. * Install all text and data segments.
  257. *
  258. * Parameters:
  259. * %ax : .text16 segment address (install_prealloc only)
  260. * %bx : .data16 segment address (install_prealloc only)
  261. * Returns:
  262. * %ax : .text16 segment address
  263. * %bx : .data16 segment address
  264. * %edi : .text physical address (if applicable)
  265. * Corrupts:
  266. * none
  267. ****************************************************************************
  268. */
  269. .section ".prefix.lib"
  270. .code16
  271. .globl install
  272. install:
  273. /* Allocate space for .text16 and .data16 */
  274. call alloc_basemem
  275. .size install, . - install
  276. .globl install_prealloc
  277. install_prealloc:
  278. /* Install .text16 and .data16 */
  279. call install_basemem
  280. #ifndef KEEP_IT_REAL
  281. /* Preserve registers and interrupt status, and disable interrupts */
  282. pushfw
  283. pushw %ds
  284. pushw %es
  285. pushl %esi
  286. pushl %ecx
  287. cli
  288. /* Load up %ds and %es, and set up vectors for far calls to .text16 */
  289. movw %bx, %ds
  290. xorw %si, %si
  291. movw %si, %es
  292. movw %ax, (init_librm_vector+2)
  293. movw %ax, (prot_call_vector+2)
  294. /* Install .text and .data to 2MB mark. Use 2MB to avoid
  295. * problems with A20.
  296. */
  297. call flatten_real_mode
  298. movl $(2<<20), %edi
  299. call install_highmem
  300. /* Set up initial protected-mode GDT, call relocate().
  301. * relocate() will return with %esi, %edi and %ecx set up
  302. * ready for the copy to the new location.
  303. */
  304. lcall *init_librm_vector
  305. pushl $relocate
  306. lcall *prot_call_vector
  307. addw $4, %sp
  308. /* Move code to new location, set up new protected-mode GDT */
  309. call flatten_real_mode
  310. pushl %edi
  311. es rep addr32 movsb
  312. popl %edi
  313. lcall *init_librm_vector
  314. /* Hide Etherboot from BIOS memory map. Note that making this
  315. * protected-mode call will also restore normal (non-flat)
  316. * real mode, as part of the protected-to-real transition.
  317. */
  318. pushl $hide_etherboot
  319. lcall *prot_call_vector
  320. addw $4, %sp
  321. /* Restore registers and interrupt status */
  322. popl %ecx
  323. popl %esi
  324. popw %es
  325. popw %ds
  326. popfw
  327. #endif
  328. ret
  329. .size install_prealloc, . - install_prealloc
  330. #ifndef KEEP_IT_REAL
  331. /* Vectors for far calls to .text16 functions */
  332. .section ".data16"
  333. init_librm_vector:
  334. .word init_librm
  335. .word 0
  336. .size init_librm_vector, . - init_librm_vector
  337. prot_call_vector:
  338. .word prot_call
  339. .word 0
  340. .size prot_call_vector, . - prot_call_vector
  341. #endif