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