選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

libprefix.S 24KB

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