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