[FREELDR] Several changes regarding chainloading and Linux boot.
[reactos.git] / boot / freeldr / freeldr / arch / i386 / linux.S
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
24 EXTERN _DiskStopFloppyMotor:PROC
25 EXTERN _Relocator16Boot:PROC
26 EXTERN _FrldrBootDrive:BYTE
27 EXTERN _FrldrBootPartition:DWORD
28
29 .code32
30
31 Regs:
32 .space REGS_SIZE
33
34 /*
35 * VOID __cdecl BootLinuxKernel(
36 * IN ULONG KernelSize,
37 * IN PVOID KernelCurrentLoadAddress,
38 * IN PVOID KernelTargetLoadAddress,
39 * IN UCHAR DriveNumber,
40 * IN ULONG PartitionNumber);
41 */
42 PUBLIC _BootLinuxKernel
43 _BootLinuxKernel:
44
45 /* Stop the floppy drive motor */
46 call _DiskStopFloppyMotor
47
48 /* Set all segment registers to 0x9000 */
49 mov ax, HEX(9000)
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
54
55 /* Set the boot drive */
56 xor edx, edx
57 mov dl, byte ptr [esp + 16]
58 test dl, dl
59 jnz set_part
60 mov dl, byte ptr ds:[_FrldrBootDrive]
61
62 /* Set the boot partition */
63 set_part:
64 mov eax, dword ptr [esp + 20]
65 test eax, eax
66 jnz continue
67 mov eax, dword ptr ds:[_FrldrBootPartition]
68 continue:
69 /* Store the 1-byte truncated partition number in DH */
70 mov dh, al
71
72 mov dword ptr [Regs + REGS_EDX], edx
73
74 /*
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.
79 */
80
81 /* Get KernelSize in ECX */
82 mov ecx, dword ptr [esp + 4]
83 test ecx, ecx // If size is zero, do not perform relocations
84 jz after_reloc
85
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)
89
90 //
91 // FIXME: Support relocating *upwards*, overlapping regions, aligned addresses,
92 // etc... !! See memmove code.
93 //
94 /* Check how we should perform relocation */
95 cmp edi, esi
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)
99
100 reloc_down:
101 /* Move the kernel down - Start with low addresses and increment them */
102 cld
103 #if 0
104 rep movsb
105 #else
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
113 #endif
114 jmp after_reloc
115
116 reloc_up:
117 /* Move the kernel up - Start with high addresses and decrement them */
118 std
119 add esi, ecx
120 add edi, ecx
121 dec esi
122 dec edi
123 rep movsb
124 // jmp after_reloc
125
126 after_reloc:
127
128 push HEX(0000) // CodePointer
129 push HEX(9020) // CodeSegment
130 push HEX(9000) // StackPointer
131 push HEX(9000) // StackSegment
132 mov eax, offset Regs
133 push eax
134 call _Relocator16Boot
135
136 /* We must never get there */
137 int 3
138
139 END