Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

libprefix.S 22KB

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