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

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