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.
19 /* $Id: main.c,v 1.212 2004/12/24 17:06:58 navaraf Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
29 /* INCLUDES *****************************************************************/
32 #include "../dbg/kdb.h"
33 #include <ntos/bootvid.h>
34 #include <napi/core.h>
37 #include <internal/ntosdbg.h>
39 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
48 #include <internal/debug.h>
50 /* GLOBALS *******************************************************************/
53 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
54 ULONG EXPORTED NtGlobalFlag
= 0;
55 CHAR EXPORTED KeNumberProcessors
;
56 KAFFINITY EXPORTED KeActiveProcessors
;
57 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
58 ULONG EXPORTED KeDcacheFlushCount
= 0;
59 ULONG EXPORTED KeIcacheFlushCount
= 0;
60 ULONG EXPORTED KiDmaIoCoherency
= 0; /* RISC Architectures only */
61 ULONG EXPORTED InitSafeBootMode
= 0; /* KB83764 */
63 /* Microsoft-style declarations */
64 EXPORTED ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
65 EXPORTED ULONG NtGlobalFlag
= 0;
66 EXPORTED CHAR KeNumberProcessors
;
67 EXPORTED KAFFINITY KeActiveProcessors
;
68 EXPORTED LOADER_PARAMETER_BLOCK KeLoaderBlock
;
69 EXPORTED ULONG KeDcacheFlushCount
= 0;
70 EXPORTED ULONG KeIcacheFlushCount
= 0;
71 EXPORTED ULONG KiDmaIoCoherency
= 0; /* RISC Architectures only */
72 EXPORTED ULONG InitSafeBootMode
= 0; /* KB83764 */
75 static LOADER_MODULE KeLoaderModules
[64];
76 static CHAR KeLoaderModuleStrings
[64][256];
77 static CHAR KeLoaderCommandLine
[256];
78 static ADDRESS_RANGE KeMemoryMap
[64];
79 static ULONG KeMemoryMapRangeCount
;
80 static ULONG FirstKrnlPhysAddr
;
81 static ULONG LastKrnlPhysAddr
;
82 static ULONG LastKernelAddress
;
83 volatile BOOLEAN Initialized
= FALSE
;
84 extern ULONG MmCoreDumpType
;
85 extern CHAR KiTimerSystemAuditing
;
87 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
90 /* FUNCTIONS ****************************************************************/
92 static VOID INIT_FUNCTION
93 InitSystemSharedUserPage (PCSZ ParameterLine
)
95 UNICODE_STRING ArcDeviceName
;
96 UNICODE_STRING ArcName
;
97 UNICODE_STRING BootPath
;
98 UNICODE_STRING DriveDeviceName
;
99 UNICODE_STRING DriveName
;
100 WCHAR DriveNameBuffer
[20];
102 PWCHAR ArcNameBuffer
;
106 OBJECT_ATTRIBUTES ObjectAttributes
;
109 BOOLEAN BootDriveFound
;
113 * The shared user page has been zeroed-out right after creation.
114 * There is NO need to do this again.
117 Ki386SetProcessorFeatures();
119 SharedUserData
->NtProductType
= NtProductWinNt
;
120 SharedUserData
->ProductTypeIsValid
= TRUE
;
121 SharedUserData
->NtMajorVersion
= 5;
122 SharedUserData
->NtMinorVersion
= 0;
124 BootDriveFound
= FALSE
;
127 * Retrieve the current dos system path
128 * (e.g.: C:\reactos) from the given arc path
129 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
130 * Format: "<arc_name>\<path> [options...]"
133 /* create local parameter line copy */
134 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
135 strcpy (ParamBuffer
, (char *)ParameterLine
);
136 DPRINT("%s\n", ParamBuffer
);
138 /* cut options off */
139 p
= strchr (ParamBuffer
, ' ');
144 DPRINT("%s\n", ParamBuffer
);
147 p
= strchr (ParamBuffer
, '\\');
150 DPRINT("Boot path: %s\n", p
);
151 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
156 DPRINT("Boot path: %s\n", "\\");
157 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
159 DPRINT("Arc name: %s\n", ParamBuffer
);
161 /* Only arc name left - build full arc name */
162 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
163 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
164 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
165 DPRINT("Arc name: %wZ\n", &ArcName
);
167 /* free ParamBuffer */
168 ExFreePool (ParamBuffer
);
170 /* allocate arc device name string */
171 ArcDeviceName
.Length
= 0;
172 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
173 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
175 InitializeObjectAttributes (&ObjectAttributes
,
181 Status
= NtOpenSymbolicLinkObject (&Handle
,
182 SYMBOLIC_LINK_ALL_ACCESS
,
184 RtlFreeUnicodeString (&ArcName
);
185 if (!NT_SUCCESS(Status
))
187 RtlFreeUnicodeString (&BootPath
);
188 RtlFreeUnicodeString (&ArcDeviceName
);
189 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
195 Status
= NtQuerySymbolicLinkObject (Handle
,
199 if (!NT_SUCCESS(Status
))
201 RtlFreeUnicodeString (&BootPath
);
202 RtlFreeUnicodeString (&ArcDeviceName
);
203 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
208 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
211 /* allocate device name string */
212 DriveDeviceName
.Length
= 0;
213 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
214 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
216 for (i
= 0; i
< 26; i
++)
218 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
219 RtlInitUnicodeString (&DriveName
,
222 InitializeObjectAttributes (&ObjectAttributes
,
228 Status
= NtOpenSymbolicLinkObject (&Handle
,
229 SYMBOLIC_LINK_ALL_ACCESS
,
231 if (!NT_SUCCESS(Status
))
233 DPRINT("Failed to open link %wZ\n",
238 Status
= NtQuerySymbolicLinkObject (Handle
,
241 if (!NT_SUCCESS(Status
))
243 DPRINT("Failed query open link %wZ\n",
247 DPRINT("Opened link: %wZ ==> %wZ\n",
248 &DriveName
, &DriveDeviceName
);
250 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
252 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
253 swprintf(SharedUserData
->NtSystemRoot
,
254 L
"%C:%wZ", 'A' + i
, &BootPath
);
256 BootDriveFound
= TRUE
;
262 RtlFreeUnicodeString (&BootPath
);
263 RtlFreeUnicodeString (&DriveDeviceName
);
264 RtlFreeUnicodeString (&ArcDeviceName
);
266 if (BootDriveFound
== FALSE
)
268 DbgPrint("No system drive found!\n");
269 KEBUGCHECK (NO_BOOT_DEVICE
);
274 ExpInitializeExecutive(VOID
)
276 LARGE_INTEGER Timeout
;
277 HANDLE ProcessHandle
;
288 BOOLEAN NoGuiBoot
= FALSE
;
290 HANDLE InitDoneEventHandle
;
291 OBJECT_ATTRIBUTES ObjectAttributes
;
294 * Fail at runtime if someone has changed various structures without
295 * updating the offsets used for the assembler code.
297 ASSERT(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
298 ASSERT(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
299 ASSERT(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
300 ASSERT(FIELD_OFFSET(KTHREAD
, NpxState
) == KTHREAD_NPX_STATE
);
301 ASSERT(FIELD_OFFSET(KTHREAD
, ServiceTable
) == KTHREAD_SERVICE_TABLE
);
302 ASSERT(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
303 ASSERT(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
304 ASSERT(FIELD_OFFSET(KTHREAD
, CallbackStack
) == KTHREAD_CALLBACK_STACK
);
305 ASSERT(FIELD_OFFSET(KTHREAD
, ApcState
.Process
) == KTHREAD_APCSTATE_PROCESS
);
306 ASSERT(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
307 KPROCESS_DIRECTORY_TABLE_BASE
);
308 ASSERT(FIELD_OFFSET(KPROCESS
, IopmOffset
) == KPROCESS_IOPM_OFFSET
);
309 ASSERT(FIELD_OFFSET(KPROCESS
, LdtDescriptor
) == KPROCESS_LDT_DESCRIPTOR0
);
310 ASSERT(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
311 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, SavedExceptionStack
) == TF_SAVED_EXCEPTION_STACK
);
312 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
313 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
315 ASSERT(FIELD_OFFSET(KPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
316 ASSERT(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
317 ASSERT(FIELD_OFFSET(KPCR
, PrcbData
) + FIELD_OFFSET(KPRCB
, CurrentThread
) == KPCR_CURRENT_THREAD
);
318 ASSERT(FIELD_OFFSET(KPCR
, PrcbData
) + FIELD_OFFSET(KPRCB
, NpxThread
) == KPCR_NPX_THREAD
);
320 ASSERT(FIELD_OFFSET(KTSS
, Esp0
) == KTSS_ESP0
);
321 ASSERT(FIELD_OFFSET(KTSS
, Eflags
) == KTSS_EFLAGS
);
322 ASSERT(FIELD_OFFSET(KTSS
, IoMapBase
) == KTSS_IOMAPBASE
);
324 ASSERT(sizeof(FX_SAVE_AREA
) == SIZEOF_FX_SAVE_AREA
);
328 KeLowerIrql(DISPATCH_LEVEL
);
332 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
335 while(*p1
&& (p2
= strchr(p1
, '/')))
338 if (!_strnicmp(p2
, "MAXMEM", 6))
341 while (isspace(*p2
)) p2
++;
345 while(isspace(*p2
)) p2
++;
350 MaxMem
= MaxMem
* 10 + *p2
- '0';
357 else if (!_strnicmp(p2
, "NOGUIBOOT", 9))
362 else if (!_strnicmp(p2
, "CRASHDUMP", 9))
368 if (!_strnicmp(p2
, "FULL", 4))
370 MmCoreDumpType
= MM_CORE_DUMP_TYPE_FULL
;
374 MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
381 MmInit1(FirstKrnlPhysAddr
,
384 (PADDRESS_RANGE
)&KeMemoryMap
,
385 KeMemoryMapRangeCount
,
386 MaxMem
> 8 ? MaxMem
: 4096);
388 /* Import ANSI code page table */
389 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
391 start
= KeLoaderModules
[i
].ModStart
;
392 length
= KeLoaderModules
[i
].ModEnd
- start
;
394 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
397 name
= (PCHAR
)KeLoaderModules
[i
].String
;
404 if (!_stricmp (name
, "ansi.nls"))
406 RtlpImportAnsiCodePage((PUSHORT
)start
, length
);
410 /* Import OEM code page table */
411 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
413 start
= KeLoaderModules
[i
].ModStart
;
414 length
= KeLoaderModules
[i
].ModEnd
- start
;
416 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
419 name
= (PCHAR
)KeLoaderModules
[i
].String
;
426 if (!_stricmp (name
, "oem.nls"))
428 RtlpImportOemCodePage((PUSHORT
)start
, length
);
432 /* Import Unicode casemap table */
433 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
435 start
= KeLoaderModules
[i
].ModStart
;
436 length
= KeLoaderModules
[i
].ModEnd
- start
;
438 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
441 name
= (PCHAR
)KeLoaderModules
[i
].String
;
448 if (!_stricmp (name
, "casemap.nls"))
450 RtlpImportUnicodeCasemap((PUSHORT
)start
, length
);
454 /* Create initial NLS tables */
455 RtlpCreateInitialNlsTables();
458 * Initialize the kernel debugger
460 KdInitSystem (1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
465 if (KeMemoryMapRangeCount
> 0)
467 DPRINT("MemoryMap:\n");
468 for (i
= 0; i
< KeMemoryMapRangeCount
; i
++)
470 switch(KeMemoryMap
[i
].Type
)
473 strcpy(str
, "(usable)");
476 strcpy(str
, "(reserved)");
479 strcpy(str
, "(ACPI data)");
482 strcpy(str
, "(ACPI NVS)");
485 sprintf(str
, "type %lu", KeMemoryMap
[i
].Type
);
487 DPRINT("%08x - %08x %s\n", KeMemoryMap
[i
].BaseAddrLow
, KeMemoryMap
[i
].BaseAddrLow
+ KeMemoryMap
[i
].LengthLow
, str
);
492 KeLowerIrql(PASSIVE_LEVEL
);
495 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
502 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
504 PiInitProcessManager();
506 if (KdPollBreakIn ())
508 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
511 /* Initialize all processors */
512 KeNumberProcessors
= 1;
514 while (!HalAllProcessorsStarted())
516 PVOID ProcessorStack
;
518 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
519 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
521 /* Allocate a stack for use when booting the processor */
522 /* FIXME: The nonpaged memory for the stack is not released after use */
524 (char*)ExAllocatePool(NonPagedPool
, MM_STACK_SIZE
) + MM_STACK_SIZE
;
525 Ki386InitialStackArray
[((int)KeNumberProcessors
)] =
526 (PVOID
)((char*)ProcessorStack
- MM_STACK_SIZE
);
528 HalStartNextProcessor(0, (ULONG
)ProcessorStack
- 2*sizeof(FX_SAVE_AREA
));
529 KeNumberProcessors
++;
533 * Initialize various critical subsystems
535 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
541 CmInitializeRegistry();
546 FsRtlpInitFileLockingImplementation();
548 /* Report all resources used by hal */
549 HalReportResourceUsage();
552 * Clear the screen to blue
554 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
557 * Display version number and copyright/warranty message
559 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
560 KERNEL_VERSION_BUILD_STR
")\n");
561 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
562 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
563 "Public License, and you\n");
564 HalDisplayString("are welcome to change it and/or distribute copies of it "
566 HalDisplayString("conditions. There is absolutely no warranty for "
569 if (KeNumberProcessors
> 1)
572 "Found %d system processors. [%lu MB Memory]\n",
574 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
579 "Found 1 system processor. [%lu MB Memory]\n",
580 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
582 HalDisplayString(str
);
587 /* Create the NLS section */
588 RtlpCreateNlsSection();
591 * Initalize services loaded at boot time
593 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
594 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
596 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
597 KeLoaderModules
[i
].String
,
598 KeLoaderModules
[i
].ModStart
,
599 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
602 /* Pass 1: import system hive registry chunk */
604 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
606 start
= KeLoaderModules
[i
].ModStart
;
607 length
= KeLoaderModules
[i
].ModEnd
- start
;
609 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
610 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
613 name
= (PCHAR
)KeLoaderModules
[i
].String
;
620 if (!_stricmp (name
, "system") ||
621 !_stricmp (name
, "system.hiv"))
623 CPRINT("Process system hive registry chunk at %08lx\n", start
);
625 CmImportSystemHive((PCHAR
)start
, length
);
629 /* Pass 2: import hardware hive registry chunk */
630 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
632 start
= KeLoaderModules
[i
].ModStart
;
633 length
= KeLoaderModules
[i
].ModEnd
- start
;
634 name
= (PCHAR
)KeLoaderModules
[i
].String
;
635 if (!_stricmp (name
, "hardware") ||
636 !_stricmp (name
, "hardware.hiv"))
638 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
639 CmImportHardwareHive((PCHAR
)start
, length
);
643 /* Create dummy keys if no hardware hive was found */
644 CmImportHardwareHive (NULL
, 0);
646 /* Initialize volatile registry settings */
647 if (SetupBoot
== FALSE
)
649 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
652 /* Initialize the time zone information from the registry */
653 ExpInitTimeZoneInfo();
656 * Enter the kernel debugger before starting up the boot drivers
662 IoCreateDriverList();
666 /* Initialize Callbacks before drivers */
667 ExpInitializeCallbacks();
669 /* Start boot logging */
671 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
672 while (*p1
&& (p2
= strchr(p1
, '/')))
675 if (!_strnicmp(p2
, "BOOTLOG", 7))
685 * Load boot start drivers
687 IopInitializeBootDrivers();
689 /* Display the boot screen image if not disabled */
692 InbvEnableBootDriver(TRUE
);
695 /* Create ARC names for boot devices */
698 /* Create the SystemRoot symbolic link */
699 CPRINT("CommandLine: %s\n", (PCHAR
)KeLoaderBlock
.CommandLine
);
700 Status
= IoCreateSystemRootLink((PCHAR
)KeLoaderBlock
.CommandLine
);
701 if (!NT_SUCCESS(Status
))
703 DbgPrint ( "IoCreateSystemRootLink FAILED: (0x%x) - ", Status
);
704 DbgPrintErrorMessage ( Status
);
705 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
712 /* On the assumption that we can now access disks start up the debug
714 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_BOOTLOG
))
719 PiInitDefaultLocale();
722 * Load services for devices found by PnP manager
724 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
727 * Load system start drivers
729 IopInitializeSystemDrivers();
731 IoDestroyDriverList();
733 /* Stop boot logging */
737 * Assign drive letters
739 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
745 * Initialize shared user page:
746 * - set dos system path, dos device map, etc.
748 InitSystemSharedUserPage ((PCHAR
)KeLoaderBlock
.CommandLine
);
750 /* Create 'ReactOSInitDone' event */
751 RtlInitUnicodeString(&Name
, L
"\\ReactOSInitDone");
752 InitializeObjectAttributes(&ObjectAttributes
,
757 Status
= NtCreateEvent(&InitDoneEventHandle
,
760 SynchronizationEvent
,
761 FALSE
); /* Not signalled */
762 if (!NT_SUCCESS(Status
))
764 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status
);
765 InitDoneEventHandle
= INVALID_HANDLE_VALUE
;
769 * Launch initial process
771 Status
= LdrLoadInitialProcess(&ProcessHandle
,
773 if (!NT_SUCCESS(Status
))
775 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
778 if (InitDoneEventHandle
!= INVALID_HANDLE_VALUE
)
780 HANDLE Handles
[2]; /* Init event, Initial process */
782 Handles
[0] = InitDoneEventHandle
;
783 Handles
[1] = ProcessHandle
;
785 /* Wait for the system to be initialized */
786 Timeout
.QuadPart
= (LONGLONG
)-1200000000; /* 120 second timeout */
787 Status
= NtWaitForMultipleObjects(((LONG
) sizeof(Handles
) / sizeof(HANDLE
)),
790 FALSE
, /* Non-alertable */
792 if (!NT_SUCCESS(Status
))
794 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status
);
796 else if (Status
== STATUS_TIMEOUT
)
798 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
800 else if (Status
== STATUS_WAIT_0
+ 1)
803 * Crash the system if the initial process was terminated.
805 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
810 InbvEnableBootDriver(FALSE
);
813 NtSetEvent(InitDoneEventHandle
, NULL
);
815 NtClose(InitDoneEventHandle
);
819 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
822 InbvEnableBootDriver(FALSE
);
826 * Crash the system if the initial process terminates within 5 seconds.
828 Timeout
.QuadPart
= (LONGLONG
)-50000000; /* 5 second timeout */
829 Status
= NtWaitForSingleObject(ProcessHandle
,
832 if (Status
!= STATUS_TIMEOUT
)
834 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
838 * Tell ke/timer.c it's okay to run.
841 KiTimerSystemAuditing
= 1;
843 NtClose(ThreadHandle
);
844 NtClose(ProcessHandle
);
847 VOID
__attribute((noinline
))
848 KiSystemStartup(BOOLEAN BootProcessor
)
855 KeApplicationProcessorInit();
858 HalInitializeProcessor(KeNumberProcessors
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
862 ExpInitializeExecutive();
865 PsTerminateSystemThread(STATUS_SUCCESS
);
869 /* Do application processor initialization */
870 PsApplicationProcessorInit();
871 KeLowerIrql(PASSIVE_LEVEL
);
872 PsIdleThreadMain(NULL
);
879 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
881 * FUNCTION: Called by the boot loader to start the kernel
883 * LoaderBlock = Pointer to boot parameters initialized by the boot
885 * NOTE: The boot parameters are stored in low memory which will become
886 * invalid after the memory managment is initialized so we make a local copy.
891 extern ULONG _bss_end__
;
897 * Copy the parameters to a local buffer because lowmem will go away
899 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
900 memcpy(&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
901 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
902 KeLoaderBlock
.ModsCount
++;
903 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
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
;
966 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
968 /* Take this value from the PE... */
970 PIMAGE_NT_HEADERS NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
971 PIMAGE_OPTIONAL_HEADER OptHead
= &NtHeader
->OptionalHeader
;
972 KeLoaderModules
[0].ModEnd
=
973 KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
976 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
979 if ((s
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
981 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
985 strcpy(KeLoaderModuleStrings
[i
], (PCHAR
)KeLoaderModules
[i
].String
);
987 /* TODO: Fix this hardcoded load address stuff... */
988 KeLoaderModules
[i
].ModStart
-= 0x200000;
989 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
990 KeLoaderModules
[i
].ModEnd
-= 0x200000;
991 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
992 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
995 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
997 /* Low level architecture specific initialization */
998 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
1000 HalBase
= KeLoaderModules
[1].ModStart
;
1001 DriverBase
= LastKernelAddress
;
1002 LdrHalBase
= (ULONG_PTR
)DriverBase
;
1004 LdrInitModuleManagement();
1009 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)KERNEL_BASE
, &DriverSize
);
1011 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
1014 * Process ntoskrnl.exe
1016 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
, (PVOID
)KERNEL_BASE
, (PVOID
)DriverBase
, &DriverSize
);
1018 /* Now our imports from HAL are fixed. This is the first */
1019 /* time in the boot process that we can use HAL */
1021 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
1022 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
1024 KeMemoryMapRangeCount
= 0;
1025 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
1027 /* We have a memory map from the nice BIOS */
1028 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
1030 while (i
< KeLoaderBlock
.MmapLength
)
1032 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1033 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
1034 sizeof(ADDRESS_RANGE
));
1035 KeMemoryMapRangeCount
++;
1038 KeLoaderBlock
.MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
1039 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
1043 KeLoaderBlock
.MmapLength
= 0;
1044 KeLoaderBlock
.MmapAddr
= (ULONG
)KeMemoryMap
;
1047 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
1048 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);