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