xref: /reactos/boot/freeldr/freeldr/arch/i386/linux.S (revision 139a3d66)
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
26EXTERN _FrldrBootDrive:BYTE
27EXTERN _FrldrBootPartition:DWORD
28
29.code32
30
31Regs:
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 */
42PUBLIC _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 */
63set_part:
64    mov eax, dword ptr [esp + 20]
65    test eax, eax
66    jnz continue
67    mov eax, dword ptr ds:[_FrldrBootPartition]
68continue:
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
100reloc_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
116reloc_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
126after_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
139END
140