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

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