4e29731c74fa5fbf059e90ff368f6e6db06a4d8a
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / loader.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 #define _NTSYSTEM_
21 #include <freeldr.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 /* Page Directory and Tables for non-PAE Systems */
27 extern PAGE_DIRECTORY_X86 startup_pagedirectory;
28 extern PAGE_DIRECTORY_X86 lowmem_pagetable;
29 extern PAGE_DIRECTORY_X86 kernel_pagetable;
30 extern PAGE_DIRECTORY_X86 apic_pagetable;
31 extern PAGE_DIRECTORY_X86 kpcr_pagetable;
32 extern PAGE_DIRECTORY_X86 kuser_pagetable;
33 extern ULONG_PTR KernelBase;
34 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint;
35 /* FUNCTIONS *****************************************************************/
36
37 /*++
38 * FrLdrStartup
39 * INTERNAL
40 *
41 * Prepares the system for loading the Kernel.
42 *
43 * Params:
44 * Magic - Multiboot Magic
45 *
46 * Returns:
47 * None.
48 *
49 * Remarks:
50 * None.
51 *
52 *--*/
53 VOID
54 NTAPI
55 FrLdrStartup(ULONG Magic)
56 {
57 /* Disable Interrupts */
58 _disable();
59
60 /* Re-initalize EFLAGS */
61 Ke386EraseFlags();
62
63 /* Initialize the page directory */
64 FrLdrSetupPageDirectory();
65
66 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
67 FrLdrSetupPae(Magic);
68 }
69
70 /*++
71 * FrLdrSetupPae
72 * INTERNAL
73 *
74 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
75 * the system is UP.
76 *
77 * Params:
78 * Magic - Multiboot Magic
79 *
80 * Returns:
81 * None.
82 *
83 * Remarks:
84 * None.
85 *
86 *--*/
87 VOID
88 FASTCALL
89 FrLdrSetupPae(ULONG Magic)
90 {
91 ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory;
92
93 /* Set the PDBR */
94 __writecr3(PageDirectoryBaseAddress);
95
96 /* Enable Paging and Write Protect*/
97 __writecr0(__readcr0() | CR0_PG | CR0_WP);
98
99 /* Jump to Kernel */
100 (*KernelEntryPoint)(Magic, &LoaderBlock);
101 }
102
103 /*++
104 * FrLdrSetupPageDirectory
105 * INTERNAL
106 *
107 * Sets up the ReactOS Startup Page Directory.
108 *
109 * Params:
110 * None.
111 *
112 * Returns:
113 * None.
114 *
115 * Remarks:
116 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
117 * As such, please note that PageFrameNumber == PageEntryNumber.
118 *
119 *--*/
120 VOID
121 FASTCALL
122 FrLdrSetupPageDirectory(VOID)
123 {
124 PPAGE_DIRECTORY_X86 PageDir;
125 ULONG KernelPageTableIndex;
126 ULONG i;
127
128 /* Get the Kernel Table Index */
129 KernelPageTableIndex = KernelBase >> PDE_SHIFT;
130
131 /* Get the Startup Page Directory */
132 PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
133
134 /* Set up the Low Memory PDE */
135 PageDir->Pde[LowMemPageTableIndex].Valid = 1;
136 PageDir->Pde[LowMemPageTableIndex].Write = 1;
137 PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
138
139 /* Set up the Kernel PDEs */
140 PageDir->Pde[KernelPageTableIndex].Valid = 1;
141 PageDir->Pde[KernelPageTableIndex].Write = 1;
142 PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
143 PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
144 PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
145 PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
146
147 /* Set up the Startup PDE */
148 PageDir->Pde[StartupPageTableIndex].Valid = 1;
149 PageDir->Pde[StartupPageTableIndex].Write = 1;
150 PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
151
152 /* Set up the HAL PDE */
153 PageDir->Pde[HalPageTableIndex].Valid = 1;
154 PageDir->Pde[HalPageTableIndex].Write = 1;
155 PageDir->Pde[HalPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
156
157 /* Set up Low Memory PTEs */
158 PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
159 for (i=0; i<1024; i++)
160 {
161 PageDir->Pde[i].Valid = 1;
162 PageDir->Pde[i].Write = 1;
163 PageDir->Pde[i].Owner = 1;
164 PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
165 }
166
167 /* Set up Kernel PTEs */
168 PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
169 for (i=0; i<1536; i++)
170 {
171 PageDir->Pde[i].Valid = 1;
172 PageDir->Pde[i].Write = 1;
173 PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
174 }
175
176 /* Setup APIC Base */
177 PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
178 PageDir->Pde[0].Valid = 1;
179 PageDir->Pde[0].Write = 1;
180 PageDir->Pde[0].CacheDisable = 1;
181 PageDir->Pde[0].WriteThrough = 1;
182 PageDir->Pde[0].PageFrameNumber = PaToPfn(HAL_BASE);
183 PageDir->Pde[0x200].Valid = 1;
184 PageDir->Pde[0x200].Write = 1;
185 PageDir->Pde[0x200].CacheDisable = 1;
186 PageDir->Pde[0x200].WriteThrough = 1;
187 PageDir->Pde[0x200].PageFrameNumber = PaToPfn(HAL_BASE + KERNEL_BASE_PHYS);
188
189 /* Setup KUSER_SHARED_DATA Base */
190 PageDir->Pde[0x1F0].Valid = 1;
191 PageDir->Pde[0x1F0].Write = 1;
192 PageDir->Pde[0x1F0].PageFrameNumber = 2;
193
194 /* Setup KPCR Base*/
195 PageDir->Pde[0x1FF].Valid = 1;
196 PageDir->Pde[0x1FF].Write = 1;
197 PageDir->Pde[0x1FF].PageFrameNumber = 1;
198
199 /* Zero shared data */
200 RtlZeroMemory((PVOID)(2 << MM_PAGE_SHIFT), PAGE_SIZE);
201 }
202