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(4, 0);
25 ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
26 ULONG NtGlobalFlag
= 0;
27 CHAR KeNumberProcessors
;
28 KAFFINITY KeActiveProcessors
= 1;
29 LOADER_PARAMETER_BLOCK KeLoaderBlock
;
30 ULONG KeDcacheFlushCount
= 0;
31 ULONG KeIcacheFlushCount
= 0;
32 ULONG KiDmaIoCoherency
= 0; /* RISC Architectures only */
33 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 VOID INIT_FUNCTION
_main(ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
);
69 #if defined (ALLOC_PRAGMA)
70 #pragma alloc_text(INIT, _main)
73 /* FUNCTIONS ****************************************************************/
80 KeGetRecommendedSharedDataAlignment(VOID
)
82 return KeLargestCacheLine
;
87 __attribute((noinline
))
89 KiSystemStartup(BOOLEAN BootProcessor
)
91 DPRINT("KiSystemStartup(%d)\n", BootProcessor
);
93 /* Initialize the Application Processor */
94 if (!BootProcessor
) KeApplicationProcessorInit();
96 /* Initialize the Processor with HAL */
97 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
99 /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
102 /* Initialize the Kernel Executive */
103 ExpInitializeExecutive();
105 /* Free Initial Memory */
111 * The initial thread isn't a real ETHREAD object, we cannot call PspExitThread.
113 PspExitThread(STATUS_SUCCESS
);
116 LARGE_INTEGER Timeout
;
117 Timeout
.QuadPart
= 0x7fffffffffffffffLL
;
118 KeDelayExecutionThread(KernelMode
, FALSE
, &Timeout
);
123 /* Do application processor initialization */
124 KeApplicationProcessorInitDispatcher();
126 /* Lower IRQL and go to Idle Thread */
127 KeLowerIrql(PASSIVE_LEVEL
);
128 PsIdleThreadMain(NULL
);
131 /* Bug Check and loop forever if anything failed */
137 * FUNCTION: Called by the boot loader to start the kernel
139 * LoaderBlock = Pointer to boot parameters initialized by the boot
141 * NOTE: The boot parameters are stored in low memory which will become
142 * invalid after the memory managment is initialized so we make a local copy.
146 _main(ULONG MultiBootMagic
,
147 PLOADER_PARAMETER_BLOCK _LoaderBlock
)
154 PIMAGE_NT_HEADERS NtHeader
;
155 PIMAGE_OPTIONAL_HEADER OptHead
;
158 /* Set up the Stacks (Initial Kernel Stack and Double Trap Stack)*/
159 trap_stack
= PAGE_ROUND_UP(&double_trap_stack
);
160 trap_stack_top
= trap_stack
+ 3 * PAGE_SIZE
;
161 init_stack
= PAGE_ROUND_UP(&kernel_stack
);
162 init_stack_top
= init_stack
+ 3 * PAGE_SIZE
;
164 /* Copy the Loader Block Data locally since Low-Memory will be wiped */
165 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
166 memcpy(&KeLoaderModules
[1],
167 (PVOID
)KeLoaderBlock
.ModsAddr
,
168 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
169 KeLoaderBlock
.ModsCount
++;
170 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
172 /* Save the Base Address */
173 MmSystemRangeStart
= (PVOID
)KeLoaderBlock
.KernelBase
;
175 /* Set the Command Line */
176 strcpy(KeLoaderCommandLine
, (PCHAR
)_LoaderBlock
->CommandLine
);
177 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
179 /* Write the first Module (the Kernel) */
180 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
181 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
182 KeLoaderModules
[0].ModStart
= KERNEL_BASE
;
185 NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
186 OptHead
= &NtHeader
->OptionalHeader
;
188 /* Set Kernel Ending */
189 KeLoaderModules
[0].ModEnd
= KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
191 /* Create a block for each module */
192 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++) {
194 /* Check if we have to copy the path or not */
195 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0) {
197 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
201 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
204 /* Substract the base Address in Physical Memory */
205 KeLoaderModules
[i
].ModStart
-= 0x200000;
207 /* Add the Kernel Base Address in Virtual Memory */
208 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
210 /* Substract the base Address in Physical Memory */
211 KeLoaderModules
[i
].ModEnd
-= 0x200000;
213 /* Add the Kernel Base Address in Virtual Memory */
214 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
216 /* Select the proper String */
217 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
220 /* Choose last module address as the final kernel address */
221 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
223 /* Low level architecture specific initialization */
224 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
226 /* Select the HAL Base */
227 HalBase
= KeLoaderModules
[1].ModStart
;
229 /* Choose Driver Base */
230 DriverBase
= LastKernelAddress
;
231 LdrHalBase
= (ULONG_PTR
)DriverBase
;
233 /* Initialize Module Management */
234 LdrInitModuleManagement();
236 /* Load HAL.DLL with the PE Loader */
237 LdrSafePEProcessModule((PVOID
)HalBase
,
242 /* Increase the last kernel address with the size of HAL */
243 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
245 /* Load the Kernel with the PE Loader */
246 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
,
251 /* Now select the final beginning and ending Kernel Addresses */
252 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
253 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
255 KeMemoryMapRangeCount
= 0;
256 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
) {
258 /* We have a memory map from the nice BIOS */
259 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
262 /* Map it until we run out of size */
263 while (i
< KeLoaderBlock
.MmapLength
) {
265 /* Copy into the Kernel Memory Map */
266 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
267 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
268 sizeof(ADDRESS_RANGE
));
270 /* Increase Memory Map Count */
271 KeMemoryMapRangeCount
++;
278 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
279 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
283 /* Nothing from BIOS */
284 KeLoaderBlock
.MmapLength
= 0;
285 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
288 /* Initialize the Debugger */
289 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
292 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
294 /* Display separator + ReactOS version at start of the debug log */
295 DPRINT1("---------------------------------------------------------------\n");
296 DPRINT1("ReactOS "KERNEL_VERSION_STR
" (Build "KERNEL_VERSION_BUILD_STR
")\n");
298 /* Do general System Startup */