diff options
Diffstat (limited to 'gpxe/src/arch/i386/prefix/libprefix.S')
-rw-r--r-- | gpxe/src/arch/i386/prefix/libprefix.S | 819 |
1 files changed, 0 insertions, 819 deletions
diff --git a/gpxe/src/arch/i386/prefix/libprefix.S b/gpxe/src/arch/i386/prefix/libprefix.S deleted file mode 100644 index 9e6ba6f0..00000000 --- a/gpxe/src/arch/i386/prefix/libprefix.S +++ /dev/null @@ -1,819 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - - .arch i386 - -/** - * High memory temporary load address - * - * Temporary buffer into which to copy (or decompress) our runtime - * image, prior to calling get_memmap() and relocate(). We don't - * actually leave anything here once install() has returned. - * - * We use the start of an even megabyte so that we don't have to worry - * about the current state of the A20 line. - * - * We use 4MB rather than 2MB because some PXE stack / PMM BIOS - * combinations are known to place data required by other UNDI ROMs - * loader around the 2MB mark. - */ - .globl HIGHMEM_LOADPOINT - .equ HIGHMEM_LOADPOINT, ( 4 << 20 ) - -/* Image compression enabled */ -#define COMPRESS 1 - -#define CR0_PE 1 - -/***************************************************************************** - * Utility function: print character (with LF -> LF,CR translation) - * - * Parameters: - * %al : character to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_character -print_character: - /* Preserve registers */ - pushw %ax - pushw %bx - pushw %bp - /* If %di is non-zero, write character to buffer and exit */ - testw %di, %di - jz 1f - movb %al, %ds:(%di) - incw %di - jmp 3f -1: /* Print character */ - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - movb $0x0e, %ah /* write char, tty mode */ - cmpb $0x0a, %al /* '\n'? */ - jne 2f - int $0x10 - movb $0x0d, %al -2: int $0x10 - /* Restore registers and return */ -3: popw %bp - popw %bx - popw %ax - ret - .size print_character, . - print_character - -/***************************************************************************** - * Utility function: print a NUL-terminated string - * - * Parameters: - * %ds:si : string to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:si : character after terminating NUL - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_message -print_message: - /* Preserve registers */ - pushw %ax - /* Print string */ -1: lodsb - testb %al, %al - je 2f - call print_character - jmp 1b -2: /* Restore registers and return */ - popw %ax - ret - .size print_message, . - print_message - -/***************************************************************************** - * Utility functions: print hex digit/byte/word/dword - * - * Parameters: - * %al (low nibble) : digit to print - * %al : byte to print - * %ax : word to print - * %eax : dword to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_hex_dword -print_hex_dword: - rorl $16, %eax - call print_hex_word - rorl $16, %eax - /* Fall through */ - .size print_hex_dword, . - print_hex_dword - .globl print_hex_word -print_hex_word: - xchgb %al, %ah - call print_hex_byte - xchgb %al, %ah - /* Fall through */ - .size print_hex_word, . - print_hex_word - .globl print_hex_byte -print_hex_byte: - rorb $4, %al - call print_hex_nibble - rorb $4, %al - /* Fall through */ - .size print_hex_byte, . - print_hex_byte - .globl print_hex_nibble -print_hex_nibble: - /* Preserve registers */ - pushw %ax - /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */ - andb $0x0f, %al - cmpb $10, %al - sbbb $0x69, %al - das - call print_character - /* Restore registers and return */ - popw %ax - ret - .size print_hex_nibble, . - print_hex_nibble - -/***************************************************************************** - * Utility function: print PCI bus:dev.fn - * - * Parameters: - * %ax : PCI bus:dev.fn to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_pci_busdevfn -print_pci_busdevfn: - /* Preserve registers */ - pushw %ax - /* Print bus */ - xchgb %al, %ah - call print_hex_byte - /* Print ":" */ - movb $( ':' ), %al - call print_character - /* Print device */ - movb %ah, %al - shrb $3, %al - call print_hex_byte - /* Print "." */ - movb $( '.' ), %al - call print_character - /* Print function */ - movb %ah, %al - andb $0x07, %al - call print_hex_nibble - /* Restore registers and return */ - popw %ax - ret - .size print_pci_busdevfn, . - print_pci_busdevfn - -/***************************************************************************** - * Utility function: clear current line - * - * Parameters: - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_kill_line -print_kill_line: - /* Preserve registers */ - pushw %ax - pushw %cx - /* Print CR */ - movb $( '\r' ), %al - call print_character - /* Print 79 spaces */ - movb $( ' ' ), %al - movw $79, %cx -1: call print_character - loop 1b - /* Print CR */ - movb $( '\r' ), %al - call print_character - /* Restore registers and return */ - popw %cx - popw %ax - ret - .size print_kill_line, . - print_kill_line - -/**************************************************************************** - * pm_call (real-mode near call) - * - * Call routine in 16-bit protected mode for access to extended memory - * - * Parameters: - * %ax : address of routine to call in 16-bit protected mode - * Returns: - * none - * Corrupts: - * %ax - * - * The specified routine is called in 16-bit protected mode, with: - * - * %cs : 16-bit code segment with base matching real-mode %cs - * %ss : 16-bit data segment with base matching real-mode %ss - * %ds,%es,%fs,%gs : 32-bit data segment with zero base and 4GB limit - * - **************************************************************************** - */ - -#ifndef KEEP_IT_REAL - - /* GDT for protected-mode calls */ - .section ".prefix.lib", "awx", @progbits - .align 16 -pm_call_vars: -gdt: -gdt_limit: .word gdt_length - 1 -gdt_base: .long 0 - .word 0 /* padding */ -pm_cs: /* 16-bit protected-mode code segment */ - .equ PM_CS, pm_cs - gdt - .word 0xffff, 0 - .byte 0, 0x9b, 0x00, 0 -pm_ss: /* 16-bit protected-mode stack segment */ - .equ PM_SS, pm_ss - gdt - .word 0xffff, 0 - .byte 0, 0x93, 0x00, 0 -pm_ds: /* 32-bit protected-mode flat data segment */ - .equ PM_DS, pm_ds - gdt - .word 0xffff, 0 - .byte 0, 0x93, 0xcf, 0 -gdt_end: - .equ gdt_length, . - gdt - .size gdt, . - gdt - - .section ".prefix.lib", "awx", @progbits - .align 16 -pm_saved_gdt: - .long 0, 0 - .size pm_saved_gdt, . - pm_saved_gdt - - .equ pm_call_vars_size, . - pm_call_vars -#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) ) - - .section ".prefix.lib", "awx", @progbits - .code16 -pm_call: - /* Preserve registers, flags, and RM return point */ - pushw %bp - movw %sp, %bp - subw $pm_call_vars_size, %sp - andw $0xfff0, %sp - pushfl - pushw %gs - pushw %fs - pushw %es - pushw %ds - pushw %ss - pushw %cs - pushw $99f - - /* Set up local variable block, and preserve GDT */ - pushw %cx - pushw %si - pushw %di - pushw %ss - popw %es - movw $pm_call_vars, %si - leaw PM_CALL_VAR(pm_call_vars)(%bp), %di - movw $pm_call_vars_size, %cx - cs rep movsb - popw %di - popw %si - popw %cx - sgdt PM_CALL_VAR(pm_saved_gdt)(%bp) - - /* Set up GDT bases */ - pushl %eax - pushl %edi - xorl %eax, %eax - movw %ss, %ax - shll $4, %eax - movzwl %bp, %edi - addr32 leal PM_CALL_VAR(gdt)(%eax, %edi), %eax - movl %eax, PM_CALL_VAR(gdt_base)(%bp) - movw %cs, %ax - movw $PM_CALL_VAR(pm_cs), %di - call set_seg_base - movw %ss, %ax - movw $PM_CALL_VAR(pm_ss), %di - call set_seg_base - popl %edi - popl %eax - - /* Switch CPU to protected mode and load up segment registers */ - pushl %eax - cli - data32 lgdt PM_CALL_VAR(gdt)(%bp) - movl %cr0, %eax - orb $CR0_PE, %al - movl %eax, %cr0 - ljmp $PM_CS, $1f -1: movw $PM_SS, %ax - movw %ax, %ss - movw $PM_DS, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - popl %eax - - /* Call PM routine */ - call *%ax - - /* Set real-mode segment limits on %ds, %es, %fs and %gs */ - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - - /* Return CPU to real mode */ - movl %cr0, %eax - andb $0!CR0_PE, %al - movl %eax, %cr0 - - /* Restore registers and flags */ - lret /* will ljmp to 99f */ -99: popw %ss - popw %ds - popw %es - popw %fs - popw %gs - data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp) - popfl - movw %bp, %sp - popw %bp - ret - .size pm_call, . - pm_call - -set_seg_base: - rolw $4, %ax - movw %ax, 2(%bp,%di) - andw $0xfff0, 2(%bp,%di) - movb %al, 4(%bp,%di) - andb $0x0f, 4(%bp,%di) - ret - .size set_seg_base, . - set_seg_base - -#endif /* KEEP_IT_REAL */ - -/**************************************************************************** - * copy_bytes (real-mode or 16-bit protected-mode near call) - * - * Copy bytes - * - * Parameters: - * %ds:esi : source address - * %es:edi : destination address - * %ecx : length - * Returns: - * %ds:esi : next source address - * %es:edi : next destination address - * Corrupts: - * None - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 -copy_bytes: - pushl %ecx - rep addr32 movsb - popl %ecx - ret - .size copy_bytes, . - copy_bytes - -/**************************************************************************** - * install_block (real-mode near call) - * - * Install block to specified address - * - * Parameters: - * %esi : source physical address (must be a multiple of 16) - * %edi : destination physical address (must be a multiple of 16) - * %ecx : length of (decompressed) data - * %edx : total length of block (including any uninitialised data portion) - * Returns: - * %esi : next source physical address (will be a multiple of 16) - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 -install_block: - -#ifdef KEEP_IT_REAL - - /* Preserve registers */ - pushw %ds - pushw %es - pushl %ecx - pushl %edi - - /* Convert %esi and %edi to segment registers */ - shrl $4, %esi - movw %si, %ds - xorw %si, %si - shrl $4, %edi - movw %di, %es - xorw %di, %di - -#else /* KEEP_IT_REAL */ - - /* Call self in protected mode */ - pushw %ax - movw $1f, %ax - call pm_call - popw %ax - ret -1: - /* Preserve registers */ - pushl %ecx - pushl %edi - -#endif /* KEEP_IT_REAL */ - - -#if COMPRESS - /* Decompress source to destination */ - call decompress16 -#else - /* Copy source to destination */ - call copy_bytes -#endif - - /* Zero .bss portion */ - negl %ecx - addl %edx, %ecx - pushw %ax - xorw %ax, %ax - rep addr32 stosb - popw %ax - - /* Round up %esi to start of next source block */ - addl $0xf, %esi - andl $~0xf, %esi - - -#ifdef KEEP_IT_REAL - - /* Convert %ds:esi back to a physical address */ - movzwl %ds, %cx - shll $4, %ecx - addl %ecx, %esi - - /* Restore registers */ - popl %edi - popl %ecx - popw %es - popw %ds - -#else /* KEEP_IT_REAL */ - - /* Restore registers */ - popl %edi - popl %ecx - -#endif - - ret - .size install_block, . - install_block - -/**************************************************************************** - * alloc_basemem (real-mode near call) - * - * Allocate space for .text16 and .data16 from top of base memory. - * Memory is allocated using the BIOS free base memory counter at - * 0x40:13. - * - * Parameters: - * none - * Returns: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl alloc_basemem -alloc_basemem: - /* Preserve registers */ - pushw %fs - - /* FBMS => %ax as segment address */ - pushw $0x40 - popw %fs - movw %fs:0x13, %ax - shlw $6, %ax - - /* Calculate .data16 segment address */ - subw $_data16_memsz_pgh, %ax - pushw %ax - - /* Calculate .text16 segment address */ - subw $_text16_memsz_pgh, %ax - pushw %ax - - /* Update FBMS */ - shrw $6, %ax - movw %ax, %fs:0x13 - - /* Retrieve .text16 and .data16 segment addresses */ - popw %ax - popw %bx - - /* Restore registers and return */ - popw %fs - ret - .size alloc_basemem, . - alloc_basemem - -/**************************************************************************** - * free_basemem (real-mode near call) - * - * Free space allocated with alloc_basemem. - * - * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Returns: - * %ax : 0 if successfully freed - * Corrupts: - * none - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl free_basemem -free_basemem: - /* Preserve registers */ - pushw %fs - - /* Check FBMS counter */ - pushw %ax - shrw $6, %ax - pushw $0x40 - popw %fs - cmpw %ax, %fs:0x13 - popw %ax - jne 1f - - /* Check hooked interrupt count */ - cmpw $0, %cs:hooked_bios_interrupts - jne 1f - - /* OK to free memory */ - addw $_text16_memsz_pgh, %ax - addw $_data16_memsz_pgh, %ax - shrw $6, %ax - movw %ax, %fs:0x13 - xorw %ax, %ax - -1: /* Restore registers and return */ - popw %fs - ret - .size free_basemem, . - free_basemem - - .section ".text16.data", "aw", @progbits - .globl hooked_bios_interrupts -hooked_bios_interrupts: - .word 0 - .size hooked_bios_interrupts, . - hooked_bios_interrupts - -/**************************************************************************** - * install (real-mode near call) - * - * Install all text and data segments. - * - * Parameters: - * none - * Returns: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl install -install: - /* Preserve registers */ - pushl %esi - pushl %edi - /* Allocate space for .text16 and .data16 */ - call alloc_basemem - /* Image source = %cs:0000 */ - xorl %esi, %esi - /* Image destination = HIGHMEM_LOADPOINT */ - movl $HIGHMEM_LOADPOINT, %edi - /* Install text and data segments */ - call install_prealloc - /* Restore registers and return */ - popl %edi - popl %esi - ret - .size install, . - install - -/**************************************************************************** - * install_prealloc (real-mode near call) - * - * Install all text and data segments. - * - * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address - * %esi : Image source physical address (or zero for %cs:0000) - * %edi : Decompression temporary area physical address - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl install_prealloc -install_prealloc: - /* Save registers */ - pushal - pushw %ds - pushw %es - - /* Sanity: clear the direction flag asap */ - cld - - /* Calculate physical address of payload (i.e. first source) */ - testl %esi, %esi - jnz 1f - movw %cs, %si - shll $4, %esi -1: addl $_payload_lma, %esi - - /* Install .text16 and .data16 */ - pushl %edi - movzwl %ax, %edi - shll $4, %edi - movl $_text16_memsz, %ecx - movl %ecx, %edx - call install_block /* .text16 */ - movzwl %bx, %edi - shll $4, %edi - movl $_data16_filesz, %ecx - movl $_data16_memsz, %edx - call install_block /* .data16 */ - popl %edi - - /* Set up %ds for access to .data16 */ - movw %bx, %ds - -#ifdef KEEP_IT_REAL - /* Initialise libkir */ - movw %ax, (init_libkir_vector+2) - lcall *init_libkir_vector -#else - /* Install .text and .data to temporary area in high memory, - * prior to reading the E820 memory map and relocating - * properly. - */ - movl $_textdata_filesz, %ecx - movl $_textdata_memsz, %edx - call install_block - - /* Initialise librm at current location */ - movw %ax, (init_librm_vector+2) - lcall *init_librm_vector - - /* Call relocate() to determine target address for relocation. - * relocate() will return with %esi, %edi and %ecx set up - * ready for the copy to the new location. - */ - movw %ax, (prot_call_vector+2) - pushl $relocate - lcall *prot_call_vector - popl %edx /* discard */ - - /* Copy code to new location */ - pushl %edi - pushw %ax - movw $copy_bytes, %ax - call pm_call - popw %ax - popl %edi - - /* Initialise librm at new location */ - lcall *init_librm_vector - -#endif - /* Restore registers */ - popw %es - popw %ds - popal - ret - .size install_prealloc, . - install_prealloc - - /* Vectors for far calls to .text16 functions */ - .section ".data16", "aw", @progbits -#ifdef KEEP_IT_REAL -init_libkir_vector: - .word init_libkir - .word 0 - .size init_libkir_vector, . - init_libkir_vector -#else -init_librm_vector: - .word init_librm - .word 0 - .size init_librm_vector, . - init_librm_vector -prot_call_vector: - .word prot_call - .word 0 - .size prot_call_vector, . - prot_call_vector -#endif - -/**************************************************************************** - * uninstall (real-mode near call) - * - * Uninstall all text and data segments. - * - * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Returns: - * none - * Corrupts: - * none - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl uninstall -uninstall: - call free_basemem - ret - .size uninstall, . - uninstall - - - - /* File split information for the compressor */ -#if COMPRESS - .section ".zinfo", "a", @progbits - .ascii "COPY" - .long _prefix_lma - .long _prefix_filesz - .long _max_align - .ascii "PACK" - .long _text16_lma - .long _text16_filesz - .long _max_align - .ascii "PACK" - .long _data16_lma - .long _data16_filesz - .long _max_align - .ascii "PACK" - .long _textdata_lma - .long _textdata_filesz - .long _max_align -#else /* COMPRESS */ - .section ".zinfo", "a", @progbits - .ascii "COPY" - .long _prefix_lma - .long _filesz - .long _max_align -#endif /* COMPRESS */ |