選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

libflat.S 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Copyright (C) 2010 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. FILE_LICENCE ( GPL2_OR_LATER )
  20. .arch i386
  21. #define CR0_PE 1
  22. /****************************************************************************
  23. * flatten_real_mode
  24. *
  25. * Set up 4GB segment limits
  26. *
  27. * Parameters:
  28. * none
  29. * Returns:
  30. * none
  31. * Corrupts:
  32. * none
  33. ****************************************************************************
  34. */
  35. /* GDT for protected-mode calls */
  36. .section ".text16.early.data", "aw", @progbits
  37. .align 16
  38. flatten_gdt:
  39. flatten_gdt_limit: .word flatten_gdt_length - 1
  40. flatten_gdt_base: .long 0
  41. .word 0 /* padding */
  42. flatten_cs: /* 16-bit protected-mode flat code segment */
  43. .equ FLAT_CS, flatten_cs - flatten_gdt
  44. .word 0xffff, 0
  45. .byte 0, 0x9b, 0x8f, 0
  46. flatten_ss: /* 16-bit protected-mode flat stack segment */
  47. .equ FLAT_SS, flatten_ss - flatten_gdt
  48. .word 0xffff, 0
  49. .byte 0, 0x93, 0x8f, 0
  50. flatten_gdt_end:
  51. .equ flatten_gdt_length, . - flatten_gdt
  52. .size flatten_gdt, . - flatten_gdt
  53. .section ".text16.early.data", "aw", @progbits
  54. .align 16
  55. flatten_saved_gdt:
  56. .long 0, 0
  57. .size flatten_saved_gdt, . - flatten_saved_gdt
  58. .section ".text16.early", "awx", @progbits
  59. .code16
  60. flatten_real_mode:
  61. /* Preserve registers and flags */
  62. pushfl
  63. pushl %eax
  64. pushw %si
  65. pushw %gs
  66. pushw %fs
  67. pushw %es
  68. pushw %ds
  69. pushw %ss
  70. /* Set %ds for access to .text16.early.data variables */
  71. pushw %cs
  72. popw %ds
  73. /* Preserve original GDT */
  74. sgdt flatten_saved_gdt
  75. /* Set up GDT bases */
  76. xorl %eax, %eax
  77. movw %cs, %ax
  78. shll $4, %eax
  79. addl $flatten_gdt, %eax
  80. movl %eax, flatten_gdt_base
  81. movw %cs, %ax
  82. movw $flatten_cs, %si
  83. call set_seg_base
  84. movw %ss, %ax
  85. movw $flatten_ss, %si
  86. call set_seg_base
  87. /* Switch temporarily to protected mode and set segment registers */
  88. pushw %cs
  89. pushw $2f
  90. cli
  91. data32 lgdt flatten_gdt
  92. movl %cr0, %eax
  93. orb $CR0_PE, %al
  94. movl %eax, %cr0
  95. ljmp $FLAT_CS, $1f
  96. 1: movw $FLAT_SS, %ax
  97. movw %ax, %ss
  98. movw %ax, %ds
  99. movw %ax, %es
  100. movw %ax, %fs
  101. movw %ax, %gs
  102. movl %cr0, %eax
  103. andb $0!CR0_PE, %al
  104. movl %eax, %cr0
  105. lret
  106. 2: /* lret will ljmp to here */
  107. /* Restore GDT, registers and flags */
  108. data32 lgdt flatten_saved_gdt
  109. popw %ss
  110. popw %ds
  111. popw %es
  112. popw %fs
  113. popw %gs
  114. popw %si
  115. popl %eax
  116. popfl
  117. ret
  118. .size flatten_real_mode, . - flatten_real_mode
  119. .section ".text16.early", "awx", @progbits
  120. .code16
  121. set_seg_base:
  122. rolw $4, %ax
  123. movw %ax, 2(%si)
  124. andw $0xfff0, 2(%si)
  125. movb %al, 4(%si)
  126. andb $0x0f, 4(%si)
  127. ret
  128. .size set_seg_base, . - set_seg_base
  129. /****************************************************************************
  130. * test_a20_short, test_a20_long
  131. *
  132. * Check to see if A20 line is enabled
  133. *
  134. * Parameters:
  135. * none
  136. * Returns:
  137. * CF set if A20 line is not enabled
  138. * Corrupts:
  139. * none
  140. ****************************************************************************
  141. */
  142. #define TEST_A20_SHORT_MAX_RETRIES 0x20
  143. #define TEST_A20_LONG_MAX_RETRIES 0x200000
  144. .section ".text16.early", "awx", @progbits
  145. .code16
  146. test_a20_short:
  147. pushl %ecx
  148. movl $TEST_A20_SHORT_MAX_RETRIES, %ecx
  149. jmp 1f
  150. .size test_a20_short, . - test_a20_short
  151. test_a20_long:
  152. pushl %ecx
  153. movl $TEST_A20_LONG_MAX_RETRIES, %ecx
  154. 1: pushw %ax
  155. /* Flatten real mode so we can access the test pattern's 1MB offset */
  156. call flatten_real_mode
  157. 2: /* Modify and check test pattern; succeed if we see a difference */
  158. incw %cs:test_a20_data
  159. addr32 movw %cs:(test_a20_data + 0x100000 ), %ax
  160. cmpw %cs:test_a20_data, %ax
  161. clc
  162. jnz 99f
  163. /* Delay and retry */
  164. outb %al, $0x80
  165. addr32 loop 2b
  166. stc
  167. 99: /* Restore registers and return */
  168. popw %ax
  169. popl %ecx
  170. ret
  171. .size test_a20_long, . - test_a20_long
  172. .section ".text16.early.data", "aw", @progbits
  173. .align 2
  174. test_a20_data:
  175. .word 0xdead
  176. .size test_a20_data, . - test_a20_data
  177. /****************************************************************************
  178. * enable_a20_bios
  179. *
  180. * Try enabling A20 line via BIOS
  181. *
  182. * Parameters:
  183. * none
  184. * Returns:
  185. * CF set if A20 line is not enabled
  186. * Corrupts:
  187. * none
  188. ****************************************************************************
  189. */
  190. .section ".text16.early", "awx", @progbits
  191. .code16
  192. enable_a20_bios:
  193. /* Preserve registers */
  194. pushw %ax
  195. /* Attempt INT 15,2401 */
  196. movw $0x2401, %ax
  197. int $0x15
  198. jc 99f
  199. /* Check that success was really successful */
  200. call test_a20_short
  201. 99: /* Restore registers and return */
  202. popw %ax
  203. ret
  204. .size enable_a20_bios, . - enable_a20_bios
  205. /****************************************************************************
  206. * enable_a20_kbc
  207. *
  208. * Try enabling A20 line via keyboard controller
  209. *
  210. * Parameters:
  211. * none
  212. * Returns:
  213. * CF set if A20 line is not enabled
  214. * Corrupts:
  215. * none
  216. ****************************************************************************
  217. */
  218. #define KC_RDWR 0x60
  219. #define KC_RDWR_SET_A20 0xdf
  220. #define KC_CMD 0x64
  221. #define KC_CMD_WOUT 0xd1
  222. #define KC_CMD_NULL 0xff
  223. #define KC_STATUS 0x64
  224. #define KC_STATUS_OBUF_FULL 0x01
  225. #define KC_STATUS_IBUF_FULL 0x02
  226. #define KC_MAX_RETRIES 100000
  227. .section ".text16.early", "awx", @progbits
  228. .code16
  229. enable_a20_kbc:
  230. /* Preserve registers */
  231. pushw %ax
  232. /* Try keyboard controller */
  233. call empty_kbc
  234. movb $KC_CMD_WOUT, %al
  235. outb %al, $KC_CMD
  236. call empty_kbc
  237. movb $KC_RDWR_SET_A20, %al
  238. outb %al, $KC_RDWR
  239. call empty_kbc
  240. movb $KC_CMD_NULL, %al
  241. outb %al, $KC_CMD
  242. call empty_kbc
  243. /* Check to see if it worked */
  244. call test_a20_long
  245. /* Restore registers and return */
  246. popw %ax
  247. ret
  248. .size enable_a20_kbc, . - enable_a20_kbc
  249. .section ".text16.early", "awx", @progbits
  250. .code16
  251. empty_kbc:
  252. /* Preserve registers */
  253. pushl %ecx
  254. pushw %ax
  255. /* Wait for KBC to become empty */
  256. movl $KC_MAX_RETRIES, %ecx
  257. 1: outb %al, $0x80
  258. inb $KC_STATUS, %al
  259. testb $( KC_STATUS_OBUF_FULL | KC_STATUS_IBUF_FULL ), %al
  260. jz 99f
  261. testb $KC_STATUS_OBUF_FULL, %al
  262. jz 2f
  263. outb %al, $0x80
  264. inb $KC_RDWR, %al
  265. 2: addr32 loop 1b
  266. 99: /* Restore registers and return */
  267. popw %ax
  268. popl %ecx
  269. ret
  270. .size empty_kbc, . - empty_kbc
  271. /****************************************************************************
  272. * enable_a20_fast
  273. *
  274. * Try enabling A20 line via "Fast Gate A20"
  275. *
  276. * Parameters:
  277. * none
  278. * Returns:
  279. * CF set if A20 line is not enabled
  280. * Corrupts:
  281. * none
  282. ****************************************************************************
  283. */
  284. #define SCP_A 0x92
  285. .section ".text16.early", "awx", @progbits
  286. .code16
  287. enable_a20_fast:
  288. /* Preserve registers */
  289. pushw %ax
  290. /* Try "Fast Gate A20" */
  291. inb $SCP_A, %al
  292. orb $0x02, %al
  293. andb $~0x01, %al
  294. outb %al, $SCP_A
  295. /* Check to see if it worked */
  296. call test_a20_long
  297. /* Restore registers and return */
  298. popw %ax
  299. ret
  300. .size enable_a20_fast, . - enable_a20_fast
  301. /****************************************************************************
  302. * enable_a20
  303. *
  304. * Try enabling A20 line via any available method
  305. *
  306. * Parameters:
  307. * none
  308. * Returns:
  309. * CF set if A20 line is not enabled
  310. * Corrupts:
  311. * none
  312. ****************************************************************************
  313. */
  314. #define ENABLE_A20_RETRIES 255
  315. .section ".text16.early", "awx", @progbits
  316. .code16
  317. .globl enable_a20
  318. enable_a20:
  319. /* Preserve registers */
  320. pushl %ecx
  321. pushw %ax
  322. /* Check to see if A20 is already enabled */
  323. call test_a20_short
  324. jnc 99f
  325. /* Use known working method, if we have one */
  326. movw %cs:enable_a20_method, %ax
  327. testw %ax, %ax
  328. jz 1f
  329. call *%ax
  330. jmp 99f
  331. 1:
  332. /* Try all methods in turn until one works */
  333. movl $ENABLE_A20_RETRIES, %ecx
  334. 2: movw $enable_a20_bios, %ax
  335. movw %ax, %cs:enable_a20_method
  336. call *%ax
  337. jnc 99f
  338. movw $enable_a20_kbc, %ax
  339. movw %ax, %cs:enable_a20_method
  340. call *%ax
  341. jnc 99f
  342. movw $enable_a20_fast, %ax
  343. movw %ax, %cs:enable_a20_method
  344. call *%ax
  345. jnc 99f
  346. addr32 loop 2b
  347. /* Failure; exit with carry set */
  348. movw $0, %cs:enable_a20_method
  349. stc
  350. 99: /* Restore registers and return */
  351. popw %ax
  352. popl %ecx
  353. ret
  354. .section ".text16.early.data", "aw", @progbits
  355. .align 2
  356. enable_a20_method:
  357. .word 0
  358. .size enable_a20_method, . - enable_a20_method
  359. /****************************************************************************
  360. * access_highmem (real mode far call)
  361. *
  362. * Open up access to high memory in flat real mode with A20 enabled
  363. *
  364. * Parameters:
  365. * none
  366. * Returns:
  367. * CF set if high memory could not be accessed
  368. * Corrupts:
  369. * none
  370. ****************************************************************************
  371. */
  372. .section ".text16.early", "awx", @progbits
  373. .code16
  374. .globl access_highmem
  375. access_highmem:
  376. /* Enable A20 line */
  377. call enable_a20
  378. /* CPU will be in flat real mode as a result of this call */
  379. lret
  380. .size access_highmem, . - access_highmem