3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/main.c
6 * PURPOSE: Initalizes the kernel
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
14 #include "../dbg/kdb.h"
15 #include <ntos/bootvid.h>
16 #include <napi/core.h>
19 #include <internal/ntosdbg.h>
21 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
30 #include <internal/debug.h>
32 /* GLOBALS *******************************************************************/
34 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
35 ULONG NtMajorVersion
= 4;
36 ULONG NtMinorVersion
= 0;
37 ULONG NtOSCSDVersion
= BUILD_OSCSDVERSION(6, 0);
39 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
40 ULONG EXPORTED NtGlobalFlag
= 0;
41 CHAR EXPORTED KeNumberProcessors
;
42 KAFFINITY EXPORTED KeActiveProcessors
;
43 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
44 ULONG EXPORTED KeDcacheFlushCount
= 0;
45 ULONG EXPORTED KeIcacheFlushCount
= 0;
46 ULONG EXPORTED KiDmaIoCoherency
= 0; /* RISC Architectures only */
47 ULONG EXPORTED InitSafeBootMode
= 0; /* KB83764 */
49 /* Microsoft-style declarations */
50 EXPORTED ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
51 EXPORTED ULONG NtGlobalFlag
= 0;
52 EXPORTED CHAR KeNumberProcessors
;
53 EXPORTED KAFFINITY KeActiveProcessors
;
54 EXPORTED LOADER_PARAMETER_BLOCK KeLoaderBlock
;
55 EXPORTED ULONG KeDcacheFlushCount
= 0;
56 EXPORTED ULONG KeIcacheFlushCount
= 0;
57 EXPORTED ULONG KiDmaIoCoherency
= 0; /* RISC Architectures only */
58 EXPORTED ULONG InitSafeBootMode
= 0; /* KB83764 */
61 static LOADER_MODULE KeLoaderModules
[64];
62 static CHAR KeLoaderModuleStrings
[64][256];
63 static CHAR KeLoaderCommandLine
[256];
64 static ADDRESS_RANGE KeMemoryMap
[64];
65 static ULONG KeMemoryMapRangeCount
;
66 static ULONG_PTR FirstKrnlPhysAddr
;
67 static ULONG_PTR LastKrnlPhysAddr
;
68 static ULONG_PTR LastKernelAddress
;
69 volatile BOOLEAN Initialized
= FALSE
;
70 extern ULONG MmCoreDumpType
;
71 extern CHAR KiTimerSystemAuditing
;
73 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
75 /* We allocate 4 pages, but we only use 3. The 4th is to guarantee page alignment */
76 ULONG kernel_stack
[4096];
77 ULONG double_trap_stack
[4096];
79 /* These point to the aligned 3 pages */
85 /* FUNCTIONS ****************************************************************/
87 static VOID INIT_FUNCTION
88 InitSystemSharedUserPage (PCSZ ParameterLine
)
90 UNICODE_STRING ArcDeviceName
;
91 UNICODE_STRING ArcName
;
92 UNICODE_STRING BootPath
;
93 UNICODE_STRING DriveDeviceName
;
94 UNICODE_STRING DriveName
;
95 WCHAR DriveNameBuffer
[20];
101 OBJECT_ATTRIBUTES ObjectAttributes
;
104 BOOLEAN BootDriveFound
;
108 * The shared user page has been zeroed-out right after creation.
109 * There is NO need to do this again.
112 Ki386SetProcessorFeatures();
114 SharedUserData
->NtProductType
= NtProductWinNt
;
115 SharedUserData
->ProductTypeIsValid
= TRUE
;
116 SharedUserData
->NtMajorVersion
= 5;
117 SharedUserData
->NtMinorVersion
= 0;
119 BootDriveFound
= FALSE
;
122 * Retrieve the current dos system path
123 * (e.g.: C:\reactos) from the given arc path
124 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
125 * Format: "<arc_name>\<path> [options...]"
128 /* create local parameter line copy */
129 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
130 strcpy (ParamBuffer
, (char *)ParameterLine
);
131 DPRINT("%s\n", ParamBuffer
);
133 /* cut options off */
134 p
= strchr (ParamBuffer
, ' ');
139 DPRINT("%s\n", ParamBuffer
);
142 p
= strchr (ParamBuffer
, '\\');
145 DPRINT("Boot path: %s\n", p
);
146 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
151 DPRINT("Boot path: %s\n", "\\");
152 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
154 DPRINT("Arc name: %s\n", ParamBuffer
);
156 /* Only arc name left - build full arc name */
157 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
158 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
159 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
160 DPRINT("Arc name: %wZ\n", &ArcName
);
162 /* free ParamBuffer */
163 ExFreePool (ParamBuffer
);
165 /* allocate arc device name string */
166 ArcDeviceName
.Length
= 0;
167 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
168 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
170 InitializeObjectAttributes (&ObjectAttributes
,
176 Status
= NtOpenSymbolicLinkObject (&Handle
,
177 SYMBOLIC_LINK_ALL_ACCESS
,
179 RtlFreeUnicodeString (&ArcName
);
180 if (!NT_SUCCESS(Status
))
182 RtlFreeUnicodeString (&BootPath
);
183 RtlFreeUnicodeString (&ArcDeviceName
);
184 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
190 Status
= NtQuerySymbolicLinkObject (Handle
,
194 if (!NT_SUCCESS(Status
))
196 RtlFreeUnicodeString (&BootPath
);
197 RtlFreeUnicodeString (&ArcDeviceName
);
198 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
203 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
206 /* allocate device name string */
207 DriveDeviceName
.Length
= 0;
208 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
209 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
211 for (i
= 0; i
< 26; i
++)
213 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
214 RtlInitUnicodeString (&DriveName
,
217 InitializeObjectAttributes (&ObjectAttributes
,
223 Status
= NtOpenSymbolicLinkObject (&Handle
,
224 SYMBOLIC_LINK_ALL_ACCESS
,
226 if (!NT_SUCCESS(Status
))
228 DPRINT("Failed to open link %wZ\n",
233 Status
= NtQuerySymbolicLinkObject (Handle
,
236 if (!NT_SUCCESS(Status
))
238 DPRINT("Failed query open link %wZ\n",
242 DPRINT("Opened link: %wZ ==> %wZ\n",
243 &DriveName
, &DriveDeviceName
);
245 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
247 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
248 swprintf(SharedUserData
->NtSystemRoot
,
249 L
"%C:%wZ", 'A' + i
, &BootPath
);
251 BootDriveFound
= TRUE
;
257 RtlFreeUnicodeString (&BootPath
);
258 RtlFreeUnicodeString (&DriveDeviceName
);
259 RtlFreeUnicodeString (&ArcDeviceName
);
261 if (BootDriveFound
== FALSE
)
263 DbgPrint("No system drive found!\n");
264 KEBUGCHECK (NO_BOOT_DEVICE
);
269 ExpInitializeExecutive(VOID
)
271 LARGE_INTEGER Timeout
;
272 HANDLE ProcessHandle
;
283 BOOLEAN NoGuiBoot
= FALSE
;
285 HANDLE InitDoneEventHandle
;
286 OBJECT_ATTRIBUTES ObjectAttributes
;
289 * Fail at runtime if someone has changed various structures without
290 * updating the offsets used for the assembler code.
292 ASSERT(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
293 ASSERT(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
294 ASSERT(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
295 ASSERT(FIELD_OFFSET(KTHREAD
, NpxState
) == KTHREAD_NPX_STATE
);
296 ASSERT(FIELD_OFFSET(KTHREAD
, ServiceTable
) == KTHREAD_SERVICE_TABLE
);
297 ASSERT(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
298 ASSERT(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
299 ASSERT(FIELD_OFFSET(KTHREAD
, CallbackStack
) == KTHREAD_CALLBACK_STACK
);
300 ASSERT(FIELD_OFFSET(KTHREAD
, ApcState
.Process
) == KTHREAD_APCSTATE_PROCESS
);
301 ASSERT(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
302 KPROCESS_DIRECTORY_TABLE_BASE
);
303 ASSERT(FIELD_OFFSET(KPROCESS
, IopmOffset
) == KPROCESS_IOPM_OFFSET
);
304 ASSERT(FIELD_OFFSET(KPROCESS
, LdtDescriptor
) == KPROCESS_LDT_DESCRIPTOR0
);
305 ASSERT(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
306 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, SavedExceptionStack
) == TF_SAVED_EXCEPTION_STACK
);
307 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
308 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
310 ASSERT(FIELD_OFFSET(KPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
311 ASSERT(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
312 ASSERT(FIELD_OFFSET(KPCR
, PrcbData
) + FIELD_OFFSET(KPRCB
, CurrentThread
) == KPCR_CURRENT_THREAD
);
313 ASSERT(FIELD_OFFSET(KPCR
, PrcbData
) + FIELD_OFFSET(KPRCB
, NpxThread
) == KPCR_NPX_THREAD
);
315 ASSERT(FIELD_OFFSET(KTSS
, Esp0
) == KTSS_ESP0
);
316 ASSERT(FIELD_OFFSET(KTSS
, Eflags
) == KTSS_EFLAGS
);
317 ASSERT(FIELD_OFFSET(KTSS
, IoMapBase
) == KTSS_IOMAPBASE
);
319 ASSERT(sizeof(FX_SAVE_AREA
) == SIZEOF_FX_SAVE_AREA
);
323 KeLowerIrql(DISPATCH_LEVEL
);
327 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
330 while(*p1
&& (p2
= strchr(p1
, '/')))
333 if (!_strnicmp(p2
, "MAXMEM", 6))
336 while (isspace(*p2
)) p2
++;
340 while(isspace(*p2
)) p2
++;
345 MaxMem
= MaxMem
* 10 + *p2
- '0';
352 else if (!_strnicmp(p2
, "NOGUIBOOT", 9))
357 else if (!_strnicmp(p2
, "CRASHDUMP", 9))
363 if (!_strnicmp(p2
, "FULL", 4))
365 MmCoreDumpType
= MM_CORE_DUMP_TYPE_FULL
;
369 MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
376 MmInit1(FirstKrnlPhysAddr
,
379 (PADDRESS_RANGE
)&KeMemoryMap
,
380 KeMemoryMapRangeCount
,
381 MaxMem
> 8 ? MaxMem
: 4096);
383 /* Import ANSI code page table */
384 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
386 start
= KeLoaderModules
[i
].ModStart
;
387 length
= KeLoaderModules
[i
].ModEnd
- start
;
389 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
392 name
= (PCHAR
)KeLoaderModules
[i
].String
;
399 if (!_stricmp (name
, "ansi.nls"))
401 RtlpImportAnsiCodePage((PUSHORT
)start
, length
);
405 /* Import OEM code page table */
406 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
408 start
= KeLoaderModules
[i
].ModStart
;
409 length
= KeLoaderModules
[i
].ModEnd
- start
;
411 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
414 name
= (PCHAR
)KeLoaderModules
[i
].String
;
421 if (!_stricmp (name
, "oem.nls"))
423 RtlpImportOemCodePage((PUSHORT
)start
, length
);
427 /* Import Unicode casemap table */
428 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
430 start
= KeLoaderModules
[i
].ModStart
;
431 length
= KeLoaderModules
[i
].ModEnd
- start
;
433 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
436 name
= (PCHAR
)KeLoaderModules
[i
].String
;
443 if (!_stricmp (name
, "casemap.nls"))
445 RtlpImportUnicodeCasemap((PUSHORT
)start
, length
);
449 /* Create initial NLS tables */
450 RtlpCreateInitialNlsTables();
453 * Initialize the kernel debugger
455 KdInitSystem (1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
460 if (KeMemoryMapRangeCount
> 0)
462 DPRINT1("MemoryMap:\n");
463 for (i
= 0; i
< KeMemoryMapRangeCount
; i
++)
465 switch(KeMemoryMap
[i
].Type
)
468 strcpy(str
, "(usable)");
471 strcpy(str
, "(reserved)");
474 strcpy(str
, "(ACPI data)");
477 strcpy(str
, "(ACPI NVS)");
480 sprintf(str
, "type %lu", KeMemoryMap
[i
].Type
);
482 DPRINT1("%08x - %08x %s\n", KeMemoryMap
[i
].BaseAddrLow
, KeMemoryMap
[i
].BaseAddrLow
+ KeMemoryMap
[i
].LengthLow
, str
);
487 KeLowerIrql(PASSIVE_LEVEL
);
490 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
497 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
499 KeNumberProcessors
= 1;
501 PiInitProcessManager();
503 if (KdPollBreakIn ())
505 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
508 /* Initialize all processors */
509 while (!HalAllProcessorsStarted())
511 PVOID ProcessorStack
;
513 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
514 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
516 /* Allocate a stack for use when booting the processor */
517 ProcessorStack
= Ki386InitialStackArray
[((int)KeNumberProcessors
)] + MM_STACK_SIZE
;
519 HalStartNextProcessor(0, (ULONG
)ProcessorStack
- 2*sizeof(FX_SAVE_AREA
));
520 KeNumberProcessors
++;
524 * Initialize various critical subsystems
526 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
532 CmInitializeRegistry();
536 FsRtlpInitFileLockingImplementation();
538 /* Report all resources used by hal */
539 HalReportResourceUsage();
542 * Clear the screen to blue
544 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
547 * Display version number and copyright/warranty message
549 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
550 KERNEL_VERSION_BUILD_STR
")\n");
551 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
552 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
553 "Public License, and you\n");
554 HalDisplayString("are welcome to change it and/or distribute copies of it "
556 HalDisplayString("conditions. There is absolutely no warranty for "
559 if (KeNumberProcessors
> 1)
562 "Found %d system processors. [%lu MB Memory]\n",
564 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
569 "Found 1 system processor. [%lu MB Memory]\n",
570 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
572 HalDisplayString(str
);
577 /* Create the NLS section */
578 RtlpCreateNlsSection();
581 * Initalize services loaded at boot time
583 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
584 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
586 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
587 KeLoaderModules
[i
].String
,
588 KeLoaderModules
[i
].ModStart
,
589 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
592 /* Pass 1: import system hive registry chunk */
594 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
596 start
= KeLoaderModules
[i
].ModStart
;
597 length
= KeLoaderModules
[i
].ModEnd
- start
;
599 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
600 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
603 name
= (PCHAR
)KeLoaderModules
[i
].String
;
610 if (!_stricmp (name
, "system") ||
611 !_stricmp (name
, "system.hiv"))
613 CPRINT("Process system hive registry chunk at %08lx\n", start
);
615 CmImportSystemHive((PCHAR
)start
, length
);
619 /* Pass 2: import hardware hive registry chunk */
620 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
622 start
= KeLoaderModules
[i
].ModStart
;
623 length
= KeLoaderModules
[i
].ModEnd
- start
;
624 name
= (PCHAR
)KeLoaderModules
[i
].String
;
625 if (!_stricmp (name
, "hardware") ||
626 !_stricmp (name
, "hardware.hiv"))
628 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
629 CmImportHardwareHive((PCHAR
)start
, length
);
633 /* Create dummy keys if no hardware hive was found */
634 CmImportHardwareHive (NULL
, 0);
636 /* Initialize volatile registry settings */
637 if (SetupBoot
== FALSE
)
639 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
642 /* Initialize the time zone information from the registry */
643 ExpInitTimeZoneInfo();
646 * Enter the kernel debugger before starting up the boot drivers
652 IoCreateDriverList();
656 /* Initialize Callbacks before drivers */
657 ExpInitializeCallbacks();
659 /* Start boot logging */
661 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
662 while (*p1
&& (p2
= strchr(p1
, '/')))
665 if (!_strnicmp(p2
, "BOOTLOG", 7))
675 * Load boot start drivers
677 IopInitializeBootDrivers();
679 /* Display the boot screen image if not disabled */
682 InbvEnableBootDriver(TRUE
);
685 /* Create ARC names for boot devices */
688 /* Create the SystemRoot symbolic link */
689 CPRINT("CommandLine: %s\n", (PCHAR
)KeLoaderBlock
.CommandLine
);
690 DPRINT1("MmSystemRangeStart: 0x%x PageDir: 0x%x\n", MmSystemRangeStart
, KeLoaderBlock
.PageDirectoryStart
);
691 Status
= IoCreateSystemRootLink((PCHAR
)KeLoaderBlock
.CommandLine
);
692 if (!NT_SUCCESS(Status
))
694 DbgPrint ( "IoCreateSystemRootLink FAILED: (0x%x) - ", Status
);
695 DbgPrintErrorMessage ( Status
);
696 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
699 #if defined(KDBG) || defined(DBG)
703 /* On the assumption that we can now access disks start up the debug
705 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_BOOTLOG
))
710 PiInitDefaultLocale();
713 * Load services for devices found by PnP manager
715 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
718 * Load system start drivers
720 IopInitializeSystemDrivers();
722 IoDestroyDriverList();
724 /* Stop boot logging */
728 * Assign drive letters
730 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
736 * Initialize shared user page:
737 * - set dos system path, dos device map, etc.
739 InitSystemSharedUserPage ((PCHAR
)KeLoaderBlock
.CommandLine
);
741 /* Create 'ReactOSInitDone' event */
742 RtlInitUnicodeString(&Name
, L
"\\ReactOSInitDone");
743 InitializeObjectAttributes(&ObjectAttributes
,
748 Status
= ZwCreateEvent(&InitDoneEventHandle
,
751 SynchronizationEvent
,
752 FALSE
); /* Not signalled */
753 if (!NT_SUCCESS(Status
))
755 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status
);
756 InitDoneEventHandle
= INVALID_HANDLE_VALUE
;
760 * Launch initial process
762 Status
= LdrLoadInitialProcess(&ProcessHandle
,
764 if (!NT_SUCCESS(Status
))
766 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
769 if (InitDoneEventHandle
!= INVALID_HANDLE_VALUE
)
771 HANDLE Handles
[2]; /* Init event, Initial process */
773 Handles
[0] = InitDoneEventHandle
;
774 Handles
[1] = ProcessHandle
;
776 /* Wait for the system to be initialized */
777 Timeout
.QuadPart
= (LONGLONG
)-1200000000; /* 120 second timeout */
778 Status
= ZwWaitForMultipleObjects(((LONG
) sizeof(Handles
) / sizeof(HANDLE
)),
781 FALSE
, /* Non-alertable */
783 if (!NT_SUCCESS(Status
))
785 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status
);
787 else if (Status
== STATUS_TIMEOUT
)
789 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
791 else if (Status
== STATUS_WAIT_0
+ 1)
794 * Crash the system if the initial process was terminated.
796 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
801 InbvEnableBootDriver(FALSE
);
804 ZwSetEvent(InitDoneEventHandle
, NULL
);
806 ZwClose(InitDoneEventHandle
);
810 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
813 InbvEnableBootDriver(FALSE
);
817 * Crash the system if the initial process terminates within 5 seconds.
819 Timeout
.QuadPart
= (LONGLONG
)-50000000; /* 5 second timeout */
820 Status
= ZwWaitForSingleObject(ProcessHandle
,
823 if (Status
!= STATUS_TIMEOUT
)
825 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
829 * Tell ke/timer.c it's okay to run.
832 KiTimerSystemAuditing
= 1;
834 ZwClose(ThreadHandle
);
835 ZwClose(ProcessHandle
);
838 VOID
__attribute((noinline
))
839 KiSystemStartup(BOOLEAN BootProcessor
)
841 DPRINT1("KiSystemStartup(%d)\n", BootProcessor
);
847 KeApplicationProcessorInit();
850 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
854 ExpInitializeExecutive();
857 PsTerminateSystemThread(STATUS_SUCCESS
);
861 /* Do application processor initialization */
862 PsApplicationProcessorInit();
863 KeLowerIrql(PASSIVE_LEVEL
);
864 PsIdleThreadMain(NULL
);
871 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
873 * FUNCTION: Called by the boot loader to start the kernel
875 * LoaderBlock = Pointer to boot parameters initialized by the boot
877 * NOTE: The boot parameters are stored in low memory which will become
878 * invalid after the memory managment is initialized so we make a local copy.
887 /* Set up the Stacks */
888 trap_stack
= PAGE_ROUND_UP(&double_trap_stack
);
889 trap_stack_top
= trap_stack
+ 3 * PAGE_SIZE
;
890 init_stack
= PAGE_ROUND_UP(&kernel_stack
);
891 init_stack_top
= init_stack
+ 3 * PAGE_SIZE
;
894 * Copy the parameters to a local buffer because lowmem will go away
896 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
897 memcpy(&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
898 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
899 KeLoaderBlock
.ModsCount
++;
900 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
902 /* Save the Base Address */
903 MmSystemRangeStart
= (PVOID
)KeLoaderBlock
.KernelBase
;
906 * Convert a path specification in the grub format to one understood by the
907 * rest of the kernel.
909 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[0] == '(')
911 ULONG DiskNumber
= 0, PartNumber
= 0;
917 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[1] == 'h' &&
918 ((PUCHAR
)_LoaderBlock
->CommandLine
)[2] == 'd')
920 DiskNumber
= ((PCHAR
)_LoaderBlock
->CommandLine
)[3] - '0';
921 PartNumber
= ((PCHAR
)_LoaderBlock
->CommandLine
)[5] - '0';
923 strcpy(Temp
, &((PCHAR
)_LoaderBlock
->CommandLine
)[7]);
924 if ((options
= strchr(Temp
, ' ')) != NULL
)
933 if ((s1
= strrchr(Temp
, '/')) != NULL
)
936 if ((s1
= strrchr(Temp
, '/')) != NULL
)
941 sprintf(KeLoaderCommandLine
,
942 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
943 DiskNumber
, PartNumber
+ 1, Temp
, options
);
945 p
= KeLoaderCommandLine
;
946 while (*p
!= 0 && *p
!= ' ')
954 DPRINT1("Command Line: %s\n", KeLoaderCommandLine
);
958 strcpy(KeLoaderCommandLine
, (PCHAR
)_LoaderBlock
->CommandLine
);
960 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
962 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
963 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
964 KeLoaderModules
[0].ModStart
= KERNEL_BASE
;
965 /* Take this value from the PE... */
966 PIMAGE_NT_HEADERS NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
967 PIMAGE_OPTIONAL_HEADER OptHead
= &NtHeader
->OptionalHeader
;
968 KeLoaderModules
[0].ModEnd
= KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
969 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
972 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
974 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
978 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
980 KeLoaderModules
[i
].ModStart
-= 0x200000;
981 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
982 KeLoaderModules
[i
].ModEnd
-= 0x200000;
983 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
984 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
987 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
989 /* Low level architecture specific initialization */
990 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
992 HalBase
= KeLoaderModules
[1].ModStart
;
993 DriverBase
= LastKernelAddress
;
994 LdrHalBase
= (ULONG_PTR
)DriverBase
;
996 LdrInitModuleManagement();
1001 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)KERNEL_BASE
, &DriverSize
);
1003 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
1006 * Process ntoskrnl.exe
1008 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
, (PVOID
)KERNEL_BASE
, (PVOID
)DriverBase
, &DriverSize
);
1010 /* Now our imports from HAL are fixed. This is the first */
1011 /* time in the boot process that we can use HAL */
1013 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
1014 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
1016 KeMemoryMapRangeCount
= 0;
1017 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
1019 /* We have a memory map from the nice BIOS */
1020 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
1022 while (i
< KeLoaderBlock
.MmapLength
)
1024 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1025 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
1026 sizeof(ADDRESS_RANGE
));
1027 KeMemoryMapRangeCount
++;
1030 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
1031 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
1035 KeLoaderBlock
.MmapLength
= 0;
1036 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
1039 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
1040 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
1042 DPRINT1("_main (%x, %x)\n", MultiBootMagic
, _LoaderBlock
);