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 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  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. /* Image compression enabled */
  22. #define COMPRESS 1
  23. /* Protected mode flag */
  24. #define CR0_PE 1
  25. /*****************************************************************************
  26. * Utility function: print character (with LF -> LF,CR translation)
  27. *
  28. * Parameters:
  29. * %al : character to print
  30. * %ds:di : output buffer (or %di=0 to print to console)
  31. * Returns:
  32. * %ds:di : next character in output buffer (if applicable)
  33. *****************************************************************************
  34. */
  35. .section ".prefix.lib", "awx", @progbits
  36. .code16
  37. .globl print_character
  38. print_character:
  39. /* Preserve registers */
  40. pushw %ax
  41. pushw %bx
  42. pushw %bp
  43. /* If %di is non-zero, write character to buffer and exit */
  44. testw %di, %di
  45. jz 1f
  46. movb %al, %ds:(%di)
  47. incw %di
  48. jmp 3f
  49. 1: /* Print character */
  50. movw $0x0007, %bx /* page 0, attribute 7 (normal) */
  51. movb $0x0e, %ah /* write char, tty mode */
  52. cmpb $0x0a, %al /* '\n'? */
  53. jne 2f
  54. int $0x10
  55. movb $0x0d, %al
  56. 2: int $0x10
  57. /* Restore registers and return */
  58. 3: popw %bp
  59. popw %bx
  60. popw %ax
  61. ret
  62. .size print_character, . - print_character
  63. /*****************************************************************************
  64. * Utility function: print a NUL-terminated string
  65. *
  66. * Parameters:
  67. * %ds:si : string to print
  68. * %ds:di : output buffer (or %di=0 to print to console)
  69. * Returns:
  70. * %ds:si : character after terminating NUL
  71. * %ds:di : next character in output buffer (if applicable)
  72. *****************************************************************************
  73. */
  74. .section ".prefix.lib", "awx", @progbits
  75. .code16
  76. .globl print_message
  77. print_message:
  78. /* Preserve registers */
  79. pushw %ax
  80. /* Print string */
  81. 1: lodsb
  82. testb %al, %al
  83. je 2f
  84. call print_character
  85. jmp 1b
  86. 2: /* Restore registers and return */
  87. popw %ax
  88. ret
  89. .size print_message, . - print_message
  90. /*****************************************************************************
  91. * Utility functions: print hex digit/byte/word/dword
  92. *
  93. * Parameters:
  94. * %al (low nibble) : digit to print
  95. * %al : byte to print
  96. * %ax : word to print
  97. * %eax : dword to print
  98. * %ds:di : output buffer (or %di=0 to print to console)
  99. * Returns:
  100. * %ds:di : next character in output buffer (if applicable)
  101. *****************************************************************************
  102. */
  103. .section ".prefix.lib", "awx", @progbits
  104. .code16
  105. .globl print_hex_dword
  106. print_hex_dword:
  107. rorl $16, %eax
  108. call print_hex_word
  109. rorl $16, %eax
  110. /* Fall through */
  111. .size print_hex_dword, . - print_hex_dword
  112. .globl print_hex_word
  113. print_hex_word:
  114. xchgb %al, %ah
  115. call print_hex_byte
  116. xchgb %al, %ah
  117. /* Fall through */
  118. .size print_hex_word, . - print_hex_word
  119. .globl print_hex_byte
  120. print_hex_byte:
  121. rorb $4, %al
  122. call print_hex_nibble
  123. rorb $4, %al
  124. /* Fall through */
  125. .size print_hex_byte, . - print_hex_byte
  126. .globl print_hex_nibble
  127. print_hex_nibble:
  128. /* Preserve registers */
  129. pushw %ax
  130. /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
  131. andb $0x0f, %al
  132. cmpb $10, %al
  133. sbbb $0x69, %al
  134. das
  135. call print_character
  136. /* Restore registers and return */
  137. popw %ax
  138. ret
  139. .size print_hex_nibble, . - print_hex_nibble
  140. /*****************************************************************************
  141. * Utility function: print PCI bus:dev.fn
  142. *
  143. * Parameters:
  144. * %ax : PCI bus:dev.fn to print
  145. * %ds:di : output buffer (or %di=0 to print to console)
  146. * Returns:
  147. * %ds:di : next character in output buffer (if applicable)
  148. *****************************************************************************
  149. */
  150. .section ".prefix.lib", "awx", @progbits
  151. .code16
  152. .globl print_pci_busdevfn
  153. print_pci_busdevfn:
  154. /* Preserve registers */
  155. pushw %ax
  156. /* Print bus */
  157. xchgb %al, %ah
  158. call print_hex_byte
  159. /* Print ":" */
  160. movb $( ':' ), %al
  161. call print_character
  162. /* Print device */
  163. movb %ah, %al
  164. shrb $3, %al
  165. call print_hex_byte
  166. /* Print "." */
  167. movb $( '.' ), %al
  168. call print_character
  169. /* Print function */
  170. movb %ah, %al
  171. andb $0x07, %al
  172. call print_hex_nibble
  173. /* Restore registers and return */
  174. popw %ax
  175. ret
  176. .size print_pci_busdevfn, . - print_pci_busdevfn
  177. /*****************************************************************************
  178. * Utility function: clear current line
  179. *
  180. * Parameters:
  181. * %ds:di : output buffer (or %di=0 to print to console)
  182. * Returns:
  183. * %ds:di : next character in output buffer (if applicable)
  184. *****************************************************************************
  185. */
  186. .section ".prefix.lib", "awx", @progbits
  187. .code16
  188. .globl print_kill_line
  189. print_kill_line:
  190. /* Preserve registers */
  191. pushw %ax
  192. pushw %cx
  193. /* Print CR */
  194. movb $( '\r' ), %al
  195. call print_character
  196. /* Print 79 spaces */
  197. movb $( ' ' ), %al
  198. movw $79, %cx
  199. 1: call print_character
  200. loop 1b
  201. /* Print CR */
  202. movb $( '\r' ), %al
  203. call print_character
  204. /* Restore registers and return */
  205. popw %cx
  206. popw %ax
  207. ret
  208. .size print_kill_line, . - print_kill_line
  209. /****************************************************************************
  210. * copy_bytes
  211. *
  212. * Copy bytes
  213. *
  214. * Parameters:
  215. * %ds:esi : source address
  216. * %es:edi : destination address
  217. * %ecx : length
  218. * Returns:
  219. * %ds:esi : next source address
  220. * %es:edi : next destination address
  221. * Corrupts:
  222. * None
  223. ****************************************************************************
  224. */
  225. .section ".prefix.lib", "awx", @progbits
  226. .code16
  227. copy_bytes:
  228. pushl %ecx
  229. rep addr32 movsb
  230. popl %ecx
  231. ret
  232. .size copy_bytes, . - copy_bytes
  233. /****************************************************************************
  234. * zero_bytes
  235. *
  236. * Zero bytes
  237. *
  238. * Parameters:
  239. * %ds:esi : source address
  240. * %es:edi : destination address
  241. * %ecx : length
  242. * Returns:
  243. * %ds:esi : next source address
  244. * %es:edi : next destination address
  245. * Corrupts:
  246. * None
  247. ****************************************************************************
  248. */
  249. .section ".prefix.lib", "awx", @progbits
  250. .code16
  251. zero_bytes:
  252. pushl %ecx
  253. pushw %ax
  254. xorw %ax, %ax
  255. rep addr32 stosb
  256. popw %ax
  257. popl %ecx
  258. ret
  259. .size zero_bytes, . - zero_bytes
  260. /****************************************************************************
  261. * process_bytes
  262. *
  263. * Call memcpy()-like function
  264. *
  265. * Parameters:
  266. * %esi : source physical address
  267. * %edi : destination physical address
  268. * %ecx : length
  269. * %bx : memcpy()-like function to call, passing parameters:
  270. * %ds:esi : source address
  271. * %es:edi : destination address
  272. * %ecx : length
  273. * and returning:
  274. * %ds:esi : next source address
  275. * %es:edi : next destination address
  276. * Returns:
  277. * %esi : next source physical address
  278. * %edi : next destination physical address
  279. * Corrupts:
  280. * None
  281. ****************************************************************************
  282. */
  283. .section ".prefix.lib", "awx", @progbits
  284. .code16
  285. process_bytes:
  286. #ifndef KEEP_IT_REAL
  287. /* Preserve registers */
  288. pushfw
  289. pushl %eax
  290. pushl %ebp
  291. /* Construct GDT on stack (since .prefix may not be writable) */
  292. .equ PM_DS, 0x18 /* Flat data segment */
  293. pushl $0x008f9300
  294. pushl $0x0000ffff
  295. .equ PM_SS, 0x10 /* Stack segment based at %ss:0000 */
  296. pushl $0x008f0930
  297. pushw %ss
  298. pushw $0xffff
  299. .equ PM_CS, 0x08 /* Code segment based at %cs:0000 */
  300. pushl $0x008f09b0
  301. pushw %cs
  302. pushw $0xffff
  303. pushl $0 /* Base and length */
  304. pushw %ss
  305. pushw $0x1f
  306. movzwl %sp, %ebp
  307. shll $4, 0x02(%bp)
  308. addl %ebp, 0x02(%bp)
  309. shll $4, 0x0a(%bp)
  310. shll $4, 0x12(%bp)
  311. subw $8, %sp
  312. sgdt -8(%bp)
  313. /* Switch to protected mode */
  314. pushw %gs
  315. pushw %fs
  316. pushw %es
  317. pushw %ds
  318. pushw %ss
  319. pushw %cs
  320. pushw $2f
  321. cli
  322. data32 lgdt (%bp)
  323. movl %cr0, %eax
  324. orb $CR0_PE, %al
  325. movl %eax, %cr0
  326. ljmp $PM_CS, $1f
  327. 1: movw $PM_SS, %ax
  328. movw %ax, %ss
  329. movw $PM_DS, %ax
  330. movw %ax, %ds
  331. movw %ax, %es
  332. movw %ax, %fs
  333. movw %ax, %gs
  334. /* Call memcpy()-like function */
  335. call *%bx
  336. /* Return to (flat) real mode */
  337. movl %cr0, %eax
  338. andb $0!CR0_PE, %al
  339. movl %eax, %cr0
  340. lret
  341. 2: /* lret will ljmp to here */
  342. popw %ss
  343. popw %ds
  344. popw %es
  345. popw %fs
  346. popw %gs
  347. /* Restore GDT */
  348. data32 lgdt -8(%bp)
  349. addw $( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
  350. /* Restore registers and return */
  351. popl %ebp
  352. popl %eax
  353. popfw
  354. ret
  355. #else /* KEEP_IT_REAL */
  356. /* Preserve registers */
  357. pushl %eax
  358. pushw %ds
  359. pushw %es
  360. /* Convert %esi and %edi to %ds:esi and %es:edi */
  361. shrl $4, %esi
  362. movw %si, %ds
  363. xorw %si, %si
  364. shll $4, %esi
  365. shrl $4, %edi
  366. movw %di, %es
  367. xorw %di, %di
  368. shll $4, %edi
  369. /* Call memcpy()-like function */
  370. call *%bx
  371. /* Convert %ds:esi and %es:edi back to physical addresses */
  372. xorl %eax, %eax
  373. movw %ds, %cx
  374. shll $4, %eax
  375. addl %eax, %esi
  376. xorl %eax, %eax
  377. movw %es, %cx
  378. shll $4, %eax
  379. addl %eax, %edi
  380. /* Restore registers and return */
  381. popw %es
  382. popw %ds
  383. popl %eax
  384. ret
  385. #endif /* KEEP_IT_REAL */
  386. .size process_bytes, . - process_bytes
  387. /****************************************************************************
  388. * install_block
  389. *
  390. * Install block to specified address
  391. *
  392. * Parameters:
  393. * %esi : source physical address (must be a multiple of 16)
  394. * %edi : destination physical address (must be a multiple of 16)
  395. * %ecx : length of (decompressed) data
  396. * %edx : total length of block (including any uninitialised data portion)
  397. * Returns:
  398. * %esi : next source physical address (will be a multiple of 16)
  399. * %edi : next destination physical address (will be a multiple of 16)
  400. * Corrupts:
  401. * none
  402. ****************************************************************************
  403. */
  404. .section ".prefix.lib", "awx", @progbits
  405. .code16
  406. install_block:
  407. /* Preserve registers */
  408. pushl %ecx
  409. pushw %bx
  410. /* Decompress (or copy) source to destination */
  411. #if COMPRESS
  412. movw $decompress16, %bx
  413. #else
  414. movw $copy_bytes, %bx
  415. #endif
  416. call process_bytes
  417. /* Zero .bss portion */
  418. negl %ecx
  419. addl %edx, %ecx
  420. movw $zero_bytes, %bx
  421. call process_bytes
  422. /* Round up %esi and %edi to start of next blocks */
  423. addl $0xf, %esi
  424. andl $~0xf, %esi
  425. addl $0xf, %edi
  426. andl $~0xf, %edi
  427. /* Restore registers and return */
  428. popw %bx
  429. popl %ecx
  430. ret
  431. .size install_block, . - install_block
  432. /****************************************************************************
  433. * alloc_basemem
  434. *
  435. * Allocate space for .text16 and .data16 from top of base memory.
  436. * Memory is allocated using the BIOS free base memory counter at
  437. * 0x40:13.
  438. *
  439. * Parameters:
  440. * none
  441. * Returns:
  442. * %ax : .text16 segment address
  443. * %bx : .data16 segment address
  444. * Corrupts:
  445. * none
  446. ****************************************************************************
  447. */
  448. .section ".prefix.lib", "awx", @progbits
  449. .code16
  450. .globl alloc_basemem
  451. alloc_basemem:
  452. /* Preserve registers */
  453. pushw %fs
  454. /* FBMS => %ax as segment address */
  455. pushw $0x40
  456. popw %fs
  457. movw %fs:0x13, %ax
  458. shlw $6, %ax
  459. /* Calculate .data16 segment address */
  460. subw $_data16_memsz_pgh, %ax
  461. pushw %ax
  462. /* Calculate .text16 segment address */
  463. subw $_text16_memsz_pgh, %ax
  464. pushw %ax
  465. /* Update FBMS */
  466. shrw $6, %ax
  467. movw %ax, %fs:0x13
  468. /* Retrieve .text16 and .data16 segment addresses */
  469. popw %ax
  470. popw %bx
  471. /* Restore registers and return */
  472. popw %fs
  473. ret
  474. .size alloc_basemem, . - alloc_basemem
  475. /****************************************************************************
  476. * free_basemem
  477. *
  478. * Free space allocated with alloc_basemem.
  479. *
  480. * Parameters:
  481. * %ax : .text16 segment address
  482. * %bx : .data16 segment address
  483. * Returns:
  484. * %ax : 0 if successfully freed
  485. * Corrupts:
  486. * none
  487. ****************************************************************************
  488. */
  489. .section ".text16", "ax", @progbits
  490. .code16
  491. .globl free_basemem
  492. free_basemem:
  493. /* Preserve registers */
  494. pushw %fs
  495. /* Check FBMS counter */
  496. pushw %ax
  497. shrw $6, %ax
  498. pushw $0x40
  499. popw %fs
  500. cmpw %ax, %fs:0x13
  501. popw %ax
  502. jne 1f
  503. /* Check hooked interrupt count */
  504. cmpw $0, %cs:hooked_bios_interrupts
  505. jne 1f
  506. /* OK to free memory */
  507. addw $_text16_memsz_pgh, %ax
  508. addw $_data16_memsz_pgh, %ax
  509. shrw $6, %ax
  510. movw %ax, %fs:0x13
  511. xorw %ax, %ax
  512. 1: /* Restore registers and return */
  513. popw %fs
  514. ret
  515. .size free_basemem, . - free_basemem
  516. .section ".text16.data", "aw", @progbits
  517. .globl hooked_bios_interrupts
  518. hooked_bios_interrupts:
  519. .word 0
  520. .size hooked_bios_interrupts, . - hooked_bios_interrupts
  521. /****************************************************************************
  522. * install
  523. *
  524. * Install all text and data segments.
  525. *
  526. * Parameters:
  527. * none
  528. * Returns:
  529. * %ax : .text16 segment address
  530. * %bx : .data16 segment address
  531. * Corrupts:
  532. * none
  533. ****************************************************************************
  534. */
  535. .section ".prefix.lib", "awx", @progbits
  536. .code16
  537. .globl install
  538. install:
  539. /* Preserve registers */
  540. pushl %esi
  541. pushl %edi
  542. /* Allocate space for .text16 and .data16 */
  543. call alloc_basemem
  544. /* Image source = %cs:0000 */
  545. xorl %esi, %esi
  546. /* Image destination = default */
  547. xorl %edi, %edi
  548. /* Allow relocation */
  549. clc
  550. /* Install text and data segments */
  551. call install_prealloc
  552. /* Restore registers and return */
  553. popl %edi
  554. popl %esi
  555. ret
  556. .size install, . - install
  557. /****************************************************************************
  558. * install_prealloc
  559. *
  560. * Install all text and data segments.
  561. *
  562. * Parameters:
  563. * %ax : .text16 segment address
  564. * %bx : .data16 segment address
  565. * %esi : Image source physical address (or zero for %cs:0000)
  566. * %edi : Decompression temporary area physical address (or zero for default)
  567. * CF set : Avoid relocating to top of memory
  568. * Corrupts:
  569. * none
  570. ****************************************************************************
  571. */
  572. .section ".prefix.lib", "awx", @progbits
  573. .code16
  574. .globl install_prealloc
  575. install_prealloc:
  576. /* Save registers */
  577. pushal
  578. pushw %ds
  579. pushw %es
  580. cld /* Sanity: clear the direction flag asap */
  581. pushfw
  582. /* Set up %ds for (read-only) access to .prefix */
  583. pushw %cs
  584. popw %ds
  585. /* Copy decompression temporary area physical address to %ebp */
  586. movl %edi, %ebp
  587. /* Install .text16.early */
  588. pushl %esi
  589. xorl %esi, %esi
  590. movw %cs, %si
  591. shll $4, %esi
  592. addl $_text16_early_lma, %esi
  593. movzwl %ax, %edi
  594. shll $4, %edi
  595. movl $_text16_early_filesz, %ecx
  596. movl $_text16_early_memsz, %edx
  597. call install_block /* .text16.early */
  598. popl %esi
  599. #ifndef KEEP_IT_REAL
  600. /* Access high memory by enabling the A20 gate. (We will
  601. * already have 4GB segment limits as a result of calling
  602. * install_block.)
  603. */
  604. pushw %cs
  605. pushw $1f
  606. pushw %ax
  607. pushw $access_highmem
  608. lret
  609. 1: /* Die if we could not access high memory */
  610. jnc 3f
  611. movw $a20_death_message, %si
  612. xorw %di, %di
  613. call print_message
  614. 2: jmp 2b
  615. .section ".prefix.data", "aw", @progbits
  616. a20_death_message:
  617. .asciz "\nHigh memory inaccessible - cannot continue\n"
  618. .size a20_death_message, . - a20_death_message
  619. .previous
  620. 3:
  621. #endif
  622. /* Open payload (which may not yet be in memory) */
  623. pushw %cs
  624. pushw $1f
  625. pushw %ax
  626. pushw $open_payload
  627. lret
  628. 1: /* Die if we could not access the payload */
  629. jnc 3f
  630. xorw %di, %di
  631. movl %esi, %eax
  632. call print_hex_dword
  633. movw $payload_death_message, %si
  634. call print_message
  635. 2: jmp 2b
  636. .section ".prefix.data", "aw", @progbits
  637. payload_death_message:
  638. .asciz "\nPayload inaccessible - cannot continue\n"
  639. .size payload_death_message, . - payload_death_message
  640. .previous
  641. 3:
  642. /* Calculate physical address of payload (i.e. first source) */
  643. testl %esi, %esi
  644. jnz 1f
  645. movw %cs, %si
  646. shll $4, %esi
  647. 1: addl payload_lma, %esi
  648. /* Install .text16.late and .data16 */
  649. movl $_text16_late_filesz, %ecx
  650. movl $_text16_late_memsz, %edx
  651. call install_block /* .text16.late */
  652. movzwl %bx, %edi
  653. shll $4, %edi
  654. movl $_data16_filesz, %ecx
  655. movl $_data16_memsz, %edx
  656. call install_block /* .data16 */
  657. /* Set up %ds for access to .data16 */
  658. movw %bx, %ds
  659. #ifdef KEEP_IT_REAL
  660. /* Initialise libkir */
  661. movw %ax, (init_libkir_vector+2)
  662. lcall *init_libkir_vector
  663. #else
  664. /* Find a suitable decompression temporary area, if none specified */
  665. testl %ebp, %ebp
  666. jnz 1f
  667. /* Use INT 15,88 to find the highest available address via INT
  668. * 15,88. This limits us to around 64MB, which should avoid
  669. * all of the POST-time memory map failure modes.
  670. */
  671. pushl %eax
  672. movb $0x88, %ah
  673. int $0x15
  674. movw %ax, %bp
  675. addl $0x400, %ebp
  676. subl $_textdata_memsz_kb, %ebp
  677. shll $10, %ebp
  678. popl %eax
  679. 1:
  680. /* Install .text and .data to temporary area in high memory,
  681. * prior to reading the E820 memory map and relocating
  682. * properly.
  683. */
  684. movl %ebp, %edi
  685. movl $_textdata_filesz, %ecx
  686. movl $_textdata_memsz, %edx
  687. call install_block
  688. /* Initialise librm at current location */
  689. movw %ax, (init_librm_vector+2)
  690. movl %ebp, %edi
  691. lcall *init_librm_vector
  692. /* Skip relocation if CF was set on entry */
  693. popfw
  694. pushfw
  695. jc skip_relocate
  696. /* Call relocate() to determine target address for relocation.
  697. * relocate() will return with %esi, %edi and %ecx set up
  698. * ready for the copy to the new location.
  699. */
  700. movw %ax, (prot_call_vector+2)
  701. pushl $relocate
  702. lcall *prot_call_vector
  703. popl %edx /* discard */
  704. /* Copy code to new location */
  705. pushl %edi
  706. pushw %bx
  707. movw $copy_bytes, %bx
  708. call process_bytes
  709. popw %bx
  710. popl %edi
  711. /* Initialise librm at new location */
  712. lcall *init_librm_vector
  713. skip_relocate:
  714. #endif
  715. /* Close access to payload */
  716. movw %ax, (close_payload_vector+2)
  717. lcall *close_payload_vector
  718. /* Restore registers */
  719. popfw
  720. popw %es
  721. popw %ds
  722. popal
  723. ret
  724. .size install_prealloc, . - install_prealloc
  725. /* Vectors for far calls to .text16 functions. Must be in
  726. * .data16, since .prefix may not be writable.
  727. */
  728. .section ".data16", "aw", @progbits
  729. #ifdef KEEP_IT_REAL
  730. init_libkir_vector:
  731. .word init_libkir
  732. .word 0
  733. .size init_libkir_vector, . - init_libkir_vector
  734. #else
  735. init_librm_vector:
  736. .word init_librm
  737. .word 0
  738. .size init_librm_vector, . - init_librm_vector
  739. prot_call_vector:
  740. .word prot_call
  741. .word 0
  742. .size prot_call_vector, . - prot_call_vector
  743. #endif
  744. close_payload_vector:
  745. .word close_payload
  746. .word 0
  747. .size close_payload_vector, . - close_payload_vector
  748. /* Payload address */
  749. .section ".prefix.lib", "awx", @progbits
  750. payload_lma:
  751. .long 0
  752. .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
  753. .ascii "ADHL"
  754. .long payload_lma
  755. .long 1
  756. .long 0
  757. .previous
  758. /* Dummy routines to open and close payload */
  759. .section ".text16.early.data", "aw", @progbits
  760. .weak open_payload
  761. .weak close_payload
  762. open_payload:
  763. close_payload:
  764. clc
  765. lret
  766. .size open_payload, . - open_payload
  767. .size close_payload, . - close_payload
  768. /****************************************************************************
  769. * uninstall
  770. *
  771. * Uninstall all text and data segments.
  772. *
  773. * Parameters:
  774. * %ax : .text16 segment address
  775. * %bx : .data16 segment address
  776. * Returns:
  777. * none
  778. * Corrupts:
  779. * none
  780. ****************************************************************************
  781. */
  782. .section ".text16", "ax", @progbits
  783. .code16
  784. .globl uninstall
  785. uninstall:
  786. call free_basemem
  787. ret
  788. .size uninstall, . - uninstall
  789. /* File split information for the compressor */
  790. #if COMPRESS
  791. #define PACK_OR_COPY "PACK"
  792. #else
  793. #define PACK_OR_COPY "COPY"
  794. #endif
  795. .section ".zinfo", "a", @progbits
  796. .ascii "COPY"
  797. .long _prefix_lma
  798. .long _prefix_filesz
  799. .long _max_align
  800. .ascii PACK_OR_COPY
  801. .long _text16_early_lma
  802. .long _text16_early_filesz
  803. .long _max_align
  804. .ascii "PAYL"
  805. .long 0
  806. .long 0
  807. .long _max_align
  808. .ascii PACK_OR_COPY
  809. .long _text16_late_lma
  810. .long _text16_late_filesz
  811. .long _max_align
  812. .ascii PACK_OR_COPY
  813. .long _data16_lma
  814. .long _data16_filesz
  815. .long _max_align
  816. .ascii PACK_OR_COPY
  817. .long _textdata_lma
  818. .long _textdata_filesz
  819. .long _max_align