3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/main.c
22 * PURPOSE: Initalizes the kernel
23 * PROGRAMMER: David Welch (welch@cwcom.net)
28 /* INCLUDES *****************************************************************/
31 #include "../dbg/kdb.h"
32 #include <ntos/bootvid.h>
33 #include <napi/core.h>
36 #include <internal/ntosdbg.h>
38 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
47 #include <internal/debug.h>
49 /* GLOBALS *******************************************************************/
52 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
53 ULONG EXPORTED NtGlobalFlag
= 0;
54 CHAR EXPORTED KeNumberProcessors
;
55 KAFFINITY EXPORTED KeActiveProcessors
;
56 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
57 ULONG EXPORTED KeDcacheFlushCount
= 0;
58 ULONG EXPORTED KeIcacheFlushCount
= 0;
59 ULONG EXPORTED KiDmaIoCoherency
= 0; /* RISC Architectures only */
60 ULONG EXPORTED InitSafeBootMode
= 0; /* KB83764 */
62 /* Microsoft-style declarations */
63 EXPORTED ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
64 EXPORTED ULONG NtGlobalFlag
= 0;
65 EXPORTED CHAR KeNumberProcessors
;
66 EXPORTED KAFFINITY KeActiveProcessors
;
67 EXPORTED LOADER_PARAMETER_BLOCK KeLoaderBlock
;
68 EXPORTED ULONG KeDcacheFlushCount
= 0;
69 EXPORTED ULONG KeIcacheFlushCount
= 0;
70 EXPORTED ULONG KiDmaIoCoherency
= 0; /* RISC Architectures only */
71 EXPORTED ULONG InitSafeBootMode
= 0; /* KB83764 */
74 static LOADER_MODULE KeLoaderModules
[64];
75 static CHAR KeLoaderModuleStrings
[64][256];
76 static CHAR KeLoaderCommandLine
[256];
77 static ADDRESS_RANGE KeMemoryMap
[64];
78 static ULONG KeMemoryMapRangeCount
;
79 static ULONG_PTR FirstKrnlPhysAddr
;
80 static ULONG_PTR LastKrnlPhysAddr
;
81 static ULONG_PTR LastKernelAddress
;
82 volatile BOOLEAN Initialized
= FALSE
;
83 extern ULONG MmCoreDumpType
;
84 extern CHAR KiTimerSystemAuditing
;
86 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
89 /* FUNCTIONS ****************************************************************/
91 static VOID INIT_FUNCTION
92 InitSystemSharedUserPage (PCSZ ParameterLine
)
94 UNICODE_STRING ArcDeviceName
;
95 UNICODE_STRING ArcName
;
96 UNICODE_STRING BootPath
;
97 UNICODE_STRING DriveDeviceName
;
98 UNICODE_STRING DriveName
;
99 WCHAR DriveNameBuffer
[20];
101 PWCHAR ArcNameBuffer
;
105 OBJECT_ATTRIBUTES ObjectAttributes
;
108 BOOLEAN BootDriveFound
;
112 * The shared user page has been zeroed-out right after creation.
113 * There is NO need to do this again.
116 Ki386SetProcessorFeatures();
118 SharedUserData
->NtProductType
= NtProductWinNt
;
119 SharedUserData
->ProductTypeIsValid
= TRUE
;
120 SharedUserData
->NtMajorVersion
= 5;
121 SharedUserData
->NtMinorVersion
= 0;
123 BootDriveFound
= FALSE
;
126 * Retrieve the current dos system path
127 * (e.g.: C:\reactos) from the given arc path
128 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
129 * Format: "<arc_name>\<path> [options...]"
132 /* create local parameter line copy */
133 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
134 strcpy (ParamBuffer
, (char *)ParameterLine
);
135 DPRINT("%s\n", ParamBuffer
);
137 /* cut options off */
138 p
= strchr (ParamBuffer
, ' ');
143 DPRINT("%s\n", ParamBuffer
);
146 p
= strchr (ParamBuffer
, '\\');
149 DPRINT("Boot path: %s\n", p
);
150 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
155 DPRINT("Boot path: %s\n", "\\");
156 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
158 DPRINT("Arc name: %s\n", ParamBuffer
);
160 /* Only arc name left - build full arc name */
161 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
162 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
163 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
164 DPRINT("Arc name: %wZ\n", &ArcName
);
166 /* free ParamBuffer */
167 ExFreePool (ParamBuffer
);
169 /* allocate arc device name string */
170 ArcDeviceName
.Length
= 0;
171 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
172 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
174 InitializeObjectAttributes (&ObjectAttributes
,
180 Status
= NtOpenSymbolicLinkObject (&Handle
,
181 SYMBOLIC_LINK_ALL_ACCESS
,
183 RtlFreeUnicodeString (&ArcName
);
184 if (!NT_SUCCESS(Status
))
186 RtlFreeUnicodeString (&BootPath
);
187 RtlFreeUnicodeString (&ArcDeviceName
);
188 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
194 Status
= NtQuerySymbolicLinkObject (Handle
,
198 if (!NT_SUCCESS(Status
))
200 RtlFreeUnicodeString (&BootPath
);
201 RtlFreeUnicodeString (&ArcDeviceName
);
202 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
207 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
210 /* allocate device name string */
211 DriveDeviceName
.Length
= 0;
212 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
213 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
215 for (i
= 0; i
< 26; i
++)
217 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
218 RtlInitUnicodeString (&DriveName
,
221 InitializeObjectAttributes (&ObjectAttributes
,
227 Status
= NtOpenSymbolicLinkObject (&Handle
,
228 SYMBOLIC_LINK_ALL_ACCESS
,
230 if (!NT_SUCCESS(Status
))
232 DPRINT("Failed to open link %wZ\n",
237 Status
= NtQuerySymbolicLinkObject (Handle
,
240 if (!NT_SUCCESS(Status
))
242 DPRINT("Failed query open link %wZ\n",
246 DPRINT("Opened link: %wZ ==> %wZ\n",
247 &DriveName
, &DriveDeviceName
);
249 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
251 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
252 swprintf(SharedUserData
->NtSystemRoot
,
253 L
"%C:%wZ", 'A' + i
, &BootPath
);
255 BootDriveFound
= TRUE
;
261 RtlFreeUnicodeString (&BootPath
);
262 RtlFreeUnicodeString (&DriveDeviceName
);
263 RtlFreeUnicodeString (&ArcDeviceName
);
265 if (BootDriveFound
== FALSE
)
267 DbgPrint("No system drive found!\n");
268 KEBUGCHECK (NO_BOOT_DEVICE
);
273 ExpInitializeExecutive(VOID
)
275 LARGE_INTEGER Timeout
;
276 HANDLE ProcessHandle
;
287 BOOLEAN NoGuiBoot
= FALSE
;
289 HANDLE InitDoneEventHandle
;
290 OBJECT_ATTRIBUTES ObjectAttributes
;
293 * Fail at runtime if someone has changed various structures without
294 * updating the offsets used for the assembler code.
296 ASSERT(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
297 ASSERT(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
298 ASSERT(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
299 ASSERT(FIELD_OFFSET(KTHREAD
, NpxState
) == KTHREAD_NPX_STATE
);
300 ASSERT(FIELD_OFFSET(KTHREAD
, ServiceTable
) == KTHREAD_SERVICE_TABLE
);
301 ASSERT(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
302 ASSERT(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
303 ASSERT(FIELD_OFFSET(KTHREAD
, CallbackStack
) == KTHREAD_CALLBACK_STACK
);
304 ASSERT(FIELD_OFFSET(KTHREAD
, ApcState
.Process
) == KTHREAD_APCSTATE_PROCESS
);
305 ASSERT(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
306 KPROCESS_DIRECTORY_TABLE_BASE
);
307 ASSERT(FIELD_OFFSET(KPROCESS
, IopmOffset
) == KPROCESS_IOPM_OFFSET
);
308 ASSERT(FIELD_OFFSET(KPROCESS
, LdtDescriptor
) == KPROCESS_LDT_DESCRIPTOR0
);
309 ASSERT(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
310 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, SavedExceptionStack
) == TF_SAVED_EXCEPTION_STACK
);
311 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
312 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
314 ASSERT(FIELD_OFFSET(KPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
315 ASSERT(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
316 ASSERT(FIELD_OFFSET(KPCR
, PrcbData
) + FIELD_OFFSET(KPRCB
, CurrentThread
) == KPCR_CURRENT_THREAD
);
317 ASSERT(FIELD_OFFSET(KPCR
, PrcbData
) + FIELD_OFFSET(KPRCB
, NpxThread
) == KPCR_NPX_THREAD
);
319 ASSERT(FIELD_OFFSET(KTSS
, Esp0
) == KTSS_ESP0
);
320 ASSERT(FIELD_OFFSET(KTSS
, Eflags
) == KTSS_EFLAGS
);
321 ASSERT(FIELD_OFFSET(KTSS
, IoMapBase
) == KTSS_IOMAPBASE
);
323 ASSERT(sizeof(FX_SAVE_AREA
) == SIZEOF_FX_SAVE_AREA
);
327 KeLowerIrql(DISPATCH_LEVEL
);
331 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
334 while(*p1
&& (p2
= strchr(p1
, '/')))
337 if (!_strnicmp(p2
, "MAXMEM", 6))
340 while (isspace(*p2
)) p2
++;
344 while(isspace(*p2
)) p2
++;
349 MaxMem
= MaxMem
* 10 + *p2
- '0';
356 else if (!_strnicmp(p2
, "NOGUIBOOT", 9))
361 else if (!_strnicmp(p2
, "CRASHDUMP", 9))
367 if (!_strnicmp(p2
, "FULL", 4))
369 MmCoreDumpType
= MM_CORE_DUMP_TYPE_FULL
;
373 MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
380 MmInit1(FirstKrnlPhysAddr
,
383 (PADDRESS_RANGE
)&KeMemoryMap
,
384 KeMemoryMapRangeCount
,
385 MaxMem
> 8 ? MaxMem
: 4096);
387 /* Import ANSI code page table */
388 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
390 start
= KeLoaderModules
[i
].ModStart
;
391 length
= KeLoaderModules
[i
].ModEnd
- start
;
393 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
396 name
= (PCHAR
)KeLoaderModules
[i
].String
;
403 if (!_stricmp (name
, "ansi.nls"))
405 RtlpImportAnsiCodePage((PUSHORT
)start
, length
);
409 /* Import OEM code page table */
410 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
412 start
= KeLoaderModules
[i
].ModStart
;
413 length
= KeLoaderModules
[i
].ModEnd
- start
;
415 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
418 name
= (PCHAR
)KeLoaderModules
[i
].String
;
425 if (!_stricmp (name
, "oem.nls"))
427 RtlpImportOemCodePage((PUSHORT
)start
, length
);
431 /* Import Unicode casemap table */
432 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
434 start
= KeLoaderModules
[i
].ModStart
;
435 length
= KeLoaderModules
[i
].ModEnd
- start
;
437 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
440 name
= (PCHAR
)KeLoaderModules
[i
].String
;
447 if (!_stricmp (name
, "casemap.nls"))
449 RtlpImportUnicodeCasemap((PUSHORT
)start
, length
);
453 /* Create initial NLS tables */
454 RtlpCreateInitialNlsTables();
457 * Initialize the kernel debugger
459 KdInitSystem (1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
464 if (KeMemoryMapRangeCount
> 0)
466 DPRINT1("MemoryMap:\n");
467 for (i
= 0; i
< KeMemoryMapRangeCount
; i
++)
469 switch(KeMemoryMap
[i
].Type
)
472 strcpy(str
, "(usable)");
475 strcpy(str
, "(reserved)");
478 strcpy(str
, "(ACPI data)");
481 strcpy(str
, "(ACPI NVS)");
484 sprintf(str
, "type %lu", KeMemoryMap
[i
].Type
);
486 DPRINT1("%08x - %08x %s\n", KeMemoryMap
[i
].BaseAddrLow
, KeMemoryMap
[i
].BaseAddrLow
+ KeMemoryMap
[i
].LengthLow
, str
);
491 KeLowerIrql(PASSIVE_LEVEL
);
494 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
501 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
503 KeNumberProcessors
= 1;
505 PiInitProcessManager();
507 if (KdPollBreakIn ())
509 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
512 /* Initialize all processors */
513 while (!HalAllProcessorsStarted())
515 PVOID ProcessorStack
;
517 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
518 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
520 /* Allocate a stack for use when booting the processor */
521 ProcessorStack
= Ki386InitialStackArray
[((int)KeNumberProcessors
)] + MM_STACK_SIZE
;
523 HalStartNextProcessor(0, (ULONG
)ProcessorStack
- 2*sizeof(FX_SAVE_AREA
));
524 KeNumberProcessors
++;
528 * Initialize various critical subsystems
530 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
536 CmInitializeRegistry();
540 FsRtlpInitFileLockingImplementation();
542 /* Report all resources used by hal */
543 HalReportResourceUsage();
546 * Clear the screen to blue
548 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
551 * Display version number and copyright/warranty message
553 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
554 KERNEL_VERSION_BUILD_STR
")\n");
555 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
556 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
557 "Public License, and you\n");
558 HalDisplayString("are welcome to change it and/or distribute copies of it "
560 HalDisplayString("conditions. There is absolutely no warranty for "
563 if (KeNumberProcessors
> 1)
566 "Found %d system processors. [%lu MB Memory]\n",
568 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
573 "Found 1 system processor. [%lu MB Memory]\n",
574 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
576 HalDisplayString(str
);
581 /* Create the NLS section */
582 RtlpCreateNlsSection();
585 * Initalize services loaded at boot time
587 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
588 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
590 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
591 KeLoaderModules
[i
].String
,
592 KeLoaderModules
[i
].ModStart
,
593 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
596 /* Pass 1: import system hive registry chunk */
598 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
600 start
= KeLoaderModules
[i
].ModStart
;
601 length
= KeLoaderModules
[i
].ModEnd
- start
;
603 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
604 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
607 name
= (PCHAR
)KeLoaderModules
[i
].String
;
614 if (!_stricmp (name
, "system") ||
615 !_stricmp (name
, "system.hiv"))
617 CPRINT("Process system hive registry chunk at %08lx\n", start
);
619 CmImportSystemHive((PCHAR
)start
, length
);
623 /* Pass 2: import hardware hive registry chunk */
624 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
626 start
= KeLoaderModules
[i
].ModStart
;
627 length
= KeLoaderModules
[i
].ModEnd
- start
;
628 name
= (PCHAR
)KeLoaderModules
[i
].String
;
629 if (!_stricmp (name
, "hardware") ||
630 !_stricmp (name
, "hardware.hiv"))
632 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
633 CmImportHardwareHive((PCHAR
)start
, length
);
637 /* Create dummy keys if no hardware hive was found */
638 CmImportHardwareHive (NULL
, 0);
640 /* Initialize volatile registry settings */
641 if (SetupBoot
== FALSE
)
643 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
646 /* Initialize the time zone information from the registry */
647 ExpInitTimeZoneInfo();
650 * Enter the kernel debugger before starting up the boot drivers
656 IoCreateDriverList();
660 /* Initialize Callbacks before drivers */
661 ExpInitializeCallbacks();
663 /* Start boot logging */
665 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
666 while (*p1
&& (p2
= strchr(p1
, '/')))
669 if (!_strnicmp(p2
, "BOOTLOG", 7))
679 * Load boot start drivers
681 IopInitializeBootDrivers();
683 /* Display the boot screen image if not disabled */
686 InbvEnableBootDriver(TRUE
);
689 /* Create ARC names for boot devices */
692 /* Create the SystemRoot symbolic link */
693 CPRINT("CommandLine: %s\n", (PCHAR
)KeLoaderBlock
.CommandLine
);
694 DPRINT1("MmSystemRangeStart: 0x%x\n", MmSystemRangeStart
);
695 Status
= IoCreateSystemRootLink((PCHAR
)KeLoaderBlock
.CommandLine
);
696 if (!NT_SUCCESS(Status
))
698 DbgPrint ( "IoCreateSystemRootLink FAILED: (0x%x) - ", Status
);
699 DbgPrintErrorMessage ( Status
);
700 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
703 #if defined(KDBG) || defined(DBG)
707 /* On the assumption that we can now access disks start up the debug
709 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_BOOTLOG
))
714 PiInitDefaultLocale();
717 * Load services for devices found by PnP manager
719 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
722 * Load system start drivers
724 IopInitializeSystemDrivers();
726 IoDestroyDriverList();
728 /* Stop boot logging */
732 * Assign drive letters
734 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
740 * Initialize shared user page:
741 * - set dos system path, dos device map, etc.
743 InitSystemSharedUserPage ((PCHAR
)KeLoaderBlock
.CommandLine
);
745 /* Create 'ReactOSInitDone' event */
746 RtlInitUnicodeString(&Name
, L
"\\ReactOSInitDone");
747 InitializeObjectAttributes(&ObjectAttributes
,
752 Status
= ZwCreateEvent(&InitDoneEventHandle
,
755 SynchronizationEvent
,
756 FALSE
); /* Not signalled */
757 if (!NT_SUCCESS(Status
))
759 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status
);
760 InitDoneEventHandle
= INVALID_HANDLE_VALUE
;
764 * Launch initial process
766 Status
= LdrLoadInitialProcess(&ProcessHandle
,
768 if (!NT_SUCCESS(Status
))
770 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
773 if (InitDoneEventHandle
!= INVALID_HANDLE_VALUE
)
775 HANDLE Handles
[2]; /* Init event, Initial process */
777 Handles
[0] = InitDoneEventHandle
;
778 Handles
[1] = ProcessHandle
;
780 /* Wait for the system to be initialized */
781 Timeout
.QuadPart
= (LONGLONG
)-1200000000; /* 120 second timeout */
782 Status
= ZwWaitForMultipleObjects(((LONG
) sizeof(Handles
) / sizeof(HANDLE
)),
785 FALSE
, /* Non-alertable */
787 if (!NT_SUCCESS(Status
))
789 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status
);
791 else if (Status
== STATUS_TIMEOUT
)
793 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
795 else if (Status
== STATUS_WAIT_0
+ 1)
798 * Crash the system if the initial process was terminated.
800 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
805 InbvEnableBootDriver(FALSE
);
808 ZwSetEvent(InitDoneEventHandle
, NULL
);
810 ZwClose(InitDoneEventHandle
);
814 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
817 InbvEnableBootDriver(FALSE
);
821 * Crash the system if the initial process terminates within 5 seconds.
823 Timeout
.QuadPart
= (LONGLONG
)-50000000; /* 5 second timeout */
824 Status
= ZwWaitForSingleObject(ProcessHandle
,
827 if (Status
!= STATUS_TIMEOUT
)
829 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
833 * Tell ke/timer.c it's okay to run.
836 KiTimerSystemAuditing
= 1;
838 ZwClose(ThreadHandle
);
839 ZwClose(ProcessHandle
);
842 VOID
__attribute((noinline
))
843 KiSystemStartup(BOOLEAN BootProcessor
)
850 KeApplicationProcessorInit();
853 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
857 ExpInitializeExecutive();
860 PsTerminateSystemThread(STATUS_SUCCESS
);
864 /* Do application processor initialization */
865 PsApplicationProcessorInit();
866 KeLowerIrql(PASSIVE_LEVEL
);
867 PsIdleThreadMain(NULL
);
874 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
876 * FUNCTION: Called by the boot loader to start the kernel
878 * LoaderBlock = Pointer to boot parameters initialized by the boot
880 * NOTE: The boot parameters are stored in low memory which will become
881 * invalid after the memory managment is initialized so we make a local copy.
886 extern ULONG _bss_end__
;
892 * Copy the parameters to a local buffer because lowmem will go away
894 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
895 memcpy(&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
896 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
897 KeLoaderBlock
.ModsCount
++;
898 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
901 * Convert a path specification in the grub format to one understood by the
902 * rest of the kernel.
904 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[0] == '(')
906 ULONG DiskNumber
= 0, PartNumber
= 0;
912 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[1] == 'h' &&
913 ((PUCHAR
)_LoaderBlock
->CommandLine
)[2] == 'd')
915 DiskNumber
= ((PCHAR
)_LoaderBlock
->CommandLine
)[3] - '0';
916 PartNumber
= ((PCHAR
)_LoaderBlock
->CommandLine
)[5] - '0';
918 strcpy(Temp
, &((PCHAR
)_LoaderBlock
->CommandLine
)[7]);
919 if ((options
= strchr(Temp
, ' ')) != NULL
)
928 if ((s1
= strrchr(Temp
, '/')) != NULL
)
931 if ((s1
= strrchr(Temp
, '/')) != NULL
)
936 sprintf(KeLoaderCommandLine
,
937 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
938 DiskNumber
, PartNumber
+ 1, Temp
, options
);
940 p
= KeLoaderCommandLine
;
941 while (*p
!= 0 && *p
!= ' ')
949 DPRINT1("Command Line: %s\n", KeLoaderCommandLine
);
953 strcpy(KeLoaderCommandLine
, (PCHAR
)_LoaderBlock
->CommandLine
);
955 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
957 /* Gotta check 3GB setting right *here* before we use KERNEL_BASE! */
958 if (!_strnicmp(KeLoaderCommandLine
, "3GB", 3)) {
961 MmSystemRangeStart
= (PVOID
)0xC0000000;
966 MmSystemRangeStart
= (PVOID
)0x80000000;
969 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
970 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
971 KeLoaderModules
[0].ModStart
= KERNEL_BASE
;
973 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
975 /* Take this value from the PE... */
977 PIMAGE_NT_HEADERS NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
978 PIMAGE_OPTIONAL_HEADER OptHead
= &NtHeader
->OptionalHeader
;
979 KeLoaderModules
[0].ModEnd
=
980 KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
983 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
986 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
988 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
992 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
994 /* TODO: Fix this hardcoded load address stuff... */
995 KeLoaderModules
[i
].ModStart
-= 0x200000;
996 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
997 KeLoaderModules
[i
].ModEnd
-= 0x200000;
998 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
999 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
1002 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
1004 /* Low level architecture specific initialization */
1005 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
1007 HalBase
= KeLoaderModules
[1].ModStart
;
1008 DriverBase
= LastKernelAddress
;
1009 LdrHalBase
= (ULONG_PTR
)DriverBase
;
1011 LdrInitModuleManagement();
1016 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)KERNEL_BASE
, &DriverSize
);
1018 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
1021 * Process ntoskrnl.exe
1023 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
, (PVOID
)KERNEL_BASE
, (PVOID
)DriverBase
, &DriverSize
);
1025 /* Now our imports from HAL are fixed. This is the first */
1026 /* time in the boot process that we can use HAL */
1028 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
1029 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
1031 KeMemoryMapRangeCount
= 0;
1032 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
1034 /* We have a memory map from the nice BIOS */
1035 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
1037 while (i
< KeLoaderBlock
.MmapLength
)
1039 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1040 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
1041 sizeof(ADDRESS_RANGE
));
1042 KeMemoryMapRangeCount
++;
1045 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
1046 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
1050 KeLoaderBlock
.MmapLength
= 0;
1051 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
1054 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
1055 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);