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

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