1/* 2 * FreeLoader 3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20#include <asm.inc> 21#include <arch/pc/x86common.h> 22#include <arch/pc/pcbios.h> 23 24EXTERN _DiskStopFloppyMotor:PROC 25EXTERN _Relocator16Boot:PROC 26 27.code32 28 29Regs: 30 .space REGS_SIZE 31 32/* 33 * VOID __cdecl 34 * BootLinuxKernel( 35 * _In_ ULONG KernelSize, 36 * _In_ PVOID KernelCurrentLoadAddress, 37 * _In_ PVOID KernelTargetLoadAddress); 38 */ 39PUBLIC _BootLinuxKernel 40_BootLinuxKernel: 41 42 /* Stop the floppy drive motor */ 43 call _DiskStopFloppyMotor 44 45 /* Set all segment registers to 0x9000 */ 46 mov ax, HEX(9000) 47 mov word ptr [Regs + REGS_DS], ax 48 mov word ptr [Regs + REGS_ES], ax 49 mov word ptr [Regs + REGS_FS], ax 50 mov word ptr [Regs + REGS_GS], ax 51 52 /* 53 * Relocate the kernel image to its final destination (can be as low as 0x10000). 54 * The reason we can overwrite low memory is because this code executes 55 * between 0000:8000 and 0000:FFFF. That leaves space for 32k of code 56 * before we start interfering with Linux kernel address space. 57 */ 58 59 /* Get KernelSize in ECX */ 60 mov ecx, dword ptr [esp + 4] 61 test ecx, ecx // If size is zero, do not perform relocations 62 jz after_reloc 63 64 /* Load the source and target addresses */ 65 mov esi, dword ptr [esp + 8] // HEX(100000) // LINUX_KERNEL_LOAD_ADDRESS 66 mov edi, dword ptr [esp + 12] // HEX(10000) 67 68// 69// FIXME: Support relocating *upwards*, overlapping regions, aligned addresses, 70// etc... !! See memmove code. 71// 72 /* Check how we should perform relocation */ 73 cmp edi, esi 74 je after_reloc // target == source: do not perform relocations 75 ja reloc_up // target > source: relocate up 76// jb reloc_down // target < source: relocate down (default) 77 78reloc_down: 79 /* Move the kernel down - Start with low addresses and increment them */ 80 cld 81#if 0 82 rep movsb 83#else 84 mov edx, ecx // Copy the total number of bytes in EDX 85 and edx, HEX(0FFFFFFFC) // Number of bytes we copy using DWORDs 86 xor edx, ecx // Number of remaining bytes to copy after the DWORDs 87 shr ecx, 2 // Count number of DWORDs 88 rep movsd // Move DWORDs 89 mov ecx, edx // Count number of remaining bytes 90 rep movsb // Move bytes 91#endif 92 jmp after_reloc 93 94reloc_up: 95 /* Move the kernel up - Start with high addresses and decrement them */ 96 std 97 add esi, ecx 98 add edi, ecx 99 dec esi 100 dec edi 101 rep movsb 102 // jmp after_reloc 103 104after_reloc: 105 106 push HEX(0000) // CodePointer 107 push HEX(9020) // CodeSegment 108 push HEX(9000) // StackPointer 109 push HEX(9000) // StackSegment 110 mov eax, offset Regs 111 push eax 112 call _Relocator16Boot 113 114 /* We must never get there */ 115 int 3 116 117END 118