2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/init.c
5 * PURPOSE: Executive Initialization Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl (ekohl@rz-online.de)
10 /* INCLUDES ******************************************************************/
14 #include <internal/debug.h>
16 /* DATA **********************************************************************/
18 #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
;
28 /* Init flags and settings */
29 ULONG ExpInitializationPhase
;
30 BOOLEAN ExpInTextModeSetup
;
31 BOOLEAN IoRemoteBootClient
;
32 ULONG InitSafeBootMode
;
33 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
36 UNICODE_STRING NtSystemRoot
;
38 /* NT Initial User Application */
39 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
40 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
42 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
44 /* Boot NLS information */
45 PVOID ExpNlsTableBase
;
46 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
47 ULONG ExpUnicodeCaseTableDataOffset
;
48 NLSTABLEINFO ExpNlsTableInfo
;
49 ULONG ExpNlsTableSize
;
50 PVOID ExpNlsSectionPointer
;
52 /* CMOS Timer Sanity */
53 BOOLEAN ExCmosClockIsSane
= TRUE
;
55 /* FUNCTIONS ****************************************************************/
59 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
61 UNICODE_STRING LinkName
;
62 OBJECT_ATTRIBUTES ObjectAttributes
;
67 ANSI_STRING TargetString
;
68 UNICODE_STRING TargetName
;
70 /* Initialize the ArcName tree */
71 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
72 InitializeObjectAttributes(&ObjectAttributes
,
74 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
76 SePublicDefaultUnrestrictedSd
);
79 Status
= NtCreateDirectoryObject(&LinkHandle
,
82 if (!NT_SUCCESS(Status
))
85 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
88 /* Close the LinkHandle */
91 /* Initialize the Device tree */
92 RtlInitUnicodeString(&LinkName
, L
"\\Device");
93 InitializeObjectAttributes(&ObjectAttributes
,
95 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
97 SePublicDefaultUnrestrictedSd
);
100 Status
= NtCreateDirectoryObject(&LinkHandle
,
101 DIRECTORY_ALL_ACCESS
,
103 if (!NT_SUCCESS(Status
))
106 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
109 /* Close the LinkHandle */
110 ObCloseHandle(LinkHandle
, KernelMode
);
112 /* Create the system root symlink name */
113 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
114 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
115 if (!NT_SUCCESS(Status
))
118 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
121 /* Initialize the attributes for the link */
122 InitializeObjectAttributes(&ObjectAttributes
,
124 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
126 SePublicDefaultUnrestrictedSd
);
128 /* Build the ARC name */
131 LoaderBlock
->ArcBootDeviceName
,
132 LoaderBlock
->NtBootPathName
);
133 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
135 /* Convert it to Unicode */
136 RtlInitString(&TargetString
, Buffer
);
137 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
140 if (!NT_SUCCESS(Status
))
142 /* We failed, bugcheck */
143 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
147 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
148 SYMBOLIC_LINK_ALL_ACCESS
,
152 /* Free the strings */
153 RtlFreeUnicodeString(&LinkName
);
154 RtlFreeUnicodeString(&TargetName
);
156 /* Check if creating the link failed */
157 if (!NT_SUCCESS(Status
))
160 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
163 /* Close the handle and return success */
164 ObCloseHandle(LinkHandle
, KernelMode
);
165 return STATUS_SUCCESS
;
170 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
172 LARGE_INTEGER SectionSize
;
175 PVOID SectionBase
= NULL
;
177 LARGE_INTEGER SectionOffset
= {{0}};
178 PLIST_ENTRY ListHead
, NextEntry
;
179 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
181 /* Check if this is boot-time phase 0 initialization */
182 if (!ExpInitializationPhase
)
184 /* Loop the memory descriptors */
185 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
186 NextEntry
= ListHead
->Flink
;
187 while (NextEntry
!= ListHead
)
189 /* Get the current block */
190 MdBlock
= CONTAINING_RECORD(NextEntry
,
191 MEMORY_ALLOCATION_DESCRIPTOR
,
194 /* Check if this is an NLS block */
195 if (MdBlock
->MemoryType
== LoaderNlsData
)
197 /* Increase the table size */
198 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
201 /* Go to the next block */
202 NextEntry
= MdBlock
->ListEntry
.Flink
;
206 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
207 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
209 ExpNlsTableSize
+= 2 * PAGE_SIZE
; // BIAS FOR FREELDR. HACK!
211 /* Allocate the a new buffer since loader memory will be freed */
212 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
214 TAG('R', 't', 'l', 'i'));
215 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
217 /* Copy the codepage data in its new location. */
218 RtlCopyMemory(ExpNlsTableBase
,
219 LoaderBlock
->NlsData
->AnsiCodePageData
,
222 /* Initialize and reset the NLS TAbles */
223 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
224 ExpAnsiCodePageDataOffset
),
225 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
226 ExpOemCodePageDataOffset
),
227 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
228 ExpUnicodeCaseTableDataOffset
),
230 RtlResetRtlTranslations(&ExpNlsTableInfo
);
234 /* Set the section size */
235 SectionSize
.QuadPart
= ExpNlsTableSize
;
237 /* Create the NLS Section */
238 Status
= ZwCreateSection(&NlsSection
,
245 if (!NT_SUCCESS(Status
))
248 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
251 /* Get a pointer to the section */
252 Status
= ObReferenceObjectByHandle(NlsSection
,
256 &ExpNlsSectionPointer
,
259 if (!NT_SUCCESS(Status
))
262 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
265 /* Map the NLS Section in system space */
266 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
269 if (!NT_SUCCESS(Status
))
272 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
275 /* Copy the codepage data in its new location. */
276 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
278 /* Free the previously allocated buffer and set the new location */
279 ExFreePool(ExpNlsTableBase
);
280 ExpNlsTableBase
= SectionBase
;
282 /* Initialize the NLS Tables */
283 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
284 ExpAnsiCodePageDataOffset
),
285 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
286 ExpOemCodePageDataOffset
),
287 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
288 ExpUnicodeCaseTableDataOffset
),
290 RtlResetRtlTranslations(&ExpNlsTableInfo
);
292 /* Reset the base to 0 */
295 /* Map the section in the system process */
296 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
297 PsGetCurrentProcess(),
306 if (!NT_SUCCESS(Status
))
309 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
312 /* Copy the table into the system process and set this as the base */
313 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
314 ExpNlsTableBase
= SectionBase
;
319 ExpLoadInitialProcess(IN OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation
)
321 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
325 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
326 UNICODE_STRING SmssName
, Environment
, SystemDriveString
;
327 PVOID EnvironmentPtr
= NULL
;
329 /* Allocate memory for the process parameters */
330 Size
= sizeof(RTL_USER_PROCESS_PARAMETERS
) +
331 ((MAX_PATH
* 6) * sizeof(WCHAR
));
332 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
333 (PVOID
)&ProcessParameters
,
338 if (!NT_SUCCESS(Status
))
341 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
344 /* Setup the basic header, and give the process the low 1MB to itself */
345 ProcessParameters
->Length
= Size
;
346 ProcessParameters
->MaximumLength
= Size
;
347 ProcessParameters
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
348 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
350 /* Allocate a page for the environment */
352 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
358 if (!NT_SUCCESS(Status
))
361 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
364 /* Write the pointer */
365 ProcessParameters
->Environment
= EnvironmentPtr
;
367 /* Make a buffer for the DOS path */
368 p
= (PWSTR
)(ProcessParameters
+ 1);
369 ProcessParameters
->CurrentDirectory
.DosPath
.Buffer
= p
;
371 CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
373 /* Copy the DOS path */
374 RtlCopyUnicodeString(&ProcessParameters
->CurrentDirectory
.DosPath
,
377 /* Make a buffer for the DLL Path */
378 p
= (PWSTR
)((PCHAR
)ProcessParameters
->CurrentDirectory
.DosPath
.Buffer
+
379 ProcessParameters
->CurrentDirectory
.DosPath
.MaximumLength
);
380 ProcessParameters
->DllPath
.Buffer
= p
;
381 ProcessParameters
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
383 /* Copy the DLL path and append the system32 directory */
384 RtlCopyUnicodeString(&ProcessParameters
->DllPath
,
385 &ProcessParameters
->CurrentDirectory
.DosPath
);
386 RtlAppendUnicodeToString(&ProcessParameters
->DllPath
, L
"\\System32");
388 /* Make a buffer for the image name */
389 p
= (PWSTR
)((PCHAR
)ProcessParameters
->DllPath
.Buffer
+
390 ProcessParameters
->DllPath
.MaximumLength
);
391 ProcessParameters
->ImagePathName
.Buffer
= p
;
392 ProcessParameters
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
394 /* Make sure the buffer is a valid string which within the given length */
395 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
396 ((NtInitialUserProcessBufferLength
!= -1) &&
397 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
398 (NtInitialUserProcessBufferLength
>
399 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
401 /* Invalid initial process string, bugcheck */
402 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
403 (ULONG_PTR
)STATUS_INVALID_PARAMETER
,
404 NtInitialUserProcessBufferType
,
405 NtInitialUserProcessBufferLength
,
406 sizeof(NtInitialUserProcessBuffer
));
409 /* Cut out anything after a space */
410 p
= NtInitialUserProcessBuffer
;
411 while (*p
&& *p
!= L
' ') p
++;
413 /* Set the image path length */
414 ProcessParameters
->ImagePathName
.Length
=
415 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
417 /* Copy the actual buffer */
418 RtlCopyMemory(ProcessParameters
->ImagePathName
.Buffer
,
419 NtInitialUserProcessBuffer
,
420 ProcessParameters
->ImagePathName
.Length
);
422 /* Null-terminate it */
424 ImagePathName
.Buffer
[ProcessParameters
->ImagePathName
.Length
/
425 sizeof(WCHAR
)] = UNICODE_NULL
;
427 /* Make a buffer for the command line */
428 p
= (PWSTR
)((PCHAR
)ProcessParameters
->ImagePathName
.Buffer
+
429 ProcessParameters
->ImagePathName
.MaximumLength
);
430 ProcessParameters
->CommandLine
.Buffer
= p
;
431 ProcessParameters
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
433 /* Add the image name to the command line */
434 RtlAppendUnicodeToString(&ProcessParameters
->CommandLine
,
435 NtInitialUserProcessBuffer
);
437 /* Create the environment string */
438 RtlInitEmptyUnicodeString(&Environment
,
439 ProcessParameters
->Environment
,
442 /* Append the DLL path to it */
443 RtlAppendUnicodeToString(&Environment
, L
"Path=" );
444 RtlAppendUnicodeStringToString(&Environment
, &ProcessParameters
->DllPath
);
445 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
447 /* Create the system drive string */
448 SystemDriveString
= NtSystemRoot
;
449 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
451 /* Append it to the environment */
452 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
453 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
454 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
456 /* Append the system root to the environment */
457 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
458 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
459 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
461 /* Create SMSS process */
462 SmssName
= ProcessParameters
->ImagePathName
;
463 Status
= RtlCreateUserProcess(&SmssName
,
464 OBJ_CASE_INSENSITIVE
,
465 RtlDeNormalizeProcessParams(
474 if (!NT_SUCCESS(Status
))
477 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
480 /* Resume the thread */
481 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
482 if (!NT_SUCCESS(Status
))
485 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
489 return STATUS_SUCCESS
;
494 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
496 ULONG MsRemainder
= 0, MsIncrement
;
497 ULONG IncrementRemainder
;
500 /* Count the number of milliseconds for each clock interrupt */
501 MsIncrement
= ClockIncrement
/ (10 * 1000);
503 /* Count the remainder from the division above, with 24-bit precision */
504 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
505 for (i
= 0; i
< 24; i
++)
507 /* Shift the remainders */
509 IncrementRemainder
<<= 1;
511 /* Check if we've went past 1 ms */
512 if (IncrementRemainder
>= (10 * 1000))
514 /* Increase the remainder by one, and substract from increment */
515 IncrementRemainder
-= (10 * 1000);
520 /* Return the increment */
521 return (MsIncrement
<< 24) | MsRemainder
;
526 ExpInitSystemPhase0(VOID
)
528 /* Initialize EXRESOURCE Support */
529 ExpResourceInitialization();
531 /* Initialize the environment lock */
532 ExInitializeFastMutex(&ExpEnvironmentLock
);
534 /* Initialize the lookaside lists and locks */
535 ExpInitLookasideLists();
537 /* Initialize the Firmware Table resource and listhead */
538 InitializeListHead(&ExpFirmwareTableProviderListHead
);
539 ExInitializeResourceLite(&ExpFirmwareTableResource
);
541 /* Set the suite mask to maximum and return */
542 ExSuiteMask
= 0xFFFFFFFF;
548 ExpInitSystemPhase1(VOID
)
550 /* Initialize worker threads */
551 ExpInitializeWorkerThreads();
553 /* Initialize pushlocks */
554 ExpInitializePushLocks();
556 /* Initialize events and event pairs */
557 ExpInitializeEventImplementation();
558 ExpInitializeEventPairImplementation();
560 /* Initialize callbacks */
561 ExpInitializeCallbacks();
563 /* Initialize mutants */
564 ExpInitializeMutantImplementation();
566 /* Initialize semaphores */
567 ExpInitializeSemaphoreImplementation();
569 /* Initialize timers */
570 ExpInitializeTimerImplementation();
572 /* Initialize profiling */
573 ExpInitializeProfileImplementation();
575 /* Initialize UUIDs */
578 /* Initialize Win32K */
587 /* Check the initialization phase */
588 switch (ExpInitializationPhase
)
593 return ExpInitSystemPhase0();
598 return ExpInitSystemPhase1();
602 /* Don't know any other phase! Bugcheck! */
603 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
610 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
612 PLOADER_PARAMETER_EXTENSION Extension
;
614 /* Get the loader extension */
615 Extension
= LoaderBlock
->Extension
;
617 /* Validate the size (larger structures are OK, we'll just ignore them) */
618 if (Extension
->Size
< sizeof(LOADER_PARAMETER_EXTENSION
)) return FALSE
;
620 /* Don't validate upper versions */
621 if (Extension
->MajorVersion
> 5) return TRUE
;
623 /* Fail if this is NT 4 */
624 if (Extension
->MajorVersion
< 5) return FALSE
;
626 /* Fail if this is XP */
627 if (Extension
->MinorVersion
< 2) return FALSE
;
629 /* This is 2003 or newer, approve it */
635 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
638 PLIST_ENTRY NextEntry
;
641 PLDR_DATA_TABLE_ENTRY LdrEntry
;
642 BOOLEAN OverFlow
= FALSE
;
643 CHAR NameBuffer
[256];
644 ANSI_STRING SymbolString
;
646 /* Loop the driver list */
647 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
648 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
650 /* Skip the first two images */
654 LdrEntry
= CONTAINING_RECORD(NextEntry
,
655 LDR_DATA_TABLE_ENTRY
,
657 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
659 /* We have a name, read its data */
660 Name
= LdrEntry
->FullDllName
.Buffer
;
661 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
663 /* Check if our buffer can hold it */
664 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
672 for (Count
= 0; Count
< Length
; Count
++, Name
++)
674 /* Copy the character */
675 NameBuffer
[Count
] = (CHAR
)*Name
;
679 NameBuffer
[Count
] = ANSI_NULL
;
684 /* This should be a driver, check if it fits */
685 if (sizeof(NameBuffer
) <
686 (sizeof("\\System32\\Drivers\\") +
687 NtSystemRoot
.Length
/ sizeof(WCHAR
) - sizeof(UNICODE_NULL
) +
688 LdrEntry
->BaseDllName
.Length
/ sizeof(WCHAR
) +
691 /* Buffer too small */
696 /* Otherwise build the name. HACKED for GCC :( */
698 "%c\\System32\\Drivers\\%S",
699 SharedUserData
->NtSystemRoot
[2],
700 LdrEntry
->BaseDllName
.Buffer
);
704 /* Check if the buffer was ok */
707 /* Initialize the ANSI_STRING for the debugger */
708 RtlInitString(&SymbolString
, NameBuffer
);
710 /* Load the symbols */
711 DbgLoadImageSymbols(&SymbolString
,
717 /* Go to the next entry */
719 NextEntry
= NextEntry
->Flink
;
722 /* Check if we should break after symbol load */
723 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
728 ExpInitializeExecutive(IN ULONG Cpu
,
729 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
731 PNLS_DATA_BLOCK NlsData
;
733 ANSI_STRING AnsiPath
;
735 PCHAR CommandLine
, PerfMem
;
738 /* Validate Loader */
739 if (!ExpIsLoaderValid(LoaderBlock
))
741 /* Invalid loader version */
742 KeBugCheckEx(MISMATCHED_HAL
,
744 LoaderBlock
->Extension
->Size
,
745 LoaderBlock
->Extension
->MajorVersion
,
746 LoaderBlock
->Extension
->MinorVersion
);
749 /* Initialize PRCB pool lookaside pointers */
750 ExInitPoolLookasidePointers();
752 /* Check if this is an application CPU */
755 /* Then simply initialize it with HAL */
756 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
758 /* Initialization failed */
759 KeBugCheck(HAL_INITIALIZATION_FAILED
);
766 /* Assume no text-mode or remote boot */
767 ExpInTextModeSetup
= FALSE
;
768 IoRemoteBootClient
= FALSE
;
770 /* Check if we have a setup loader block */
771 if (LoaderBlock
->SetupLdrBlock
)
773 /* Check if this is text-mode setup */
774 if (LoaderBlock
->SetupLdrBlock
->Flags
& 1) ExpInTextModeSetup
= TRUE
;
776 /* Check if this is network boot */
777 if (LoaderBlock
->SetupLdrBlock
->Flags
& 2)
780 IoRemoteBootClient
= TRUE
;
782 /* Make sure we're actually booting off the network */
783 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
788 ExpInitializationPhase
= 0;
790 /* Get boot command line */
791 CommandLine
= LoaderBlock
->LoadOptions
;
794 /* Upcase it for comparison and check if we're in performance mode */
795 _strupr(CommandLine
);
796 PerfMem
= strstr(CommandLine
, "PERFMEM");
799 /* Check if the user gave a number of bytes to use */
800 PerfMem
= strstr(PerfMem
, "=");
803 /* Read the number of pages we'll use */
804 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
808 DPRINT1("BBT performance mode not yet supported."
809 "/PERFMEM option ignored.\n");
814 /* Check if we're burning memory */
815 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
818 /* Check if the user gave a number of bytes to use */
819 PerfMem
= strstr(PerfMem
, "=");
822 /* Read the number of pages we'll use */
823 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
827 DPRINT1("Burnable memory support not yet present."
828 "/BURNMEM option ignored.\n");
834 /* Setup NLS Base and offsets */
835 NlsData
= LoaderBlock
->NlsData
;
836 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
837 ExpAnsiCodePageDataOffset
= 0;
838 ExpOemCodePageDataOffset
= ((ULONG_PTR
)NlsData
->OemCodePageData
-
839 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
840 ExpUnicodeCaseTableDataOffset
= ((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
841 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
843 /* Initialize the NLS Tables */
844 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
845 ExpAnsiCodePageDataOffset
),
846 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
847 ExpOemCodePageDataOffset
),
848 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
849 ExpUnicodeCaseTableDataOffset
),
851 RtlResetRtlTranslations(&ExpNlsTableInfo
);
853 /* Now initialize the HAL */
854 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
856 /* HAL failed to initialize, bugcheck */
857 KeBugCheck(HAL_INITIALIZATION_FAILED
);
860 /* Make sure interrupts are active now */
863 /* Clear the crypto exponent */
864 SharedUserData
->CryptoExponent
= 0;
866 /* Set global flags for the checked build */
868 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
869 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
872 /* Setup NT System Root Path */
873 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
875 /* Convert to ANSI_STRING and null-terminate it */
876 RtlInitString(&AnsiPath
, Buffer
);
877 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
879 /* Get the string from KUSER_SHARED_DATA's buffer */
880 RtlInitEmptyUnicodeString(&NtSystemRoot
,
881 SharedUserData
->NtSystemRoot
,
882 sizeof(SharedUserData
->NtSystemRoot
));
885 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
886 if (!NT_SUCCESS(Status
)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED
);
888 /* Setup bugcheck messages */
889 KiInitializeBugCheck();
891 /* Setup initial system settings (FIXME: Needs Cm Rewrite) */
892 //CmGetSystemControlValues(CommandLine, &CmControlVector);
894 /* Initialize the executive at phase 0 */
895 if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED
);
897 /* Load boot symbols */
898 ExpLoadBootSymbols(LoaderBlock
);
900 /* Set system ranges */
901 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
902 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
904 /* Make a copy of the NLS Tables */
905 ExpInitNls(LoaderBlock
);
907 /* Check if the user wants a kernel stack trace database */
908 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
911 DPRINT1("Kernel-mode stack trace support not yet present."
912 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
915 /* Check if he wanted exception logging */
916 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
919 DPRINT1("Kernel-mode exception logging support not yet present."
920 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
923 /* Initialize the Handle Table */
924 ExpInitializeHandleTables();
927 /* On checked builds, allocate the system call count table */
928 KeServiceDescriptorTable
[0].Count
=
929 ExAllocatePoolWithTag(NonPagedPool
,
930 KiServiceLimit
* sizeof(ULONG
),
931 TAG('C', 'a', 'l', 'l'));
933 /* Use it for the shadow table too */
934 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
936 /* Make sure allocation succeeded */
937 if (KeServiceDescriptorTable
[0].Count
)
939 /* Zero the call counts to 0 */
940 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
941 KiServiceLimit
* sizeof(ULONG
));
945 /* Create the Basic Object Manager Types to allow new Object Types */
946 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED
);
948 /* Load basic Security for other Managers */
949 if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
951 /* Initialize the Process Manager */
952 if (!PsInitSystem(LoaderBlock
)) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED
);
954 /* Initialize the PnP Manager */
955 if (!PpInitSystem()) KEBUGCHECK(PP0_INITIALIZATION_FAILED
);
957 /* Initialize the User-Mode Debugging Subsystem */
960 /* Calculate the tick count multiplier */
961 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
962 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
964 /* Set the OS Version */
965 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
966 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
968 /* Set the machine type */
970 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_I386
;
971 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_I386
;
972 #elif defined(_PPC_) // <3 Arty
973 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_POWERPC
;
974 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_POWERPC
;
976 #error "Unsupported ReactOS Target"
982 Phase1InitializationDiscard(PVOID Context
)
984 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
985 PCHAR CommandLine
, Y2KHackRequired
;
986 LARGE_INTEGER Timeout
;
988 TIME_FIELDS TimeFields
;
989 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
;
990 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
991 BOOLEAN SosEnabled
, NoGuiBoot
;
994 /* Allocate initial process information */
995 ProcessInfo
= ExAllocatePoolWithTag(NonPagedPool
,
996 sizeof(RTL_USER_PROCESS_INFORMATION
),
997 TAG('I', 'n', 'i', 't'));
1001 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1004 /* Set to phase 1 */
1005 ExpInitializationPhase
= 1;
1007 /* Set us at maximum priority */
1008 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1010 /* Do Phase 1 HAL Initialization */
1011 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1013 /* Get the command line and upcase it */
1014 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
1016 /* Check if GUI Boot is enabled */
1017 NoGuiBoot
= (strstr(CommandLine
, "NOGUIBOOT")) ? TRUE
: FALSE
;
1019 /* Get the SOS setting */
1020 SosEnabled
= strstr(CommandLine
, "SOS") ? TRUE
: FALSE
;
1022 /* Setup the boot driver */
1023 InbvDisplayInitialize();
1024 if (!ExpInTextModeSetup
) InbvDisplayInitialize2(NoGuiBoot
);
1026 /* Check if GUI boot is enabled */
1029 /* It is, display the boot logo and enable printing strings */
1030 InbvEnableDisplayString(SosEnabled
);
1031 InbvDisplayBootLogo(SosEnabled
);
1035 /* Release display ownership if not using GUI boot */
1036 if (!SosEnabled
) InbvNotifyDisplayOwnershipLost(NULL
);
1038 /* Don't allow boot-time strings */
1039 InbvEnableDisplayString(FALSE
);
1042 /* Check if this is LiveCD (WinPE) mode */
1043 if (strstr(CommandLine
, "MININT"))
1045 /* Setup WinPE Settings */
1046 InitIsWinPEMode
= TRUE
;
1047 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM")) ? 0x80000000 : 1;
1050 /* FIXME: Print product name, version, and build */
1052 /* Initialize Power Subsystem in Phase 0 */
1053 if (!PoInitSystem(0, AcpiTableDetected
)) KeBugCheck(INTERNAL_POWER_ERROR
);
1055 /* Check for Y2K hack */
1056 Y2KHackRequired
= strstr(CommandLine
, "YEAR");
1057 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1058 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1060 /* Query the clock */
1061 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1063 /* Check if we're using the Y2K hack */
1064 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1066 /* Convert to time fields */
1067 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1068 UniversalBootTime
= SystemBootTime
;
1070 #if 0 // FIXME: Won't work until we can read registry data here
1071 /* FIXME: This assumes that the RTC is not already in GMT */
1072 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1075 /* Set the boot time-zone bias */
1076 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1077 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1078 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1080 /* Convert the boot time to local time, and set it */
1081 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1082 ExpTimeZoneBias
.QuadPart
;
1085 /* Update the system time */
1086 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1088 /* Remember this as the boot time */
1089 KeBootTime
= UniversalBootTime
;
1093 /* Initialize all processors */
1094 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1096 /* FIXME: Print CPU and Memory */
1098 /* Update the progress bar */
1099 InbvUpdateProgressBar(5);
1101 /* Call OB initialization again */
1102 if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1104 /* Initialize Basic System Objects and Worker Threads */
1105 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1107 /* Initialize the later stages of the kernel */
1108 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1110 /* Call KD Providers at Phase 1 */
1111 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1113 /* Failed, bugcheck */
1114 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1117 /* Initialize the SRM in Phase 1 */
1118 if (!SeInit()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
1120 /* Update the progress bar */
1121 InbvUpdateProgressBar(10);
1123 /* Create SystemRoot Link */
1124 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1125 if (!NT_SUCCESS(Status
))
1127 /* Failed to create the system root link */
1128 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1131 /* Set up Region Maps, Sections and the Paging File */
1132 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1134 /* Create NLS section */
1135 ExpInitNls(KeLoaderBlock
);
1137 /* Initialize Cache Views */
1138 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1140 /* Initialize the Registry */
1141 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1143 /* Update progress bar */
1144 InbvUpdateProgressBar(15);
1146 /* Update timezone information */
1147 ExRefreshTimeZoneInformation(&SystemBootTime
);
1149 /* Initialize the File System Runtime Library */
1150 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1152 /* Report all resources used by HAL */
1153 HalReportResourceUsage();
1155 /* Call the debugger DLL once we have KD64 6.0 support */
1156 //KdDebuggerInitialize1(LoaderBlock);
1158 /* Setup PnP Manager in phase 1 */
1159 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1161 /* Update progress bar */
1162 InbvUpdateProgressBar(20);
1164 /* Initialize LPC */
1165 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1167 /* Initialize the I/O Subsystem */
1168 if (!IoInitSystem(KeLoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1170 /* Unmap Low memory, and initialize the MPW and Balancer Thread */
1171 MmInitSystem(2, LoaderBlock
);
1173 /* Update progress bar */
1174 InbvUpdateProgressBar(80);
1176 /* Initialize VDM support */
1177 KeI386VdmInitialize();
1179 /* Initialize Power Subsystem in Phase 1*/
1180 if (!PoInitSystem(1, AcpiTableDetected
)) KeBugCheck(INTERNAL_POWER_ERROR
);
1182 /* Initialize the Process Manager at Phase 1 */
1183 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1185 /* Update progress bar */
1186 InbvUpdateProgressBar(85);
1188 /* Make sure nobody touches the loader block again */
1189 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1190 LoaderBlock
= Context
= NULL
;
1192 /* Update progress bar */
1193 InbvUpdateProgressBar(90);
1195 /* Launch initial process */
1196 Status
= ExpLoadInitialProcess(ProcessInfo
);
1198 /* Update progress bar */
1199 InbvUpdateProgressBar(100);
1201 /* Allow strings to be displayed */
1202 InbvEnableDisplayString(TRUE
);
1204 /* Wait 5 seconds for it to initialize */
1205 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1206 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1207 if (!NoGuiBoot
) InbvFinalizeBootLogo();
1208 if (Status
== STATUS_SUCCESS
)
1210 /* Bugcheck the system if SMSS couldn't initialize */
1211 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1214 /* Close process handles */
1215 ZwClose(ProcessInfo
->ThreadHandle
);
1216 ZwClose(ProcessInfo
->ProcessHandle
);
1218 /* FIXME: We should free the initial process' memory!*/
1220 /* Increase init phase */
1221 ExpInitializationPhase
+= 1;
1223 /* Free the process information */
1224 ExFreePool(ProcessInfo
);
1229 Phase1Initialization(IN PVOID Context
)
1231 /* Do the .INIT part of Phase 1 which we can free later */
1232 Phase1InitializationDiscard(Context
);
1234 /* Jump into zero page thread */
1235 MmZeroPageThreadMain(NULL
);