3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
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.
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.
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.
21 #include <arch/pc/x86common.h>
22 #include <arch/pc/pcbios.h>
24 EXTERN _DiskStopFloppyMotor:PROC
25 EXTERN _Relocator16Boot:PROC
26 EXTERN _FrldrBootDrive:BYTE
27 EXTERN _FrldrBootPartition:DWORD
35 * VOID __cdecl BootLinuxKernel(
36 * IN ULONG KernelSize,
37 * IN PVOID KernelCurrentLoadAddress,
38 * IN PVOID KernelTargetLoadAddress,
39 * IN UCHAR DriveNumber,
40 * IN ULONG PartitionNumber);
42 PUBLIC _BootLinuxKernel
45 /* Stop the floppy drive motor */
46 call _DiskStopFloppyMotor
48 /* Set all segment registers to 0x9000 */
50 mov word ptr [Regs + REGS_DS], ax
51 mov word ptr [Regs + REGS_ES], ax
52 mov word ptr [Regs + REGS_FS], ax
53 mov word ptr [Regs + REGS_GS], ax
55 /* Set the boot drive */
57 mov dl, byte ptr [esp + 16]
60 mov dl, byte ptr ds:[_FrldrBootDrive]
62 /* Set the boot partition */
64 mov eax, dword ptr [esp + 20]
67 mov eax, dword ptr ds:[_FrldrBootPartition]
69 /* Store the 1-byte truncated partition number in DH */
72 mov dword ptr [Regs + REGS_EDX], edx
75 * Relocate the kernel image to its final destination (can be as low as 0x10000).
76 * The reason we can overwrite low memory is because this code executes
77 * between 0000:8000 and 0000:FFFF. That leaves space for 32k of code
78 * before we start interfering with Linux kernel address space.
81 /* Get KernelSize in ECX */
82 mov ecx, dword ptr [esp + 4]
83 test ecx, ecx // If size is zero, do not perform relocations
86 /* Load the source and target addresses */
87 mov esi, dword ptr [esp + 8] // HEX(100000) // LINUX_KERNEL_LOAD_ADDRESS
88 mov edi, dword ptr [esp + 12] // HEX(10000)
91 // FIXME: Support relocating *upwards*, overlapping regions, aligned addresses,
92 // etc... !! See memmove code.
94 /* Check how we should perform relocation */
96 je after_reloc // target == source: do not perform relocations
97 ja reloc_up // target > source: relocate up
98 // jb reloc_down // target < source: relocate down (default)
101 /* Move the kernel down - Start with low addresses and increment them */
106 mov edx, ecx // Copy the total number of bytes in EDX
107 and edx, HEX(0FFFFFFFC) // Number of bytes we copy using DWORDs
108 xor edx, ecx // Number of remaining bytes to copy after the DWORDs
109 shr ecx, 2 // Count number of DWORDs
110 rep movsd // Move DWORDs
111 mov ecx, edx // Count number of remaining bytes
112 rep movsb // Move bytes
117 /* Move the kernel up - Start with high addresses and decrement them */
128 push HEX(0000) // CodePointer
129 push HEX(9020) // CodeSegment
130 push HEX(9000) // StackPointer
131 push HEX(9000) // StackSegment
134 call _Relocator16Boot
136 /* We must never get there */