You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  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. #ifdef NDEBUG
  379. /* Call memcpy()-like function */
  380. call *%bx
  381. #endif
  382. /* Return to (flat) real mode */
  383. movl %cr0, %eax
  384. andb $0!CR0_PE, %al
  385. movl %eax, %cr0
  386. lret
  387. 2: /* lret will ljmp to here */
  388. popw %ss
  389. popw %ds
  390. popw %es
  391. popw %fs
  392. popw %gs
  393. #ifndef NDEBUG
  394. /* Call memcpy()-like function in flat real mode (to allow for
  395. * debug output via INT 10).
  396. */
  397. pushw %ds
  398. pushw %es
  399. xorw %ax, %ax
  400. movw %ax, %ds
  401. movw %ax, %es
  402. call *%bx
  403. popw %es
  404. popw %ds
  405. #endif
  406. /* Restore GDT */
  407. data32 lgdt -8(%bp)
  408. addw $( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
  409. /* Restore registers and return */
  410. popl %ebp
  411. popl %eax
  412. ret
  413. #else /* KEEP_IT_REAL */
  414. /* Preserve registers */
  415. pushl %eax
  416. pushw %ds
  417. pushw %es
  418. /* Convert %esi and %edi to %ds:esi and %es:edi */
  419. shrl $4, %esi
  420. movw %si, %ds
  421. xorw %si, %si
  422. shll $4, %esi
  423. shrl $4, %edi
  424. movw %di, %es
  425. xorw %di, %di
  426. shll $4, %edi
  427. /* Call memcpy()-like function */
  428. call *%bx
  429. /* Convert %ds:esi and %es:edi back to physical addresses */
  430. xorl %eax, %eax
  431. movw %ds, %cx
  432. shll $4, %eax
  433. addl %eax, %esi
  434. xorl %eax, %eax
  435. movw %es, %cx
  436. shll $4, %eax
  437. addl %eax, %edi
  438. /* Restore registers and return */
  439. popw %es
  440. popw %ds
  441. popl %eax
  442. ret
  443. #endif /* KEEP_IT_REAL */
  444. .size process_bytes, . - process_bytes
  445. /****************************************************************************
  446. * install_block
  447. *
  448. * Install block to specified address
  449. *
  450. * Parameters:
  451. * %esi : source physical address (must be a multiple of 16)
  452. * %edi : destination physical address (must be a multiple of 16)
  453. * %ecx : length of (decompressed) data
  454. * %edx : total length of block (including any uninitialised data portion)
  455. * Returns:
  456. * %esi : next source physical address (will be a multiple of 16)
  457. * %edi : next destination physical address (will be a multiple of 16)
  458. * Corrupts:
  459. * none
  460. ****************************************************************************
  461. */
  462. .section ".prefix.lib", "awx", @progbits
  463. .code16
  464. install_block:
  465. /* Preserve registers */
  466. pushl %ecx
  467. pushw %bx
  468. /* Decompress (or copy) source to destination */
  469. #if COMPRESS
  470. movw $decompress16, %bx
  471. #else
  472. movw $copy_bytes, %bx
  473. #endif
  474. call process_bytes
  475. /* Zero .bss portion */
  476. negl %ecx
  477. addl %edx, %ecx
  478. movw $zero_bytes, %bx
  479. call process_bytes
  480. /* Round up %esi and %edi to start of next blocks */
  481. addl $0xf, %esi
  482. andl $~0xf, %esi
  483. addl $0xf, %edi
  484. andl $~0xf, %edi
  485. /* Restore registers and return */
  486. popw %bx
  487. popl %ecx
  488. ret
  489. .size install_block, . - install_block
  490. /****************************************************************************
  491. * alloc_basemem
  492. *
  493. * Allocate space for .text16 and .data16 from top of base memory.
  494. * Memory is allocated using the BIOS free base memory counter at
  495. * 0x40:13.
  496. *
  497. * Parameters:
  498. * none
  499. * Returns:
  500. * %ax : .text16 segment address
  501. * %bx : .data16 segment address
  502. * Corrupts:
  503. * none
  504. ****************************************************************************
  505. */
  506. .section ".prefix.lib", "awx", @progbits
  507. .code16
  508. .globl alloc_basemem
  509. alloc_basemem:
  510. /* Preserve registers */
  511. pushw %fs
  512. /* FBMS => %ax as segment address */
  513. pushw $0x40
  514. popw %fs
  515. movw %fs:0x13, %ax
  516. shlw $6, %ax
  517. /* Calculate .data16 segment address */
  518. subw $_data16_memsz_pgh, %ax
  519. pushw %ax
  520. /* Calculate .text16 segment address. Round down to ensure
  521. * low bits are zero, to speed up mode transitions under KVM.
  522. */
  523. subw $_text16_memsz_pgh, %ax
  524. andb $~0x03, %al
  525. pushw %ax
  526. /* Update FBMS */
  527. shrw $6, %ax
  528. movw %ax, %fs:0x13
  529. /* Retrieve .text16 and .data16 segment addresses */
  530. popw %ax
  531. popw %bx
  532. /* Restore registers and return */
  533. popw %fs
  534. ret
  535. .size alloc_basemem, . - alloc_basemem
  536. /****************************************************************************
  537. * free_basemem
  538. *
  539. * Free space allocated with alloc_basemem.
  540. *
  541. * Parameters:
  542. * none (.text16 segment address is implicit in %cs)
  543. * Returns:
  544. * %ax : 0 if successfully freed
  545. * Corrupts:
  546. * none
  547. ****************************************************************************
  548. */
  549. .section ".text16", "ax", @progbits
  550. .code16
  551. .globl free_basemem
  552. free_basemem:
  553. /* Preserve registers */
  554. pushw %fs
  555. pushw %ax
  556. /* Check FBMS counter */
  557. movw %cs, %ax
  558. shrw $6, %ax
  559. pushw $0x40
  560. popw %fs
  561. cmpw %ax, %fs:0x13
  562. jne 1f
  563. /* Check hooked interrupt count */
  564. cmpw $0, %cs:hooked_bios_interrupts
  565. jne 1f
  566. /* OK to free memory */
  567. movw %cs, %ax
  568. addw $_text16_memsz_pgh, %ax
  569. addw $_data16_memsz_pgh, %ax
  570. shrw $6, %ax
  571. movw %ax, %fs:0x13
  572. xorw %ax, %ax
  573. 1: /* Restore registers and return */
  574. popw %ax
  575. popw %fs
  576. ret
  577. .size free_basemem, . - free_basemem
  578. .section ".text16.data", "aw", @progbits
  579. .globl hooked_bios_interrupts
  580. hooked_bios_interrupts:
  581. .word 0
  582. .size hooked_bios_interrupts, . - hooked_bios_interrupts
  583. /****************************************************************************
  584. * install
  585. *
  586. * Install all text and data segments.
  587. *
  588. * Parameters:
  589. * none
  590. * Returns:
  591. * %ax : .text16 segment address
  592. * %bx : .data16 segment address
  593. * Corrupts:
  594. * none
  595. ****************************************************************************
  596. */
  597. .section ".prefix.lib", "awx", @progbits
  598. .code16
  599. .globl install
  600. install:
  601. progress "install:\n"
  602. /* Preserve registers */
  603. pushl %esi
  604. pushl %edi
  605. pushl %ebp
  606. /* Allocate space for .text16 and .data16 */
  607. call alloc_basemem
  608. /* Image source = %cs:0000 */
  609. xorl %esi, %esi
  610. /* Image destination = default */
  611. xorl %edi, %edi
  612. /* Allow arbitrary relocation */
  613. orl $0xffffffff, %ebp
  614. /* Install text and data segments */
  615. call install_prealloc
  616. /* Restore registers and return */
  617. popl %ebp
  618. popl %edi
  619. popl %esi
  620. ret
  621. .size install, . - install
  622. /****************************************************************************
  623. * install_prealloc
  624. *
  625. * Install all text and data segments.
  626. *
  627. * Parameters:
  628. * %ax : .text16 segment address
  629. * %bx : .data16 segment address
  630. * %esi : Image source physical address (or zero for %cs:0000)
  631. * %edi : Decompression temporary area physical address (or zero for default)
  632. * %ebp : Maximum end address for relocation
  633. * - 0xffffffff for no maximum
  634. * - 0x00000000 to inhibit use of INT 15,e820 and INT 15,e801
  635. * Corrupts:
  636. * none
  637. ****************************************************************************
  638. */
  639. .section ".prefix.lib", "awx", @progbits
  640. .code16
  641. .globl install_prealloc
  642. install_prealloc:
  643. progress "install_prealloc:\n"
  644. /* Save registers on external stack */
  645. pushal
  646. pushw %ds
  647. pushw %es
  648. cld /* Sanity: clear the direction flag asap */
  649. /* Switch to temporary stack in .bss16 */
  650. pushw %ss
  651. popw %ds
  652. movl %esp, %ecx
  653. movw %bx, %ss
  654. movl $_data16_memsz, %esp
  655. pushw %ds
  656. pushl %ecx
  657. /* Set up %ds for (read-only) access to .prefix */
  658. pushw %cs
  659. popw %ds
  660. /* Save decompression temporary area physical address */
  661. pushl %edi
  662. /* Install .text16.early and calculate %ecx as offset to next block */
  663. progress " .text16.early\n"
  664. pushl %esi
  665. xorl %esi, %esi
  666. movw %cs, %si
  667. shll $4, %esi
  668. pushl %esi /* Save original %cs:0000 */
  669. addl $_text16_early_lma, %esi
  670. movzwl %ax, %edi
  671. shll $4, %edi
  672. movl $_text16_early_filesz, %ecx
  673. movl $_text16_early_memsz, %edx
  674. call install_block /* .text16.early */
  675. popl %ecx /* Calculate offset to next block */
  676. subl %esi, %ecx
  677. negl %ecx
  678. popl %esi
  679. #ifndef KEEP_IT_REAL
  680. /* Access high memory by enabling the A20 gate. (We will
  681. * already have 4GB segment limits as a result of calling
  682. * install_block.)
  683. */
  684. progress " access_highmem\n"
  685. pushw %cs
  686. pushw $1f
  687. pushw %ax
  688. pushw $access_highmem
  689. lret
  690. 1: /* Die if we could not access high memory */
  691. jnc 3f
  692. movw $a20_death_message, %si
  693. xorw %di, %di
  694. call print_message
  695. 2: jmp 2b
  696. .section ".prefix.data", "aw", @progbits
  697. a20_death_message:
  698. .asciz "\nHigh memory inaccessible - cannot continue\n"
  699. .size a20_death_message, . - a20_death_message
  700. .previous
  701. 3:
  702. #endif
  703. /* Open payload (which may not yet be in memory) */
  704. progress " open_payload\n"
  705. pushw %cs
  706. pushw $1f
  707. pushw %ax
  708. pushw $open_payload
  709. lret
  710. 1: /* Die if we could not access the payload */
  711. jnc 3f
  712. xorw %di, %di
  713. movl %esi, %eax
  714. call print_hex_dword
  715. call print_space
  716. movl %ecx, %eax
  717. call print_hex_dword
  718. movw $payload_death_message, %si
  719. call print_message
  720. 2: /* Halt system */
  721. cli
  722. hlt
  723. jmp 2b
  724. .section ".prefix.data", "aw", @progbits
  725. payload_death_message:
  726. .asciz "\nPayload inaccessible - cannot continue\n"
  727. .size payload_death_message, . - payload_death_message
  728. .previous
  729. 3:
  730. /* Calculate physical address of payload (i.e. first source) */
  731. testl %esi, %esi
  732. jnz 1f
  733. movw %cs, %si
  734. shll $4, %esi
  735. 1: addl %ecx, %esi
  736. /* Install .text16.late and .data16 */
  737. progress " .text16.late\n"
  738. movl $_text16_late_filesz, %ecx
  739. movl $_text16_late_memsz, %edx
  740. call install_block /* .text16.late */
  741. progress " .data16\n"
  742. movzwl %bx, %edi
  743. shll $4, %edi
  744. movl $_data16_filesz, %ecx
  745. movl $_data16_filesz, %edx /* do not zero our temporary stack */
  746. call install_block /* .data16 */
  747. /* Set up %ds for access to .data16 */
  748. movw %bx, %ds
  749. /* Restore decompression temporary area physical address */
  750. popl %edi
  751. #ifndef KEEP_IT_REAL
  752. /* Find a suitable decompression temporary area, if none specified */
  753. pushl %eax
  754. testl %edi, %edi
  755. jnz 1f
  756. /* Use INT 15,88 to find the highest available address via INT
  757. * 15,88. This limits us to around 64MB, which should avoid
  758. * all of the POST-time memory map failure modes.
  759. */
  760. movb $0x88, %ah
  761. int $0x15
  762. movw %ax, %di
  763. addl $0x400, %edi
  764. subl $_textdata_memsz_kb, %edi
  765. shll $10, %edi
  766. /* Sanity check: if we have ended up below 1MB, use 1MB */
  767. cmpl $0x100000, %edi
  768. jae 1f
  769. movl $0x100000, %edi
  770. 1: popl %eax
  771. /* Install .text and .data to temporary area in high memory,
  772. * prior to reading the E820 memory map and relocating
  773. * properly.
  774. */
  775. progress " .textdata\n"
  776. pushl %edi
  777. movl $_textdata_filesz, %ecx
  778. movl $_textdata_memsz, %edx
  779. call install_block
  780. popl %edi
  781. #endif /* KEEP_IT_REAL */
  782. /* Switch back to original stack and zero .bss16 */
  783. lss %ss:(%esp), %esp
  784. pushl %edi
  785. pushw %es
  786. movw %bx, %es
  787. movl $_data16_filesz, %edi
  788. movl $_data16_memsz, %ecx
  789. subl %edi, %ecx
  790. call zero_bytes
  791. popw %es
  792. popl %edi
  793. #ifndef KEEP_IT_REAL
  794. /* Initialise librm at current location */
  795. progress " init_librm\n"
  796. movw %ax, (init_librm_vector+2)
  797. lcall *init_librm_vector
  798. /* Inhibit INT 15,e820 and INT 15,e801 if applicable */
  799. testl %ebp, %ebp
  800. jnz 1f
  801. incb memmap_post
  802. decl %ebp
  803. 1:
  804. /* Call relocate() to determine target address for relocation.
  805. * relocate() will return with %esi, %edi and %ecx set up
  806. * ready for the copy to the new location.
  807. */
  808. progress " relocate\n"
  809. movw %ax, (prot_call_vector+2)
  810. pushl $relocate
  811. lcall *prot_call_vector
  812. popl %edx /* discard */
  813. /* Copy code to new location */
  814. progress " copy\n"
  815. pushl %edi
  816. pushw %bx
  817. movw $copy_bytes, %bx
  818. call process_bytes
  819. popw %bx
  820. popl %edi
  821. /* Initialise librm at new location */
  822. progress " init_librm\n"
  823. lcall *init_librm_vector
  824. #else /* KEEP_IT_REAL */
  825. /* Initialise libkir */
  826. movw %ax, (init_libkir_vector+2)
  827. lcall *init_libkir_vector
  828. #endif /* KEEP_IT_REAL */
  829. /* Close access to payload */
  830. progress " close_payload\n"
  831. movw %ax, (close_payload_vector+2)
  832. lcall *close_payload_vector
  833. /* Restore registers */
  834. popw %es
  835. popw %ds
  836. popal
  837. ret
  838. .size install_prealloc, . - install_prealloc
  839. /* Vectors for far calls to .text16 functions. Must be in
  840. * .data16, since .prefix may not be writable.
  841. */
  842. .section ".data16", "aw", @progbits
  843. #ifdef KEEP_IT_REAL
  844. init_libkir_vector:
  845. .word init_libkir
  846. .word 0
  847. .size init_libkir_vector, . - init_libkir_vector
  848. #else
  849. init_librm_vector:
  850. .word init_librm
  851. .word 0
  852. .size init_librm_vector, . - init_librm_vector
  853. prot_call_vector:
  854. .word prot_call
  855. .word 0
  856. .size prot_call_vector, . - prot_call_vector
  857. #endif
  858. close_payload_vector:
  859. .word close_payload
  860. .word 0
  861. .size close_payload_vector, . - close_payload_vector
  862. /* Dummy routines to open and close payload */
  863. .section ".text16.early.data", "aw", @progbits
  864. .weak open_payload
  865. .weak close_payload
  866. open_payload:
  867. close_payload:
  868. clc
  869. lret
  870. .size open_payload, . - open_payload
  871. .size close_payload, . - close_payload
  872. /****************************************************************************
  873. * uninstall
  874. *
  875. * Uninstall all text and data segments.
  876. *
  877. * Parameters:
  878. * none (.text16 segment address is implicit in %cs)
  879. * Returns:
  880. * none
  881. * Corrupts:
  882. * none
  883. ****************************************************************************
  884. */
  885. .section ".text16", "ax", @progbits
  886. .code16
  887. .globl uninstall
  888. uninstall:
  889. call free_basemem
  890. ret
  891. .size uninstall, . - uninstall
  892. /* File split information for the compressor */
  893. #if COMPRESS
  894. #define PACK_OR_COPY "PACK"
  895. #else
  896. #define PACK_OR_COPY "COPY"
  897. #endif
  898. .section ".zinfo", "a", @progbits
  899. .ascii "COPY"
  900. .long _prefix_lma
  901. .long _prefix_filesz
  902. .long _max_align
  903. .ascii PACK_OR_COPY
  904. .long _text16_early_lma
  905. .long _text16_early_filesz
  906. .long _max_align
  907. .ascii "PAYL"
  908. .long 0
  909. .long 0
  910. .long _payload_align
  911. .ascii "COPY"
  912. .long _pprefix_lma
  913. .long _pprefix_filesz
  914. .long _max_align
  915. .ascii PACK_OR_COPY
  916. .long _text16_late_lma
  917. .long _text16_late_filesz
  918. .long _max_align
  919. .ascii PACK_OR_COPY
  920. .long _data16_lma
  921. .long _data16_filesz
  922. .long _max_align
  923. .ascii PACK_OR_COPY
  924. .long _textdata_lma
  925. .long _textdata_filesz
  926. .long _max_align
  927. .weak _payload_align
  928. .equ _payload_align, 1