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))
21 ULONG NtMajorVersion
= 5;
22 ULONG NtMinorVersion
= 0;
23 ULONG NtOSCSDVersion
= BUILD_OSCSDVERSION(4, 0);
24 ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
25 ULONG NtGlobalFlag
= 0;
26 CHAR KeNumberProcessors
;
27 KAFFINITY KeActiveProcessors
= 1;
28 ROS_LOADER_PARAMETER_BLOCK KeLoaderBlock
;
29 ULONG KeDcacheFlushCount
= 0;
30 ULONG KeIcacheFlushCount
= 0;
31 ULONG KiDmaIoCoherency
= 0; /* RISC Architectures only */
32 ULONG InitSafeBootMode
= 0; /* KB83764 */
34 LOADER_MODULE KeLoaderModules
[64];
35 static CHAR KeLoaderModuleStrings
[64][256];
36 static CHAR KeLoaderCommandLine
[256];
37 ADDRESS_RANGE KeMemoryMap
[64];
38 ULONG KeMemoryMapRangeCount
;
39 ULONG_PTR FirstKrnlPhysAddr
;
40 ULONG_PTR LastKrnlPhysAddr
;
41 ULONG_PTR LastKernelAddress
;
43 PVOID KeUserApcDispatcher
= NULL
;
44 PVOID KeUserCallbackDispatcher
= NULL
;
45 PVOID KeUserExceptionDispatcher
= NULL
;
46 PVOID KeRaiseUserExceptionDispatcher
= NULL
;
48 ULONG KeLargestCacheLine
= 0x40; /* FIXME: Arch-specific */
50 /* the initial stacks are declared in main_asm.S */
51 extern ULONG kernel_stack
;
52 extern ULONG kernel_stack_top
;
53 extern ULONG kernel_trap_stack
;
54 extern ULONG kernel_trap_stack_top
;
56 /* These point to the aligned 3 pages */
57 ULONG init_stack
= (ULONG
)&kernel_stack
;
58 ULONG init_stack_top
= (ULONG
)&kernel_stack_top
;
59 ULONG trap_stack
= (ULONG
)&kernel_trap_stack
;
60 ULONG trap_stack_top
= (ULONG
)&kernel_trap_stack_top
;
62 /* Cached modules from the loader block */
63 PLOADER_MODULE CachedModules
[MaximumCachedModuleType
];
65 extern unsigned int _image_base__
;
66 ULONG_PTR KERNEL_BASE
= (ULONG_PTR
)&_image_base__
;
68 VOID INIT_FUNCTION
_main(ULONG MultiBootMagic
, PROS_LOADER_PARAMETER_BLOCK _LoaderBlock
);
70 #if defined (ALLOC_PRAGMA)
71 #pragma alloc_text(INIT, _main)
74 /* FUNCTIONS ****************************************************************/
81 KeGetRecommendedSharedDataAlignment(VOID
)
83 return KeLargestCacheLine
;
88 __attribute((noinline
))
90 KiSystemStartup(BOOLEAN BootProcessor
)
92 DPRINT("KiSystemStartup(%d)\n", BootProcessor
);
94 /* Initialize the Application Processor */
95 if (!BootProcessor
) KeApplicationProcessorInit();
97 /* Initialize the Processor with HAL */
98 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
100 /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
103 /* Initialize the Kernel Executive */
104 ExpInitializeExecutive();
106 /* Free Initial Memory */
112 * The initial thread isn't a real ETHREAD object, we cannot call PspExitThread.
114 PspExitThread(STATUS_SUCCESS
);
117 LARGE_INTEGER Timeout
;
118 Timeout
.QuadPart
= 0x7fffffffffffffffLL
;
119 KeDelayExecutionThread(KernelMode
, FALSE
, &Timeout
);
124 /* Do application processor initialization */
125 KeApplicationProcessorInitDispatcher();
127 /* Lower IRQL and go to Idle Thread */
128 KeLowerIrql(PASSIVE_LEVEL
);
129 PsIdleThreadMain(NULL
);
132 /* Bug Check and loop forever if anything failed */
138 * FUNCTION: Called by the boot loader to start the kernel
140 * LoaderBlock = Pointer to boot parameters initialized by the boot
142 * NOTE: The boot parameters are stored in low memory which will become
143 * invalid after the memory managment is initialized so we make a local copy.
147 _main(ULONG MultiBootMagic
,
148 PROS_LOADER_PARAMETER_BLOCK _LoaderBlock
)
155 PIMAGE_NT_HEADERS NtHeader
;
156 PIMAGE_OPTIONAL_HEADER OptHead
;
159 /* Copy the Loader Block Data locally since Low-Memory will be wiped */
160 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
161 memcpy(&KeLoaderModules
[1],
162 (PVOID
)KeLoaderBlock
.ModsAddr
,
163 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
164 KeLoaderBlock
.ModsCount
++;
165 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
167 /* Save the Base Address */
168 MmSystemRangeStart
= (PVOID
)KeLoaderBlock
.KernelBase
;
170 /* Set the Command Line */
171 strcpy(KeLoaderCommandLine
, (PCHAR
)_LoaderBlock
->CommandLine
);
172 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
174 /* Write the first Module (the Kernel) */
175 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
176 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
177 KeLoaderModules
[0].ModStart
= KERNEL_BASE
;
180 NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
181 OptHead
= &NtHeader
->OptionalHeader
;
183 /* Set Kernel Ending */
184 KeLoaderModules
[0].ModEnd
= KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
186 /* Create a block for each module */
187 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++) {
189 /* Check if we have to copy the path or not */
190 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0) {
192 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
196 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
199 /* Substract the base Address in Physical Memory */
200 KeLoaderModules
[i
].ModStart
-= 0x200000;
202 /* Add the Kernel Base Address in Virtual Memory */
203 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
205 /* Substract the base Address in Physical Memory */
206 KeLoaderModules
[i
].ModEnd
-= 0x200000;
208 /* Add the Kernel Base Address in Virtual Memory */
209 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
211 /* Select the proper String */
212 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
215 /* Choose last module address as the final kernel address */
216 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
218 /* Low level architecture specific initialization */
219 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
221 /* Select the HAL Base */
222 HalBase
= KeLoaderModules
[1].ModStart
;
224 /* Choose Driver Base */
225 DriverBase
= LastKernelAddress
;
226 LdrHalBase
= (ULONG_PTR
)DriverBase
;
228 /* Initialize Module Management */
229 LdrInitModuleManagement();
231 /* Load HAL.DLL with the PE Loader */
232 LdrSafePEProcessModule((PVOID
)HalBase
,
237 /* Increase the last kernel address with the size of HAL */
238 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
240 /* Load the Kernel with the PE Loader */
241 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
,
246 /* Now select the final beginning and ending Kernel Addresses */
247 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
248 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
250 KeMemoryMapRangeCount
= 0;
251 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
) {
253 /* We have a memory map from the nice BIOS */
254 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
257 /* Map it until we run out of size */
258 while (i
< KeLoaderBlock
.MmapLength
) {
260 /* Copy into the Kernel Memory Map */
261 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
262 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
263 sizeof(ADDRESS_RANGE
));
265 /* Increase Memory Map Count */
266 KeMemoryMapRangeCount
++;
273 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
274 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
278 /* Nothing from BIOS */
279 KeLoaderBlock
.MmapLength
= 0;
280 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
283 /* Initialize the Debugger */
284 KdInitSystem (0, &KeLoaderBlock
);
287 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
289 /* Do general System Startup */