2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 FILE_LICENCE ( GPL2_OR_LATER )
24 /* Image compression enabled */
27 /*****************************************************************************
28 * Utility function: print character (with LF -> LF,CR translation)
31 * %al : character to print
32 * %ds:di : output buffer (or %di=0 to print to console)
34 * %ds:di : next character in output buffer (if applicable)
35 *****************************************************************************
37 .section ".prefix.lib", "awx", @progbits
39 .globl print_character
41 /* Preserve registers */
45 /* If %di is non-zero, write character to buffer and exit */
51 1: /* Print character */
52 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
53 movb $0x0e, %ah /* write char, tty mode */
54 cmpb $0x0a, %al /* '\n'? */
59 /* Restore registers and return */
64 .size print_character, . - print_character
66 /*****************************************************************************
67 * Utility function: print a NUL-terminated string
70 * %ds:si : string to print
71 * %ds:di : output buffer (or %di=0 to print to console)
73 * %ds:si : character after terminating NUL
74 * %ds:di : next character in output buffer (if applicable)
75 *****************************************************************************
77 .section ".prefix.lib", "awx", @progbits
81 /* Preserve registers */
89 2: /* Restore registers and return */
92 .size print_message, . - print_message
94 /*****************************************************************************
95 * Utility functions: print hex digit/byte/word/dword
98 * %al (low nibble) : digit to print
100 * %ax : word to print
101 * %eax : dword to print
102 * %ds:di : output buffer (or %di=0 to print to console)
104 * %ds:di : next character in output buffer (if applicable)
105 *****************************************************************************
107 .section ".prefix.lib", "awx", @progbits
109 .globl print_hex_dword
115 .size print_hex_dword, . - print_hex_dword
116 .globl print_hex_word
122 .size print_hex_word, . - print_hex_word
123 .globl print_hex_byte
126 call print_hex_nibble
129 .size print_hex_byte, . - print_hex_byte
130 .globl print_hex_nibble
132 /* Preserve registers */
134 /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
140 /* Restore registers and return */
143 .size print_hex_nibble, . - print_hex_nibble
145 /*****************************************************************************
146 * Utility function: print PCI bus:dev.fn
149 * %ax : PCI bus:dev.fn to print
150 * %ds:di : output buffer (or %di=0 to print to console)
152 * %ds:di : next character in output buffer (if applicable)
153 *****************************************************************************
155 .section ".prefix.lib", "awx", @progbits
157 .globl print_pci_busdevfn
159 /* Preserve registers */
177 call print_hex_nibble
178 /* Restore registers and return */
181 .size print_pci_busdevfn, . - print_pci_busdevfn
183 /*****************************************************************************
184 * Utility function: clear current line
187 * %ds:di : output buffer (or %di=0 to print to console)
189 * %ds:di : next character in output buffer (if applicable)
190 *****************************************************************************
192 .section ".prefix.lib", "awx", @progbits
194 .globl print_kill_line
196 /* Preserve registers */
202 /* Print 79 spaces */
205 1: call print_character
210 /* Restore registers and return */
214 .size print_kill_line, . - print_kill_line
216 /****************************************************************************
222 * %ds:esi : source address
223 * %es:edi : destination address
226 * %ds:esi : next source address
227 * %es:edi : next destination address
230 ****************************************************************************
233 .section ".prefix.lib", "awx", @progbits
240 .size copy_bytes, . - copy_bytes
241 #endif /* COMPRESS */
243 /****************************************************************************
246 * Install block to specified address
249 * %esi : source physical address (must be a multiple of 16)
250 * %edi : destination physical address (must be a multiple of 16)
251 * %ecx : length of (decompressed) data
252 * %edx : total length of block (including any uninitialised data portion)
254 * %esi : next source physical address (will be a multiple of 16)
255 * %edi : next destination physical address (will be a multiple of 16)
258 ****************************************************************************
260 .section ".prefix.lib", "awx", @progbits
263 /* Preserve registers */
268 /* Convert %esi and %edi to %ds:esi and %es:edi */
279 /* Decompress source to destination */
282 /* Copy source to destination */
286 /* Zero .bss portion */
294 /* Round up %esi and %edi to start of next blocks */
300 /* Convert %ds:esi and %es:edi back to physical addresses */
310 /* Restore registers and return */
315 .size install_block, . - install_block
317 /****************************************************************************
320 * Allocate space for .text16 and .data16 from top of base memory.
321 * Memory is allocated using the BIOS free base memory counter at
327 * %ax : .text16 segment address
328 * %bx : .data16 segment address
331 ****************************************************************************
333 .section ".prefix.lib", "awx", @progbits
337 /* Preserve registers */
340 /* FBMS => %ax as segment address */
346 /* Calculate .data16 segment address */
347 subw $_data16_memsz_pgh, %ax
350 /* Calculate .text16 segment address */
351 subw $_text16_memsz_pgh, %ax
358 /* Retrieve .text16 and .data16 segment addresses */
362 /* Restore registers and return */
365 .size alloc_basemem, . - alloc_basemem
367 /****************************************************************************
370 * Free space allocated with alloc_basemem.
373 * %ax : .text16 segment address
374 * %bx : .data16 segment address
376 * %ax : 0 if successfully freed
379 ****************************************************************************
381 .section ".text16", "ax", @progbits
385 /* Preserve registers */
388 /* Check FBMS counter */
397 /* Check hooked interrupt count */
398 cmpw $0, %cs:hooked_bios_interrupts
401 /* OK to free memory */
402 addw $_text16_memsz_pgh, %ax
403 addw $_data16_memsz_pgh, %ax
408 1: /* Restore registers and return */
411 .size free_basemem, . - free_basemem
413 .section ".text16.data", "aw", @progbits
414 .globl hooked_bios_interrupts
415 hooked_bios_interrupts:
417 .size hooked_bios_interrupts, . - hooked_bios_interrupts
419 /****************************************************************************
422 * Install all text and data segments.
427 * %ax : .text16 segment address
428 * %bx : .data16 segment address
431 ****************************************************************************
433 .section ".prefix.lib", "awx", @progbits
437 /* Preserve registers */
440 /* Allocate space for .text16 and .data16 */
442 /* Image source = %cs:0000 */
444 /* Image destination = default */
446 /* Allow relocation */
448 /* Install text and data segments */
449 call install_prealloc
450 /* Restore registers and return */
454 .size install, . - install
456 /****************************************************************************
459 * Install all text and data segments.
462 * %ax : .text16 segment address
463 * %bx : .data16 segment address
464 * %esi : Image source physical address (or zero for %cs:0000)
465 * %edi : Decompression temporary area physical address (or zero for default)
466 * CF set : Avoid relocating to top of memory
469 ****************************************************************************
471 .section ".prefix.lib", "awx", @progbits
473 .globl install_prealloc
479 cld /* Sanity: clear the direction flag asap */
482 /* Set up %ds for (read-only) access to .prefix */
486 /* Copy decompression temporary area physical address to %ebp */
489 /* Install .text16.early */
494 addl $_text16_early_lma, %esi
497 movl $_text16_early_filesz, %ecx
498 movl $_text16_early_memsz, %edx
499 call install_block /* .text16.early */
503 /* Access high memory */
507 pushw $access_highmem
509 1: /* Die if we could not access high memory */
511 movw $a20_death_message, %si
515 .section ".prefix.data", "aw", @progbits
517 .asciz "\nHigh memory inaccessible - cannot continue\n"
518 .size a20_death_message, . - a20_death_message
523 /* Open payload (which may not yet be in memory) */
529 1: /* Die if we could not access the payload */
534 movw $payload_death_message, %si
537 .section ".prefix.data", "aw", @progbits
538 payload_death_message:
539 .asciz "\nPayload inaccessible - cannot continue\n"
540 .size payload_death_message, . - payload_death_message
544 /* Calculate physical address of payload (i.e. first source) */
549 1: addl payload_lma, %esi
551 /* Install .text16.late and .data16 */
552 movl $_text16_late_filesz, %ecx
553 movl $_text16_late_memsz, %edx
554 call install_block /* .text16.late */
557 movl $_data16_filesz, %ecx
558 movl $_data16_memsz, %edx
559 call install_block /* .data16 */
561 /* Set up %ds for access to .data16 */
565 /* Initialise libkir */
566 movw %ax, (init_libkir_vector+2)
567 lcall *init_libkir_vector
569 /* Find a suitable decompression temporary area, if none specified */
572 /* Use INT 15,88 to find the highest available address via INT
573 * 15,88. This limits us to around 64MB, which should avoid
574 * all of the POST-time memory map failure modes.
581 subl $_textdata_memsz_kb, %ebp
585 /* Install .text and .data to temporary area in high memory,
586 * prior to reading the E820 memory map and relocating
590 movl $_textdata_filesz, %ecx
591 movl $_textdata_memsz, %edx
594 /* Initialise librm at current location */
595 movw %ax, (init_librm_vector+2)
597 lcall *init_librm_vector
599 /* Skip relocation if CF was set on entry */
604 /* Call relocate() to determine target address for relocation.
605 * relocate() will return with %esi, %edi and %ecx set up
606 * ready for the copy to the new location.
608 movw %ax, (prot_call_vector+2)
610 lcall *prot_call_vector
611 popl %edx /* discard */
613 /* Copy code to new location */
622 /* Initialise librm at new location */
623 lcall *init_librm_vector
627 /* Close access to payload */
628 movw %ax, (close_payload_vector+2)
629 lcall *close_payload_vector
631 /* Restore registers */
637 .size install_prealloc, . - install_prealloc
639 /* Vectors for far calls to .text16 functions. Must be in
640 * .data16, since .prefix may not be writable.
642 .section ".data16", "aw", @progbits
647 .size init_libkir_vector, . - init_libkir_vector
652 .size init_librm_vector, . - init_librm_vector
656 .size prot_call_vector, . - prot_call_vector
658 close_payload_vector:
661 .size close_payload_vector, . - close_payload_vector
663 /* Payload address */
664 .section ".prefix.lib", "awx", @progbits
667 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
674 /* Dummy routines to open and close payload */
675 .section ".text16.early.data", "aw", @progbits
682 .size open_payload, . - open_payload
683 .size close_payload, . - close_payload
685 /****************************************************************************
688 * Uninstall all text and data segments.
691 * %ax : .text16 segment address
692 * %bx : .data16 segment address
697 ****************************************************************************
699 .section ".text16", "ax", @progbits
705 .size uninstall, . - uninstall
709 /* File split information for the compressor */
711 #define PACK_OR_COPY "PACK"
713 #define PACK_OR_COPY "COPY"
715 .section ".zinfo", "a", @progbits
721 .long _text16_early_lma
722 .long _text16_early_filesz
729 .long _text16_late_lma
730 .long _text16_late_filesz
738 .long _textdata_filesz