您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

libprefix.S 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  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. FILE_LICENCE ( GPL2_OR_LATER )
  20. .arch i386
  21. /**
  22. * High memory temporary load address
  23. *
  24. * Temporary buffer into which to copy (or decompress) our runtime
  25. * image, prior to calling get_memmap() and relocate(). We don't
  26. * actually leave anything here once install() has returned.
  27. */
  28. .globl HIGHMEM_LOADPOINT
  29. .equ HIGHMEM_LOADPOINT, ( 1 << 20 )
  30. /* Image compression enabled */
  31. #define COMPRESS 1
  32. /*****************************************************************************
  33. * Utility function: print character (with LF -> LF,CR translation)
  34. *
  35. * Parameters:
  36. * %al : character to print
  37. * %ds:di : output buffer (or %di=0 to print to console)
  38. * Returns:
  39. * %ds:di : next character in output buffer (if applicable)
  40. *****************************************************************************
  41. */
  42. .section ".prefix.lib", "awx", @progbits
  43. .code16
  44. .globl print_character
  45. print_character:
  46. /* Preserve registers */
  47. pushw %ax
  48. pushw %bx
  49. pushw %bp
  50. /* If %di is non-zero, write character to buffer and exit */
  51. testw %di, %di
  52. jz 1f
  53. movb %al, %ds:(%di)
  54. incw %di
  55. jmp 3f
  56. 1: /* Print character */
  57. movw $0x0007, %bx /* page 0, attribute 7 (normal) */
  58. movb $0x0e, %ah /* write char, tty mode */
  59. cmpb $0x0a, %al /* '\n'? */
  60. jne 2f
  61. int $0x10
  62. movb $0x0d, %al
  63. 2: int $0x10
  64. /* Restore registers and return */
  65. 3: popw %bp
  66. popw %bx
  67. popw %ax
  68. ret
  69. .size print_character, . - print_character
  70. /*****************************************************************************
  71. * Utility function: print a NUL-terminated string
  72. *
  73. * Parameters:
  74. * %ds:si : string to print
  75. * %ds:di : output buffer (or %di=0 to print to console)
  76. * Returns:
  77. * %ds:si : character after terminating NUL
  78. * %ds:di : next character in output buffer (if applicable)
  79. *****************************************************************************
  80. */
  81. .section ".prefix.lib", "awx", @progbits
  82. .code16
  83. .globl print_message
  84. print_message:
  85. /* Preserve registers */
  86. pushw %ax
  87. /* Print string */
  88. 1: lodsb
  89. testb %al, %al
  90. je 2f
  91. call print_character
  92. jmp 1b
  93. 2: /* Restore registers and return */
  94. popw %ax
  95. ret
  96. .size print_message, . - print_message
  97. /*****************************************************************************
  98. * Utility functions: print hex digit/byte/word/dword
  99. *
  100. * Parameters:
  101. * %al (low nibble) : digit to print
  102. * %al : byte to print
  103. * %ax : word to print
  104. * %eax : dword to print
  105. * %ds:di : output buffer (or %di=0 to print to console)
  106. * Returns:
  107. * %ds:di : next character in output buffer (if applicable)
  108. *****************************************************************************
  109. */
  110. .section ".prefix.lib", "awx", @progbits
  111. .code16
  112. .globl print_hex_dword
  113. print_hex_dword:
  114. rorl $16, %eax
  115. call print_hex_word
  116. rorl $16, %eax
  117. /* Fall through */
  118. .size print_hex_dword, . - print_hex_dword
  119. .globl print_hex_word
  120. print_hex_word:
  121. xchgb %al, %ah
  122. call print_hex_byte
  123. xchgb %al, %ah
  124. /* Fall through */
  125. .size print_hex_word, . - print_hex_word
  126. .globl print_hex_byte
  127. print_hex_byte:
  128. rorb $4, %al
  129. call print_hex_nibble
  130. rorb $4, %al
  131. /* Fall through */
  132. .size print_hex_byte, . - print_hex_byte
  133. .globl print_hex_nibble
  134. print_hex_nibble:
  135. /* Preserve registers */
  136. pushw %ax
  137. /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
  138. andb $0x0f, %al
  139. cmpb $10, %al
  140. sbbb $0x69, %al
  141. das
  142. call print_character
  143. /* Restore registers and return */
  144. popw %ax
  145. ret
  146. .size print_hex_nibble, . - print_hex_nibble
  147. /*****************************************************************************
  148. * Utility function: print PCI bus:dev.fn
  149. *
  150. * Parameters:
  151. * %ax : PCI bus:dev.fn to print
  152. * %ds:di : output buffer (or %di=0 to print to console)
  153. * Returns:
  154. * %ds:di : next character in output buffer (if applicable)
  155. *****************************************************************************
  156. */
  157. .section ".prefix.lib", "awx", @progbits
  158. .code16
  159. .globl print_pci_busdevfn
  160. print_pci_busdevfn:
  161. /* Preserve registers */
  162. pushw %ax
  163. /* Print bus */
  164. xchgb %al, %ah
  165. call print_hex_byte
  166. /* Print ":" */
  167. movb $( ':' ), %al
  168. call print_character
  169. /* Print device */
  170. movb %ah, %al
  171. shrb $3, %al
  172. call print_hex_byte
  173. /* Print "." */
  174. movb $( '.' ), %al
  175. call print_character
  176. /* Print function */
  177. movb %ah, %al
  178. andb $0x07, %al
  179. call print_hex_nibble
  180. /* Restore registers and return */
  181. popw %ax
  182. ret
  183. .size print_pci_busdevfn, . - print_pci_busdevfn
  184. /*****************************************************************************
  185. * Utility function: clear current line
  186. *
  187. * Parameters:
  188. * %ds:di : output buffer (or %di=0 to print to console)
  189. * Returns:
  190. * %ds:di : next character in output buffer (if applicable)
  191. *****************************************************************************
  192. */
  193. .section ".prefix.lib", "awx", @progbits
  194. .code16
  195. .globl print_kill_line
  196. print_kill_line:
  197. /* Preserve registers */
  198. pushw %ax
  199. pushw %cx
  200. /* Print CR */
  201. movb $( '\r' ), %al
  202. call print_character
  203. /* Print 79 spaces */
  204. movb $( ' ' ), %al
  205. movw $79, %cx
  206. 1: call print_character
  207. loop 1b
  208. /* Print CR */
  209. movb $( '\r' ), %al
  210. call print_character
  211. /* Restore registers and return */
  212. popw %cx
  213. popw %ax
  214. ret
  215. .size print_kill_line, . - print_kill_line
  216. /****************************************************************************
  217. * copy_bytes
  218. *
  219. * Copy bytes
  220. *
  221. * Parameters:
  222. * %ds:esi : source address
  223. * %es:edi : destination address
  224. * %ecx : length
  225. * Returns:
  226. * %ds:esi : next source address
  227. * %es:edi : next destination address
  228. * Corrupts:
  229. * None
  230. ****************************************************************************
  231. */
  232. #if ! COMPRESS
  233. .section ".prefix.lib", "awx", @progbits
  234. .code16
  235. copy_bytes:
  236. pushl %ecx
  237. rep addr32 movsb
  238. popl %ecx
  239. ret
  240. .size copy_bytes, . - copy_bytes
  241. #endif /* COMPRESS */
  242. /****************************************************************************
  243. * install_block
  244. *
  245. * Install block to specified address
  246. *
  247. * Parameters:
  248. * %esi : source physical address (must be a multiple of 16)
  249. * %edi : destination physical address (must be a multiple of 16)
  250. * %ecx : length of (decompressed) data
  251. * %edx : total length of block (including any uninitialised data portion)
  252. * Returns:
  253. * %esi : next source physical address (will be a multiple of 16)
  254. * %edi : next destination physical address (will be a multiple of 16)
  255. * Corrupts:
  256. * none
  257. ****************************************************************************
  258. */
  259. .section ".prefix.lib", "awx", @progbits
  260. .code16
  261. install_block:
  262. /* Preserve registers */
  263. pushw %ds
  264. pushw %es
  265. pushl %ecx
  266. /* Convert %esi and %edi to %ds:esi and %es:edi */
  267. shrl $4, %esi
  268. movw %si, %ds
  269. xorw %si, %si
  270. shll $4, %esi
  271. shrl $4, %edi
  272. movw %di, %es
  273. xorw %di, %di
  274. shll $4, %edi
  275. #if COMPRESS
  276. /* Decompress source to destination */
  277. call decompress16
  278. #else
  279. /* Copy source to destination */
  280. call copy_bytes
  281. #endif
  282. /* Zero .bss portion */
  283. negl %ecx
  284. addl %edx, %ecx
  285. pushw %ax
  286. xorw %ax, %ax
  287. rep addr32 stosb
  288. popw %ax
  289. /* Round up %esi and %edi to start of next blocks */
  290. addl $0xf, %esi
  291. andl $~0xf, %esi
  292. addl $0xf, %edi
  293. andl $~0xf, %edi
  294. /* Convert %ds:esi and %es:edi back to physical addresses */
  295. xorl %ecx, %ecx
  296. movw %ds, %cx
  297. shll $4, %ecx
  298. addl %ecx, %esi
  299. xorl %ecx, %ecx
  300. movw %es, %cx
  301. shll $4, %ecx
  302. addl %ecx, %edi
  303. /* Restore registers and return */
  304. popl %ecx
  305. popw %es
  306. popw %ds
  307. ret
  308. .size install_block, . - install_block
  309. /****************************************************************************
  310. * alloc_basemem
  311. *
  312. * Allocate space for .text16 and .data16 from top of base memory.
  313. * Memory is allocated using the BIOS free base memory counter at
  314. * 0x40:13.
  315. *
  316. * Parameters:
  317. * none
  318. * Returns:
  319. * %ax : .text16 segment address
  320. * %bx : .data16 segment address
  321. * Corrupts:
  322. * none
  323. ****************************************************************************
  324. */
  325. .section ".prefix.lib", "awx", @progbits
  326. .code16
  327. .globl alloc_basemem
  328. alloc_basemem:
  329. /* Preserve registers */
  330. pushw %fs
  331. /* FBMS => %ax as segment address */
  332. pushw $0x40
  333. popw %fs
  334. movw %fs:0x13, %ax
  335. shlw $6, %ax
  336. /* Calculate .data16 segment address */
  337. subw $_data16_memsz_pgh, %ax
  338. pushw %ax
  339. /* Calculate .text16 segment address */
  340. subw $_text16_memsz_pgh, %ax
  341. pushw %ax
  342. /* Update FBMS */
  343. shrw $6, %ax
  344. movw %ax, %fs:0x13
  345. /* Retrieve .text16 and .data16 segment addresses */
  346. popw %ax
  347. popw %bx
  348. /* Restore registers and return */
  349. popw %fs
  350. ret
  351. .size alloc_basemem, . - alloc_basemem
  352. /****************************************************************************
  353. * free_basemem
  354. *
  355. * Free space allocated with alloc_basemem.
  356. *
  357. * Parameters:
  358. * %ax : .text16 segment address
  359. * %bx : .data16 segment address
  360. * Returns:
  361. * %ax : 0 if successfully freed
  362. * Corrupts:
  363. * none
  364. ****************************************************************************
  365. */
  366. .section ".text16", "ax", @progbits
  367. .code16
  368. .globl free_basemem
  369. free_basemem:
  370. /* Preserve registers */
  371. pushw %fs
  372. /* Check FBMS counter */
  373. pushw %ax
  374. shrw $6, %ax
  375. pushw $0x40
  376. popw %fs
  377. cmpw %ax, %fs:0x13
  378. popw %ax
  379. jne 1f
  380. /* Check hooked interrupt count */
  381. cmpw $0, %cs:hooked_bios_interrupts
  382. jne 1f
  383. /* OK to free memory */
  384. addw $_text16_memsz_pgh, %ax
  385. addw $_data16_memsz_pgh, %ax
  386. shrw $6, %ax
  387. movw %ax, %fs:0x13
  388. xorw %ax, %ax
  389. 1: /* Restore registers and return */
  390. popw %fs
  391. ret
  392. .size free_basemem, . - free_basemem
  393. .section ".text16.data", "aw", @progbits
  394. .globl hooked_bios_interrupts
  395. hooked_bios_interrupts:
  396. .word 0
  397. .size hooked_bios_interrupts, . - hooked_bios_interrupts
  398. /****************************************************************************
  399. * install
  400. *
  401. * Install all text and data segments.
  402. *
  403. * Parameters:
  404. * none
  405. * Returns:
  406. * %ax : .text16 segment address
  407. * %bx : .data16 segment address
  408. * Corrupts:
  409. * none
  410. ****************************************************************************
  411. */
  412. .section ".prefix.lib", "awx", @progbits
  413. .code16
  414. .globl install
  415. install:
  416. /* Preserve registers */
  417. pushl %esi
  418. pushl %edi
  419. /* Allocate space for .text16 and .data16 */
  420. call alloc_basemem
  421. /* Image source = %cs:0000 */
  422. xorl %esi, %esi
  423. /* Image destination = HIGHMEM_LOADPOINT */
  424. movl $HIGHMEM_LOADPOINT, %edi
  425. /* Install text and data segments */
  426. call install_prealloc
  427. /* Restore registers and return */
  428. popl %edi
  429. popl %esi
  430. ret
  431. .size install, . - install
  432. /****************************************************************************
  433. * install_prealloc
  434. *
  435. * Install all text and data segments.
  436. *
  437. * Parameters:
  438. * %ax : .text16 segment address
  439. * %bx : .data16 segment address
  440. * %esi : Image source physical address (or zero for %cs:0000)
  441. * %edi : Decompression temporary area physical address
  442. * Corrupts:
  443. * none
  444. ****************************************************************************
  445. */
  446. .section ".prefix.lib", "awx", @progbits
  447. .code16
  448. .globl install_prealloc
  449. install_prealloc:
  450. /* Save registers */
  451. pushal
  452. pushw %ds
  453. pushw %es
  454. /* Sanity: clear the direction flag asap */
  455. cld
  456. /* Copy decompression temporary area physical address to %ebp */
  457. movl %edi, %ebp
  458. /* Install .text16.early */
  459. pushl %esi
  460. xorl %esi, %esi
  461. movw %cs, %si
  462. shll $4, %esi
  463. addl $_text16_early_lma, %esi
  464. movzwl %ax, %edi
  465. shll $4, %edi
  466. movl $_text16_early_filesz, %ecx
  467. movl $_text16_early_memsz, %edx
  468. call install_block /* .text16.early */
  469. popl %esi
  470. /* Open up access to payload */
  471. #ifndef KEEP_IT_REAL
  472. /* Access high memory */
  473. pushw %cs
  474. pushw $1f
  475. pushw %ax
  476. pushw $access_highmem
  477. lret
  478. 1: /* Die if we could not access high memory */
  479. jnc 3f
  480. movw $a20_death_message, %si
  481. xorw %di, %di
  482. call print_message
  483. 2: jmp 2b
  484. .section ".prefix.data", "aw", @progbits
  485. a20_death_message:
  486. .asciz "Gate A20 stuck - cannot continue\n"
  487. .size a20_death_message, . - a20_death_message
  488. .previous
  489. 3:
  490. #endif
  491. /* Calculate physical address of payload (i.e. first source) */
  492. testl %esi, %esi
  493. jnz 1f
  494. movw %cs, %si
  495. shll $4, %esi
  496. 1: addl %cs:payload_lma, %esi
  497. /* Install .text16.late and .data16 */
  498. movl $_text16_late_filesz, %ecx
  499. movl $_text16_late_memsz, %edx
  500. call install_block /* .text16.late */
  501. movzwl %bx, %edi
  502. shll $4, %edi
  503. movl $_data16_filesz, %ecx
  504. movl $_data16_memsz, %edx
  505. call install_block /* .data16 */
  506. /* Set up %ds for access to .data16 */
  507. movw %bx, %ds
  508. #ifdef KEEP_IT_REAL
  509. /* Initialise libkir */
  510. movw %ax, (init_libkir_vector+2)
  511. lcall *init_libkir_vector
  512. #else
  513. /* Install .text and .data to temporary area in high memory,
  514. * prior to reading the E820 memory map and relocating
  515. * properly.
  516. */
  517. movl %ebp, %edi
  518. movl $_textdata_filesz, %ecx
  519. movl $_textdata_memsz, %edx
  520. call install_block
  521. /* Initialise librm at current location */
  522. movw %ax, (init_librm_vector+2)
  523. movl %ebp, %edi
  524. lcall *init_librm_vector
  525. /* Call relocate() to determine target address for relocation.
  526. * relocate() will return with %esi, %edi and %ecx set up
  527. * ready for the copy to the new location.
  528. */
  529. movw %ax, (prot_call_vector+2)
  530. pushl $relocate
  531. lcall *prot_call_vector
  532. popl %edx /* discard */
  533. /* Copy code to new location */
  534. pushl %edi
  535. xorw %ax, %ax
  536. movw %ax, %es
  537. es rep addr32 movsb
  538. popl %edi
  539. /* Initialise librm at new location */
  540. lcall *init_librm_vector
  541. #endif
  542. /* Restore registers */
  543. popw %es
  544. popw %ds
  545. popal
  546. ret
  547. .size install_prealloc, . - install_prealloc
  548. /* Vectors for far calls to .text16 functions. Must be in
  549. * .data16, since .prefix may not be writable.
  550. */
  551. .section ".data16", "aw", @progbits
  552. #ifdef KEEP_IT_REAL
  553. init_libkir_vector:
  554. .word init_libkir
  555. .word 0
  556. .size init_libkir_vector, . - init_libkir_vector
  557. #else
  558. init_librm_vector:
  559. .word init_librm
  560. .word 0
  561. .size init_librm_vector, . - init_librm_vector
  562. prot_call_vector:
  563. .word prot_call
  564. .word 0
  565. .size prot_call_vector, . - prot_call_vector
  566. #endif
  567. /* Payload address */
  568. .section ".prefix.lib", "awx", @progbits
  569. payload_lma:
  570. .long 0
  571. .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
  572. .ascii "ADHL"
  573. .long payload_lma
  574. .long 1
  575. .long 0
  576. .previous
  577. /****************************************************************************
  578. * uninstall
  579. *
  580. * Uninstall all text and data segments.
  581. *
  582. * Parameters:
  583. * %ax : .text16 segment address
  584. * %bx : .data16 segment address
  585. * Returns:
  586. * none
  587. * Corrupts:
  588. * none
  589. ****************************************************************************
  590. */
  591. .section ".text16", "ax", @progbits
  592. .code16
  593. .globl uninstall
  594. uninstall:
  595. call free_basemem
  596. ret
  597. .size uninstall, . - uninstall
  598. /* File split information for the compressor */
  599. #if COMPRESS
  600. #define PACK_OR_COPY "PACK"
  601. #else
  602. #define PACK_OR_COPY "COPY"
  603. #endif
  604. .section ".zinfo", "a", @progbits
  605. .ascii "COPY"
  606. .long _prefix_lma
  607. .long _prefix_filesz
  608. .long _max_align
  609. .ascii PACK_OR_COPY
  610. .long _text16_early_lma
  611. .long _text16_early_filesz
  612. .long _max_align
  613. .ascii "PAYL"
  614. .long 0
  615. .long 0
  616. .long _max_align
  617. .ascii PACK_OR_COPY
  618. .long _text16_late_lma
  619. .long _text16_late_filesz
  620. .long _max_align
  621. .ascii PACK_OR_COPY
  622. .long _data16_lma
  623. .long _data16_filesz
  624. .long _max_align
  625. .ascii PACK_OR_COPY
  626. .long _textdata_lma
  627. .long _textdata_filesz
  628. .long _max_align