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