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 )
25 * High memory temporary load address
27 * Temporary buffer into which to copy (or decompress) our runtime
28 * image, prior to calling get_memmap() and relocate(). We don't
29 * actually leave anything here once install() has returned.
31 .globl HIGHMEM_LOADPOINT
32 .equ HIGHMEM_LOADPOINT, ( 1 << 20 )
34 /* Image compression enabled */
37 /*****************************************************************************
38 * Utility function: print character (with LF -> LF,CR translation)
41 * %al : character to print
42 * %ds:di : output buffer (or %di=0 to print to console)
44 * %ds:di : next character in output buffer (if applicable)
45 *****************************************************************************
47 .section ".prefix.lib", "awx", @progbits
49 .globl print_character
51 /* Preserve registers */
55 /* If %di is non-zero, write character to buffer and exit */
61 1: /* Print character */
62 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
63 movb $0x0e, %ah /* write char, tty mode */
64 cmpb $0x0a, %al /* '\n'? */
69 /* Restore registers and return */
74 .size print_character, . - print_character
76 /*****************************************************************************
77 * Utility function: print a NUL-terminated string
80 * %ds:si : string to print
81 * %ds:di : output buffer (or %di=0 to print to console)
83 * %ds:si : character after terminating NUL
84 * %ds:di : next character in output buffer (if applicable)
85 *****************************************************************************
87 .section ".prefix.lib", "awx", @progbits
91 /* Preserve registers */
99 2: /* Restore registers and return */
102 .size print_message, . - print_message
104 /*****************************************************************************
105 * Utility functions: print hex digit/byte/word/dword
108 * %al (low nibble) : digit to print
109 * %al : byte to print
110 * %ax : word to print
111 * %eax : dword to print
112 * %ds:di : output buffer (or %di=0 to print to console)
114 * %ds:di : next character in output buffer (if applicable)
115 *****************************************************************************
117 .section ".prefix.lib", "awx", @progbits
119 .globl print_hex_dword
125 .size print_hex_dword, . - print_hex_dword
126 .globl print_hex_word
132 .size print_hex_word, . - print_hex_word
133 .globl print_hex_byte
136 call print_hex_nibble
139 .size print_hex_byte, . - print_hex_byte
140 .globl print_hex_nibble
142 /* Preserve registers */
144 /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
150 /* Restore registers and return */
153 .size print_hex_nibble, . - print_hex_nibble
155 /*****************************************************************************
156 * Utility function: print PCI bus:dev.fn
159 * %ax : PCI bus:dev.fn to print
160 * %ds:di : output buffer (or %di=0 to print to console)
162 * %ds:di : next character in output buffer (if applicable)
163 *****************************************************************************
165 .section ".prefix.lib", "awx", @progbits
167 .globl print_pci_busdevfn
169 /* Preserve registers */
187 call print_hex_nibble
188 /* Restore registers and return */
191 .size print_pci_busdevfn, . - print_pci_busdevfn
193 /*****************************************************************************
194 * Utility function: clear current line
197 * %ds:di : output buffer (or %di=0 to print to console)
199 * %ds:di : next character in output buffer (if applicable)
200 *****************************************************************************
202 .section ".prefix.lib", "awx", @progbits
204 .globl print_kill_line
206 /* Preserve registers */
212 /* Print 79 spaces */
215 1: call print_character
220 /* Restore registers and return */
224 .size print_kill_line, . - print_kill_line
226 /****************************************************************************
232 * %ds:esi : source address
233 * %es:edi : destination address
236 * %ds:esi : next source address
237 * %es:edi : next destination address
240 ****************************************************************************
243 .section ".prefix.lib", "awx", @progbits
250 .size copy_bytes, . - copy_bytes
251 #endif /* COMPRESS */
253 /****************************************************************************
256 * Install block to specified address
259 * %esi : source physical address (must be a multiple of 16)
260 * %edi : destination physical address (must be a multiple of 16)
261 * %ecx : length of (decompressed) data
262 * %edx : total length of block (including any uninitialised data portion)
264 * %esi : next source physical address (will be a multiple of 16)
265 * %edi : next destination physical address (will be a multiple of 16)
268 ****************************************************************************
270 .section ".prefix.lib", "awx", @progbits
273 /* Preserve registers */
278 /* Convert %esi and %edi to %ds:esi and %es:edi */
289 /* Decompress source to destination */
292 /* Copy source to destination */
296 /* Zero .bss portion */
304 /* Round up %esi and %edi to start of next blocks */
310 /* Convert %ds:esi and %es:edi back to physical addresses */
320 /* Restore registers and return */
325 .size install_block, . - install_block
327 /****************************************************************************
330 * Allocate space for .text16 and .data16 from top of base memory.
331 * Memory is allocated using the BIOS free base memory counter at
337 * %ax : .text16 segment address
338 * %bx : .data16 segment address
341 ****************************************************************************
343 .section ".prefix.lib", "awx", @progbits
347 /* Preserve registers */
350 /* FBMS => %ax as segment address */
356 /* Calculate .data16 segment address */
357 subw $_data16_memsz_pgh, %ax
360 /* Calculate .text16 segment address */
361 subw $_text16_memsz_pgh, %ax
368 /* Retrieve .text16 and .data16 segment addresses */
372 /* Restore registers and return */
375 .size alloc_basemem, . - alloc_basemem
377 /****************************************************************************
380 * Free space allocated with alloc_basemem.
383 * %ax : .text16 segment address
384 * %bx : .data16 segment address
386 * %ax : 0 if successfully freed
389 ****************************************************************************
391 .section ".text16", "ax", @progbits
395 /* Preserve registers */
398 /* Check FBMS counter */
407 /* Check hooked interrupt count */
408 cmpw $0, %cs:hooked_bios_interrupts
411 /* OK to free memory */
412 addw $_text16_memsz_pgh, %ax
413 addw $_data16_memsz_pgh, %ax
418 1: /* Restore registers and return */
421 .size free_basemem, . - free_basemem
423 .section ".text16.data", "aw", @progbits
424 .globl hooked_bios_interrupts
425 hooked_bios_interrupts:
427 .size hooked_bios_interrupts, . - hooked_bios_interrupts
429 /****************************************************************************
432 * Install all text and data segments.
437 * %ax : .text16 segment address
438 * %bx : .data16 segment address
441 ****************************************************************************
443 .section ".prefix.lib", "awx", @progbits
447 /* Preserve registers */
450 /* Allocate space for .text16 and .data16 */
452 /* Image source = %cs:0000 */
454 /* Image destination = HIGHMEM_LOADPOINT */
455 movl $HIGHMEM_LOADPOINT, %edi
456 /* Install text and data segments */
457 call install_prealloc
458 /* Restore registers and return */
462 .size install, . - install
464 /****************************************************************************
467 * Install all text and data segments.
470 * %ax : .text16 segment address
471 * %bx : .data16 segment address
472 * %esi : Image source physical address (or zero for %cs:0000)
473 * %edi : Decompression temporary area physical address
476 ****************************************************************************
478 .section ".prefix.lib", "awx", @progbits
480 .globl install_prealloc
487 /* Sanity: clear the direction flag asap */
490 /* Copy decompression temporary area physical address to %ebp */
493 /* Install .text16.early */
498 addl $_text16_early_lma, %esi
501 movl $_text16_early_filesz, %ecx
502 movl $_text16_early_memsz, %edx
503 call install_block /* .text16.early */
506 /* Open up access to payload */
508 /* Access high memory */
512 pushw $access_highmem
514 1: /* Die if we could not access high memory */
516 movw $a20_death_message, %si
520 .section ".prefix.data", "aw", @progbits
522 .asciz "Gate A20 stuck - cannot continue\n"
523 .size a20_death_message, . - a20_death_message
528 /* Calculate physical address of payload (i.e. first source) */
533 1: addl %cs:payload_lma, %esi
535 /* Install .text16.late and .data16 */
536 movl $_text16_late_filesz, %ecx
537 movl $_text16_late_memsz, %edx
538 call install_block /* .text16.late */
541 movl $_data16_filesz, %ecx
542 movl $_data16_memsz, %edx
543 call install_block /* .data16 */
545 /* Set up %ds for access to .data16 */
549 /* Initialise libkir */
550 movw %ax, (init_libkir_vector+2)
551 lcall *init_libkir_vector
553 /* Install .text and .data to temporary area in high memory,
554 * prior to reading the E820 memory map and relocating
558 movl $_textdata_filesz, %ecx
559 movl $_textdata_memsz, %edx
562 /* Initialise librm at current location */
563 movw %ax, (init_librm_vector+2)
565 lcall *init_librm_vector
567 /* Call relocate() to determine target address for relocation.
568 * relocate() will return with %esi, %edi and %ecx set up
569 * ready for the copy to the new location.
571 movw %ax, (prot_call_vector+2)
573 lcall *prot_call_vector
574 popl %edx /* discard */
576 /* Copy code to new location */
583 /* Initialise librm at new location */
584 lcall *init_librm_vector
587 /* Restore registers */
592 .size install_prealloc, . - install_prealloc
594 /* Vectors for far calls to .text16 functions. Must be in
595 * .data16, since .prefix may not be writable.
597 .section ".data16", "aw", @progbits
602 .size init_libkir_vector, . - init_libkir_vector
607 .size init_librm_vector, . - init_librm_vector
611 .size prot_call_vector, . - prot_call_vector
614 /* Payload address */
615 .section ".prefix.lib", "awx", @progbits
618 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
625 /****************************************************************************
628 * Uninstall all text and data segments.
631 * %ax : .text16 segment address
632 * %bx : .data16 segment address
637 ****************************************************************************
639 .section ".text16", "ax", @progbits
645 .size uninstall, . - uninstall
649 /* File split information for the compressor */
651 #define PACK_OR_COPY "PACK"
653 #define PACK_OR_COPY "COPY"
655 .section ".zinfo", "a", @progbits
661 .long _text16_early_lma
662 .long _text16_early_filesz
669 .long _text16_late_lma
670 .long _text16_late_filesz
678 .long _textdata_filesz