Fix a couple of problems with FreeLDR portability.
[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 #undef DbgPrint
26
27 /* Page Directory and Tables for non-PAE Systems */
28 extern PAGE_DIRECTORY_X86 startup_pagedirectory;
29 extern PAGE_DIRECTORY_X86 lowmem_pagetable;
30 extern PAGE_DIRECTORY_X86 kernel_pagetable;
31 extern PAGE_DIRECTORY_X86 hyperspace_pagetable;
32 extern PAGE_DIRECTORY_X86 apic_pagetable;
33 extern PAGE_DIRECTORY_X86 kpcr_pagetable;
34 extern PAGE_DIRECTORY_X86 kuser_pagetable;
35 extern ULONG_PTR KernelBase;
36 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint;
37 /* FUNCTIONS *****************************************************************/
38
39 /*++
40 * FrLdrStartup
41 * INTERNAL
42 *
43 * Prepares the system for loading the Kernel.
44 *
45 * Params:
46 * Magic - Multiboot Magic
47 *
48 * Returns:
49 * None.
50 *
51 * Remarks:
52 * None.
53 *
54 *--*/
55 VOID
56 NTAPI
57 FrLdrStartup(ULONG Magic)
58 {
59 /* Disable Interrupts */
60 _disable();
61
62 /* Re-initalize EFLAGS */
63 Ke386EraseFlags();
64
65 /* Initialize the page directory */
66 FrLdrSetupPageDirectory();
67
68 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
69 FrLdrSetupPae(Magic);
70 }
71
72 /*++
73 * FrLdrSetupPae
74 * INTERNAL
75 *
76 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
77 * the system is UP.
78 *
79 * Params:
80 * Magic - Multiboot Magic
81 *
82 * Returns:
83 * None.
84 *
85 * Remarks:
86 * None.
87 *
88 *--*/
89 VOID
90 FASTCALL
91 FrLdrSetupPae(ULONG Magic)
92 {
93 ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory;
94
95 /* Set the PDBR */
96 __writecr3(PageDirectoryBaseAddress);
97
98 /* Enable Paging and Write Protect*/
99 __writecr0(__readcr0() | X86_CR0_PG | X86_CR0_WP);
100
101 /* Jump to Kernel */
102 (*KernelEntryPoint)(Magic, &LoaderBlock);
103 }
104
105 /*++
106 * FrLdrSetupPageDirectory
107 * INTERNAL
108 *
109 * Sets up the ReactOS Startup Page Directory.
110 *
111 * Params:
112 * None.
113 *
114 * Returns:
115 * None.
116 *
117 * Remarks:
118 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
119 * As such, please note that PageFrameNumber == PageEntryNumber.
120 *
121 *--*/
122 VOID
123 FASTCALL
124 FrLdrSetupPageDirectory(VOID)
125 {
126 PPAGE_DIRECTORY_X86 PageDir;
127 ULONG KernelPageTableIndex;
128 ULONG i;
129
130 /* Get the Kernel Table Index */
131 KernelPageTableIndex = KernelBase >> PDE_SHIFT;
132
133 /* Get the Startup Page Directory */
134 PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
135
136 /* Set up the Low Memory PDE */
137 PageDir->Pde[LowMemPageTableIndex].Valid = 1;
138 PageDir->Pde[LowMemPageTableIndex].Write = 1;
139 PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
140
141 /* Set up the Kernel PDEs */
142 PageDir->Pde[KernelPageTableIndex].Valid = 1;
143 PageDir->Pde[KernelPageTableIndex].Write = 1;
144 PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
145 PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
146 PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
147 PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
148
149 /* Set up the Startup PDE */
150 PageDir->Pde[StartupPageTableIndex].Valid = 1;
151 PageDir->Pde[StartupPageTableIndex].Write = 1;
152 PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
153
154 /* Set up the Hyperspace PDE */
155 PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
156 PageDir->Pde[HyperspacePageTableIndex].Write = 1;
157 PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);
158
159 /* Set up the HAL PDE */
160 PageDir->Pde[HalPageTableIndex].Valid = 1;
161 PageDir->Pde[HalPageTableIndex].Write = 1;
162 PageDir->Pde[HalPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
163
164 /* Set up Low Memory PTEs */
165 PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
166 for (i=0; i<1024; i++)
167 {
168 PageDir->Pde[i].Valid = 1;
169 PageDir->Pde[i].Write = 1;
170 PageDir->Pde[i].Owner = 1;
171 PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
172 }
173
174 /* Set up Kernel PTEs */
175 PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
176 for (i=0; i<1536; i++)
177 {
178 PageDir->Pde[i].Valid = 1;
179 PageDir->Pde[i].Write = 1;
180 PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
181 }
182
183 /* Setup APIC Base */
184 PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
185 PageDir->Pde[0].Valid = 1;
186 PageDir->Pde[0].Write = 1;
187 PageDir->Pde[0].CacheDisable = 1;
188 PageDir->Pde[0].WriteThrough = 1;
189 PageDir->Pde[0].PageFrameNumber = PaToPfn(HAL_BASE);
190 PageDir->Pde[0x200].Valid = 1;
191 PageDir->Pde[0x200].Write = 1;
192 PageDir->Pde[0x200].CacheDisable = 1;
193 PageDir->Pde[0x200].WriteThrough = 1;
194 PageDir->Pde[0x200].PageFrameNumber = PaToPfn(HAL_BASE + KERNEL_BASE_PHYS);
195
196 /* Setup KUSER_SHARED_DATA Base */
197 PageDir->Pde[0x1F0].Valid = 1;
198 PageDir->Pde[0x1F0].Write = 1;
199 PageDir->Pde[0x1F0].PageFrameNumber = 2;
200
201 /* Setup KPCR Base*/
202 PageDir->Pde[0x1FF].Valid = 1;
203 PageDir->Pde[0x1FF].Write = 1;
204 PageDir->Pde[0x1FF].PageFrameNumber = 1;
205 }
206