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);
25 EXPORTED ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
26 EXPORTED ULONG NtGlobalFlag
= 0;
27 EXPORTED CHAR KeNumberProcessors
;
28 EXPORTED KAFFINITY KeActiveProcessors
;
29 EXPORTED LOADER_PARAMETER_BLOCK KeLoaderBlock
;
30 EXPORTED ULONG KeDcacheFlushCount
= 0;
31 EXPORTED ULONG KeIcacheFlushCount
= 0;
32 EXPORTED ULONG KiDmaIoCoherency
= 0; /* RISC Architectures only */
33 EXPORTED ULONG InitSafeBootMode
= 0; /* KB83764 */
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
;
44 PVOID KeUserApcDispatcher
= NULL
;
45 PVOID KeUserCallbackDispatcher
= NULL
;
46 PVOID KeUserExceptionDispatcher
= NULL
;
47 PVOID KeRaiseUserExceptionDispatcher
= NULL
;
49 ULONG KeLargestCacheLine
= 0x40; /* FIXME: Arch-specific */
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];
55 /* These point to the aligned 3 pages */
61 /* Cached modules from the loader block */
62 PLOADER_MODULE CachedModules
[MaximumCachedModuleType
];
64 extern unsigned int _image_base__
;
65 ULONG_PTR KERNEL_BASE
= (ULONG_PTR
)&_image_base__
;
67 /* FUNCTIONS ****************************************************************/
74 KeGetRecommendedSharedDataAlignment(VOID
)
76 return KeLargestCacheLine
;
81 __attribute((noinline
))
83 KiSystemStartup(BOOLEAN BootProcessor
)
85 DPRINT("KiSystemStartup(%d)\n", BootProcessor
);
87 /* Initialize the Application Processor */
88 if (!BootProcessor
) KeApplicationProcessorInit();
90 /* Initialize the Processor with HAL */
91 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
93 /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
96 /* Initialize the Kernel Executive */
97 ExpInitializeExecutive();
99 /* Free Initial Memory */
105 * The initial thread isn't a real ETHREAD object, we cannot call PspExitThread.
107 PspExitThread(STATUS_SUCCESS
);
110 LARGE_INTEGER Timeout
;
111 Timeout
.QuadPart
= 0x7fffffffffffffffLL
;
112 KeDelayExecutionThread(KernelMode
, FALSE
, &Timeout
);
117 /* Do application processor initialization */
118 KeApplicationProcessorInitDispatcher();
120 /* Lower IRQL and go to Idle Thread */
121 KeLowerIrql(PASSIVE_LEVEL
);
122 PsIdleThreadMain(NULL
);
125 /* Bug Check and loop forever if anything failed */
131 * FUNCTION: Called by the boot loader to start the kernel
133 * LoaderBlock = Pointer to boot parameters initialized by the boot
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.
140 _main(ULONG MultiBootMagic
,
141 PLOADER_PARAMETER_BLOCK _LoaderBlock
)
148 PIMAGE_NT_HEADERS NtHeader
;
149 PIMAGE_OPTIONAL_HEADER OptHead
;
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
;
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
;
166 /* Save the Base Address */
167 MmSystemRangeStart
= (PVOID
)KeLoaderBlock
.KernelBase
;
169 /* Set the Command Line */
170 strcpy(KeLoaderCommandLine
, (PCHAR
)_LoaderBlock
->CommandLine
);
171 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
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
;
179 NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
180 OptHead
= &NtHeader
->OptionalHeader
;
182 /* Set Kernel Ending */
183 KeLoaderModules
[0].ModEnd
= KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
185 /* Create a block for each module */
186 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++) {
188 /* Check if we have to copy the path or not */
189 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0) {
191 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
195 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
198 /* Substract the base Address in Physical Memory */
199 KeLoaderModules
[i
].ModStart
-= 0x200000;
201 /* Add the Kernel Base Address in Virtual Memory */
202 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
204 /* Substract the base Address in Physical Memory */
205 KeLoaderModules
[i
].ModEnd
-= 0x200000;
207 /* Add the Kernel Base Address in Virtual Memory */
208 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
210 /* Select the proper String */
211 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
214 /* Choose last module address as the final kernel address */
215 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
217 /* Low level architecture specific initialization */
218 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
220 /* Select the HAL Base */
221 HalBase
= KeLoaderModules
[1].ModStart
;
223 /* Choose Driver Base */
224 DriverBase
= LastKernelAddress
;
225 LdrHalBase
= (ULONG_PTR
)DriverBase
;
227 /* Initialize Module Management */
228 LdrInitModuleManagement();
230 /* Load HAL.DLL with the PE Loader */
231 LdrSafePEProcessModule((PVOID
)HalBase
,
236 /* Increase the last kernel address with the size of HAL */
237 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
239 /* Load the Kernel with the PE Loader */
240 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
,
245 /* Now select the final beginning and ending Kernel Addresses */
246 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
247 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
249 KeMemoryMapRangeCount
= 0;
250 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
) {
252 /* We have a memory map from the nice BIOS */
253 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
256 /* Map it until we run out of size */
257 while (i
< KeLoaderBlock
.MmapLength
) {
259 /* Copy into the Kernel Memory Map */
260 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
261 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
262 sizeof(ADDRESS_RANGE
));
264 /* Increase Memory Map Count */
265 KeMemoryMapRangeCount
++;
272 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
273 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
277 /* Nothing from BIOS */
278 KeLoaderBlock
.MmapLength
= 0;
279 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
282 /* Initialize the Debugger */
283 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
286 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
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");
292 /* Do general System Startup */