Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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