- Fix compile issues caused by previous patch.
[reactos.git] / reactos / ntoskrnl / ke / main.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/main.c
5 * PURPOSE: Initalizes the kernel
6 *
7 * PROGRAMMERS: Alex Ionescu (cleaned up code, moved Executiv stuff to ex/init.c)
8 * David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
20
21
22 ULONG NtMajorVersion = 5;
23 ULONG NtMinorVersion = 0;
24 ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(6, 0);
25 ULONG NtBuildNumber = KERNEL_VERSION_BUILD;
26 ULONG NtGlobalFlag = 0;
27 CHAR KeNumberProcessors;
28 KAFFINITY KeActiveProcessors = 1;
29 LOADER_PARAMETER_BLOCK KeLoaderBlock;
30 ULONG KeDcacheFlushCount = 0;
31 ULONG KeIcacheFlushCount = 0;
32 ULONG KiDmaIoCoherency = 0; /* RISC Architectures only */
33 ULONG InitSafeBootMode = 0; /* KB83764 */
34
35 LOADER_MODULE KeLoaderModules[64];
36 static CHAR KeLoaderModuleStrings[64][256];
37 static CHAR KeLoaderCommandLine[256];
38 ADDRESS_RANGE KeMemoryMap[64];
39 ULONG KeMemoryMapRangeCount;
40 ULONG_PTR FirstKrnlPhysAddr;
41 ULONG_PTR LastKrnlPhysAddr;
42 ULONG_PTR LastKernelAddress;
43
44 PVOID KeUserApcDispatcher = NULL;
45 PVOID KeUserCallbackDispatcher = NULL;
46 PVOID KeUserExceptionDispatcher = NULL;
47 PVOID KeRaiseUserExceptionDispatcher = NULL;
48
49 ULONG KeLargestCacheLine = 0x40; /* FIXME: Arch-specific */
50
51 /* We allocate 4 pages, but we only use 3. The 4th is to guarantee page alignment */
52 ULONG kernel_stack[4096];
53 ULONG double_trap_stack[4096];
54
55 /* These point to the aligned 3 pages */
56 ULONG init_stack;
57 ULONG init_stack_top;
58 ULONG trap_stack;
59 ULONG trap_stack_top;
60
61 /* Cached modules from the loader block */
62 PLOADER_MODULE CachedModules[MaximumCachedModuleType];
63
64 extern unsigned int _image_base__;
65 ULONG_PTR KERNEL_BASE = (ULONG_PTR)&_image_base__;
66
67 /* FUNCTIONS ****************************************************************/
68
69 /*
70 * @implemented
71 */
72 ULONG
73 STDCALL
74 KeGetRecommendedSharedDataAlignment(VOID)
75 {
76 return KeLargestCacheLine;
77 }
78
79 VOID
80 #ifdef __GNUC__
81 __attribute((noinline))
82 #endif
83 KiSystemStartup(BOOLEAN BootProcessor)
84 {
85 DPRINT("KiSystemStartup(%d)\n", BootProcessor);
86
87 /* Initialize the Application Processor */
88 if (!BootProcessor) KeApplicationProcessorInit();
89
90 /* Initialize the Processor with HAL */
91 HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
92
93 /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
94 if (BootProcessor) {
95
96 /* Initialize the Kernel Executive */
97 ExpInitializeExecutive();
98
99 /* Free Initial Memory */
100 MiFreeInitMemory();
101
102 /* Never returns */
103 #if 0
104 /* FIXME:
105 * The initial thread isn't a real ETHREAD object, we cannot call PspExitThread.
106 */
107 PspExitThread(STATUS_SUCCESS);
108 #else
109 while (1) {
110 LARGE_INTEGER Timeout;
111 Timeout.QuadPart = 0x7fffffffffffffffLL;
112 KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
113 }
114 #endif
115 } else {
116
117 /* Do application processor initialization */
118 KeApplicationProcessorInitDispatcher();
119
120 /* Lower IRQL and go to Idle Thread */
121 KeLowerIrql(PASSIVE_LEVEL);
122 PsIdleThreadMain(NULL);
123 }
124
125 /* Bug Check and loop forever if anything failed */
126 KEBUGCHECK(0);
127 for(;;);
128 }
129
130 /*
131 * FUNCTION: Called by the boot loader to start the kernel
132 * ARGUMENTS:
133 * LoaderBlock = Pointer to boot parameters initialized by the boot
134 * loader
135 * NOTE: The boot parameters are stored in low memory which will become
136 * invalid after the memory managment is initialized so we make a local copy.
137 */
138 VOID
139 INIT_FUNCTION
140 _main(ULONG MultiBootMagic,
141 PLOADER_PARAMETER_BLOCK _LoaderBlock)
142 {
143 ULONG i;
144 ULONG size;
145 ULONG HalBase;
146 ULONG DriverBase;
147 ULONG DriverSize;
148 PIMAGE_NT_HEADERS NtHeader;
149 PIMAGE_OPTIONAL_HEADER OptHead;
150 CHAR* s;
151
152 /* Set up the Stacks (Initial Kernel Stack and Double Trap Stack)*/
153 trap_stack = PAGE_ROUND_UP(&double_trap_stack);
154 trap_stack_top = trap_stack + 3 * PAGE_SIZE;
155 init_stack = PAGE_ROUND_UP(&kernel_stack);
156 init_stack_top = init_stack + 3 * PAGE_SIZE;
157
158 /* Copy the Loader Block Data locally since Low-Memory will be wiped */
159 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
160 memcpy(&KeLoaderModules[1],
161 (PVOID)KeLoaderBlock.ModsAddr,
162 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
163 KeLoaderBlock.ModsCount++;
164 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
165
166 /* Save the Base Address */
167 MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
168
169 /* Set the Command Line */
170 strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
171 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
172
173 /* Write the first Module (the Kernel) */
174 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
175 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
176 KeLoaderModules[0].ModStart = KERNEL_BASE;
177
178 /* Read PE Data */
179 NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
180 OptHead = &NtHeader->OptionalHeader;
181
182 /* Set Kernel Ending */
183 KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
184
185 /* Create a block for each module */
186 for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
187
188 /* Check if we have to copy the path or not */
189 if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0) {
190
191 strcpy(KeLoaderModuleStrings[i], s + 1);
192
193 } else {
194
195 strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
196 }
197
198 /* Substract the base Address in Physical Memory */
199 KeLoaderModules[i].ModStart -= 0x200000;
200
201 /* Add the Kernel Base Address in Virtual Memory */
202 KeLoaderModules[i].ModStart += KERNEL_BASE;
203
204 /* Substract the base Address in Physical Memory */
205 KeLoaderModules[i].ModEnd -= 0x200000;
206
207 /* Add the Kernel Base Address in Virtual Memory */
208 KeLoaderModules[i].ModEnd += KERNEL_BASE;
209
210 /* Select the proper String */
211 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
212 }
213
214 /* Choose last module address as the final kernel address */
215 LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
216
217 /* Low level architecture specific initialization */
218 KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
219
220 /* Select the HAL Base */
221 HalBase = KeLoaderModules[1].ModStart;
222
223 /* Choose Driver Base */
224 DriverBase = LastKernelAddress;
225 LdrHalBase = (ULONG_PTR)DriverBase;
226
227 /* Initialize Module Management */
228 LdrInitModuleManagement();
229
230 /* Load HAL.DLL with the PE Loader */
231 LdrSafePEProcessModule((PVOID)HalBase,
232 (PVOID)DriverBase,
233 (PVOID)KERNEL_BASE,
234 &DriverSize);
235
236 /* Increase the last kernel address with the size of HAL */
237 LastKernelAddress += PAGE_ROUND_UP(DriverSize);
238
239 /* Load the Kernel with the PE Loader */
240 LdrSafePEProcessModule((PVOID)KERNEL_BASE,
241 (PVOID)KERNEL_BASE,
242 (PVOID)DriverBase,
243 &DriverSize);
244
245 /* Now select the final beginning and ending Kernel Addresses */
246 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
247 LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
248
249 KeMemoryMapRangeCount = 0;
250 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) {
251
252 /* We have a memory map from the nice BIOS */
253 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
254 i = 0;
255
256 /* Map it until we run out of size */
257 while (i < KeLoaderBlock.MmapLength) {
258
259 /* Copy into the Kernel Memory Map */
260 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
261 (PVOID)(KeLoaderBlock.MmapAddr + i),
262 sizeof(ADDRESS_RANGE));
263
264 /* Increase Memory Map Count */
265 KeMemoryMapRangeCount++;
266
267 /* Increase Size */
268 i += size;
269 }
270
271 /* Save data */
272 KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
273 KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
274
275 } else {
276
277 /* Nothing from BIOS */
278 KeLoaderBlock.MmapLength = 0;
279 KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
280 }
281
282 /* Initialize the Debugger */
283 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
284
285 /* Initialize HAL */
286 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
287
288 /* Display separator + ReactOS version at start of the debug log */
289 DPRINT1("---------------------------------------------------------------\n");
290 DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
291
292 /* Do general System Startup */
293 KiSystemStartup(1);
294 }
295
296 /* EOF */