2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/main.c
5 * PURPOSE: Initalizes the kernel
7 * PROGRAMMERS: Alex Ionescu (cleaned up code, moved Executiv stuff to ex/init.c)
8 * David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *******************************************************************/
19 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
22 ULONG NtMajorVersion
= 5;
23 ULONG NtMinorVersion
= 0;
24 ULONG NtOSCSDVersion
= BUILD_OSCSDVERSION(6, 0);
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 */
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 */
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
;
58 ULONG KeLargestCacheLine
= 0x40; /* FIXME: Arch-specific */
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];
64 /* These point to the aligned 3 pages */
70 /* Cached modules from the loader block */
71 PLOADER_MODULE CachedModules
[MaximumCachedModuleType
];
73 /* FUNCTIONS ****************************************************************/
80 KeGetRecommendedSharedDataAlignment(VOID
)
82 return KeLargestCacheLine
;
86 __attribute((noinline
))
87 KiSystemStartup(BOOLEAN BootProcessor
)
89 DPRINT("KiSystemStartup(%d)\n", BootProcessor
);
91 /* Initialize the Application Processor */
92 if (!BootProcessor
) KeApplicationProcessorInit();
94 /* Initialize the Processor with HAL */
95 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
97 /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
100 /* Initialize the Kernel Executive */
101 ExpInitializeExecutive();
103 /* Free Initial Memory */
107 PspExitThread(STATUS_SUCCESS
);
111 /* Do application processor initialization */
112 PsApplicationProcessorInit();
114 /* Lower IRQL and go to Idle Thread */
115 KeLowerIrql(PASSIVE_LEVEL
);
116 PsIdleThreadMain(NULL
);
119 /* Bug Check and loop forever if anything failed */
125 * FUNCTION: Called by the boot loader to start the kernel
127 * LoaderBlock = Pointer to boot parameters initialized by the boot
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.
134 _main(ULONG MultiBootMagic
,
135 PLOADER_PARAMETER_BLOCK _LoaderBlock
)
142 PIMAGE_NT_HEADERS NtHeader
;
143 PIMAGE_OPTIONAL_HEADER OptHead
;
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
;
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
;
160 /* Save the Base Address */
161 MmSystemRangeStart
= (PVOID
)KeLoaderBlock
.KernelBase
;
163 /* Set the Command Line */
164 strcpy(KeLoaderCommandLine
, (PCHAR
)_LoaderBlock
->CommandLine
);
165 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
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
;
173 NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
174 OptHead
= &NtHeader
->OptionalHeader
;
176 /* Set Kernel Ending */
177 KeLoaderModules
[0].ModEnd
= KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
179 /* Create a block for each module */
180 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++) {
182 /* Check if we have to copy the path or not */
183 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0) {
185 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
189 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
192 /* Substract the base Address in Physical Memory */
193 KeLoaderModules
[i
].ModStart
-= 0x200000;
195 /* Add the Kernel Base Address in Virtual Memory */
196 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
198 /* Substract the base Address in Physical Memory */
199 KeLoaderModules
[i
].ModEnd
-= 0x200000;
201 /* Add the Kernel Base Address in Virtual Memory */
202 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
204 /* Select the proper String */
205 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
208 /* Choose last module address as the final kernel address */
209 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
211 /* Low level architecture specific initialization */
212 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
214 /* Select the HAL Base */
215 HalBase
= KeLoaderModules
[1].ModStart
;
217 /* Choose Driver Base */
218 DriverBase
= LastKernelAddress
;
219 LdrHalBase
= (ULONG_PTR
)DriverBase
;
221 /* Initialize Module Management */
222 LdrInitModuleManagement();
224 /* Load HAL.DLL with the PE Loader */
225 LdrSafePEProcessModule((PVOID
)HalBase
,
230 /* Increase the last kernel address with the size of HAL */
231 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
233 /* Load the Kernel with the PE Loader */
234 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
,
239 /* Now select the final beginning and ending Kernel Addresses */
240 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
241 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
243 KeMemoryMapRangeCount
= 0;
244 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
) {
246 /* We have a memory map from the nice BIOS */
247 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
250 /* Map it until we run out of size */
251 while (i
< KeLoaderBlock
.MmapLength
) {
253 /* Copy into the Kernel Memory Map */
254 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
255 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
256 sizeof(ADDRESS_RANGE
));
258 /* Increase Memory Map Count */
259 KeMemoryMapRangeCount
++;
266 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
267 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
271 /* Nothing from BIOS */
272 KeLoaderBlock
.MmapLength
= 0;
273 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
276 /* Initialize the Debugger */
277 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
280 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
282 /* Do general System Startup */