When Winload calls Ntoskrnl, it passes a data structure called the loader parameter block that contains the system and boot partition paths, a pointer to the memory tables Winload generated to describe the physical memory on the system, a pointer to the in-memory copy of the HARDWARE and SYSTEM registry hives, a pointer to the list of boot drivers Winload loaded, as well as various other information related to the boot processing performed until this point.
Ntoskrnl then begins the first of its two-phase initialization process, called phase 0 and phase 1. Most executive subsystems have an initialization function that takes a parameter that identifies which phase is executing.
During phase 0, interrupts are disabled. The purpose of this phase is to build the rudimentary structures required to allow the services needed in phase 1 to be invoked. Ntoskrnl’s main function calls KiSystemStartup, which in turn calls HalInitializeProcessor and KiInitializeKernel for each CPU. KiInitializeKernel, if running on the boot CPU, performs systemwide kernel initialization, such as initializing internal lists and other data structures that all CPUs share. It also checks whether virtualization was specified as a BCD option (hypervisorlaunchtype),
and whether the CPU supports hardware virtualization technology. The first instance of KiInitializeKernel then calls the function responsible for orchestrating phase 0, InitBootProcessor, while subsequent processors only call HalInitSystem.
InitBootProcessor starts by initializing the pool look-aside pointers for the initial CPU and by checking for and honoring the BCD burnmemory boot option, where it discards the amount of physical memory the value specifies. It then performs enough initialization of the NLS files that were loaded by Winload (described earlier) to allow Unicode to ANSI and OEM translation to work. Next, it continues by calling the HAL function HalInitSystem, which gives the HAL a chance to gain system control before Windows performs significant further initialization. One responsibility of HalInitSystem is to prepare the system interrupt controller of each CPU for interrupts and to configure the interval clock timer interrupt, which is used for CPU time accounting.
When HalInitSystem returns control, InitBootProcessor proceeds by computing the reciprocal for timer expiration. Reciprocals are used for optimizing divisions on most modern processors. They can perform multiplications faster, and because Windows must divide the current 64-bit time value in order to find out which timers need to expire, this static calculation reduces interrupt latency when the clock interval fires. InitBootProcessor then continues by setting up the system root path and searching the kernel image for the location of the crash message strings it displays on blue screens, caching their location to avoid looking up the strings during a crash, which could be dangerous and unreliable. Next, InitBootProcessor initializes the quota functionality part of the process manager and reads the control vector.
This data structure contains more than 150 kernel-tuning options that are part of the HKLM\SYSTEM\CurrentControlSet\Control registry key, including information such as the licensing data and version information for the installation.
InitBootProcessor is now ready to call the phase 0 initialization routines for the executive, Driver Verifier, and memory manager. These components perform the following initialization steps:
1. The executive initializes various internal locks, resources, lists, and variables and validates that the product suite type in the registry is valid, discouraging casual modification of the registry in order to “upgrade” to a SKU of Windows that was not actually purchased. This is only one of the many such checks in the kernel.
2. The Driver Verifier, if enabled, initializes various settings and behaviors based on the current state of the system (such as whether safe mode is enabled) and verification options. It also picks which drivers to target for tests that target randomly chosen drivers.
3. The memory manager constructs page tables and internal data structures that are necessary to provide basic memory services. It also builds and reserves an area for the system file cache and creates memory areas for the paged and nonpaged pools. The other executive subsystems, the kernel, and device drivers use these two memory pools for allocating their data structures.
Next, InitBootProcessor calls HalInitializeBios to set up the BIOS emulation code part of the HAL. This code is used both on real BIOS systems, as well as on EFI systems, to allow access (or to emulate access) to 16-bit real mode interrupts and memory, which are used mainly by Bootvid to display the early VGA boot screen and bugcheck screen. After the function returns, the kernel initializes the Bootvid library and displays early boot status messages by calling InbvEnableBootDriver and InbvDriverInitailize.
At this point, InitBootProcessor enumerates the boot-start drivers that were loaded by Winload and calls DbgLoadImageSymbols to inform the kernel debugger (if attached) to load symbols for each of these drivers. If the host debugger has configured the break on symbol load option, this will be the earliest point for a kernel debugger to gain control of the system. InitBootProcessor now calls HvlInitSystem, which attempts to connect to the hypervisor in case Windows might be running inside a Hyper-V host system’s child partition. When the function returns, it calls HeadlessInit to initialize the serial console if the machine was configured for Emergency Management Services (EMS).
Next, InitBootProcessor builds the versioning information that will be used later in the boot process, such as the build number, service pack version, and beta version status. Then it copies the NLS tables that Winload previously loaded into paged pool, reinitializes them, and creates the kernel stack trace database if the global flags specify creating one.
Finally, InitBootProcessor calls the object manager, security reference monitor, process manager, user-mode debugging framework, and the Plug and Play manager. These components perform the following initialization steps:
1. During the object manager initialization, the objects that are necessary to construct the object manager namespace are defined so that other subsystems can insert objects into it. A handle table is created so that resource tracking can begin.
2. The security reference monitor initializes the token type object and then uses the object to create and prepare the first local system account token for assignment to the initial process.
3. The process manager performs most of its initialization in phase 0, defining the process and thread object types and setting up lists to track active processes and threads. The process manager also creates a process object for the initial process and names it Idle. As its last step, the process manager creates the System process and a system thread to execute the routine Phase1Initialization. This thread doesn’t start running right away because interrupts are still disabled.
4. The user-mode debugging framework creates the definition of the debug object type that is used for attaching a debugger to a process and receiving debugger events.
5. The Plug and Play manager’s phase 0 initialization then takes place, which involves simply initializing an executive resource used to synchronize bus resources.
When control returns to KiInitializeKernel, the last step is to allocate the DPC stack for the current processor and the I/O privilege map save area (on x86 systems only), after which control proceeds to the Idle loop, which then causes the system thread created in step 3 of the previous process description to begin executing phase 1. (Secondary processors wait to begin their initialization until step 8 of phase 1, described in the following list.)
Phase 1 consists of the following steps:
1. Phase1InitializationDiscard, which, as the name implies, discards the code that is part of the INIT section of the kernel image in order to preserve memory.
2. The initialization thread sets its priority to 31, the highest possible, in order to prevent preemption.
3. HalInitSystem prepares the system to accept interrupts from devices and to enable interrupts.
4. The boot video driver is called, which in turn displays the Windows startup screen, which by default consists of a black screen and a progress bar. If the quietboot boot option was used, this step will not occur.
5. The kernel builds various strings and version information, which are displayed on the boot screen through Bootvid if the sos boot option was enabled. This includes the full version information, number of processors supported, and amount of memory supported.
6. The power manager’s initialization is called.
7. The system time is initialized (by calling HalQueryRealTimeClock) and then stored as the time the system booted.
8. On a multiprocessor system, the remaining processors are initialized by KeStartAllProcessors and HalAllProcessorsStarted. The number of processors that will be initialized and supported depends on a combination of the actual physical count, the licensing information for the installed SKU of Windows, boot options such as numproc and onecpu, and whether dynamic partitioning is enabled (Windows Server 2008 systems only). After all the available processors have initialized, the affinity of the system process is updated to include all processors.
9. The object manager creates the namespace root directory (\), \ObjectTypes directory,
and the DOS device name mapping directory (\Global??). It then creates the
\DosDevices symbolic link that points at the Windows subsystem device name mapping directory.
10. The executive is called to create the executive object types, including semaphore, mutex, event, and timer.
11. The I/O manager is called to create the I/O manager object types, including device,
driver, controller, adapter, and file objects.
12. The kernel debugger library finalizes initialization of debugging settings and parameters if the debugger has not been triggered prior to this point.
13. The transaction manager also creates its object types, such as the enlistment, resource manager, and transaction manager types.
14. The kernel initializes scheduler (dispatcher) data structures and the system service dispatch table.
15. If the Driver Verifier is enabled and, depending on verification options, pool verification is enabled, object handle tracing is started for the system process.
16. The security reference monitor creates the \Security directory in the object manager namespace and initializes auditing data structures if auditing is enabled.
17. The memory manager is called to create the section object and the memory manager’s system worker threads.
18. NLS tables are mapped into system space so that they can be easily mapped by usermode processes.
19. Ntdll.dll is mapped into the system address space.
20. The cache manager initializes the file system cache data structures and creates its worker threads.
21. The configuration manager creates the \Registry key object in the object manager namespace and copies the initial registry data passed by Winload into the HARDWARE and SYSTEM hives.
22. The errata manager initializes and scans the registry for errata information, as well as the INF database containing errata for various drivers.
23. SuperFetch and the prefetcher are initialized.
24. The current time zone information is initialized.
25. Global file system driver data structures are initialized.
26. Phase 1 of debugger-transport-specific information is performed by calling the KdDebuggerInitialize1 routine in the registered transport, such as Kdcom.dll.
27. The Plug and Play manager calls the Plug and Play BIOS.
28. The advanced local procedure call (ALPC) subsystem initializes the ALPC port type and ALPC waitable port type objects. The older LPC objects are set as aliases.
29. If the system was booted with boot logging (with the BCD bootlog option), the boot log file is initialized. If the system was booted in safe mode, a string is displayed on the boot screen with the current safe mode boot type.
30. The executive is called to execute its second initialization phase, where it configures part of the Windows licensing functionality in the kernel, such as validating the registry settings that hold license data. Also, if persistent data from boot applications is present (such as memory diagnostic results or resume from hibernation information), the relevant log files and information are written to disk or to the registry.
31. The MiniNT/WinPE registry keys are created if this is such a boot, and the NLS object directory is created in the namespace, which will be used later to host the section objects for the various memory-mapped NLS files.
32. The I/O manager initialization now takes place. This stage is a complex phase of system startup that accounts for most of the boot time.
The I/O manager first initializes various internal structures and creates the driver and device object types. It then calls the Plug and Play manager, power manager, and HAL to begin the various stages of dynamic device enumeration and initialization. Then the Windows Management Instrumentation (WMI) subsystem is initialized, which provides WMI support for device drivers. This also initializes Event Tracing for Windows (ETW). Next, all the boot-start drivers are called to perform their driver-specific initialization, and then the system-start device drivers are loaded and initialized. Finally, the Windows subsystem device names are created as symbolic links in the object manager’s namespace.
33. The transaction manager sets up the Windows software trace preprocessor (WPP) and ETW and initializes with WMI.
34. Now that boot-start and system-start drivers are loaded, the errata manager loads the
INF database with the driver errata and begins parsing it, which includes applying registry PCI configuration workarounds.
35. If the computer is booting in safe mode, this fact is recorded in the registry.
36. Unless explicitly disabled in the registry, paging of kernel-mode code (in Ntoskrnl and drivers) is enabled.
37. The configuration manager makes sure that all processors on an SMP system are identical in terms of the features that they support; otherwise, it crashes the system.
38. On 32-bit systems, VDM (Virtual Dos Machine) support is initialized, which includes determining whether the processor supports Virtual Machine Extensions (VME).
39. The process manager is called to set up rate limiting for jobs, initialize the static environment for protected processes, and look up the various system-defined entry points in the user-mode system library (Ntdll.dll).
40. The power manager is called to initialize various power management structures.
41. The rest of the licensing information for the system is initialized, including caching the current policy settings stored in the registry.
42. The security reference monitor is called to create the Command Server Thread that communicates with Lsass.
43. The Session Manager (Smss) process is started. Smss is responsible for creating the user-mode environment that provides the visible interface to Windows—its initialization steps are covered in the next section.
44. All the memory used up by the loader parameter block and all its references is now freed.
As a final step before considering the executive and kernel initialization complete, the phase 1 initialization thread waits for the handle to the Session Manager process with a timeout value of 5 seconds. If the Session Manager process exits before the 5 seconds elapse, the system crashes with a SESSION5_INITIALIZATION_FAILED stop code.
If the 5-second wait times out (that is, if 5 seconds elapse), the Session Manager is assumed to have started successfully, and the phase 1 initialization function calls the memory manager’s zero page thread function. Thus, this system thread becomes the zero page thread for the remainder of the life of the system.
Source of Information : Microsoft Press Windows Internals 5th Edition