Understand NT's initialization sequence

The boot process is the first of three major phases Windows NT goes through during one cycle of normal operation. The other phases are normal operation and shutdown. Although this column and other articles in Windows NT Magazine have extensively covered the details of NT's policies and mechanisms during normal operation, the boot process is not usually covered in depth (for a selection of these articles, see "Related Articles in Windows NT Magazine"). Even Microsoft's literature on the boot process, including Microsoft Windows NT Server 4.0 Resource Kit and Microsoft Windows NT Device Driver Kit, glosses over the details and presents a somewhat inaccurate picture of the steps NT goes through during a boot.

This month, I will begin a detailed tour through the NT boot process. I'll start at the point at which you install NT and proceed through the way NTLDR and NTDETECT execute. Device drivers are a crucial part of the boot process, so I'll present the way they control where in the boot they load and initialize. Next time, I'll describe how the Executive subsystems initialize, and then I'll show you how the Kernel launches the user-mode portion of NT by starting the Session Manager process, the Win32 subsystem, and the logon process. Along the way, I'll highlight the points at which various text appears on the screen to help you correlate the internal process with what you see when you watch NT boot.

Preboot
The NT boot process doesn't begin when you power on your computer or press the reset key. It begins when you install NT on your computer. At some point during the execution of NT's Setup program, NT prepares the system's primary hard disk with code that takes part in the boot process. Before I discuss what this code does, let me explain how and where NT places it on a disk. Since the early days of DOS, a standard has existed on x86 systems for the way physical hard disks are divided into logical disks. Microsoft operating systems (OSs) split hard disks into discrete areas known as partitions and use file systems (e.g., FAT, NTFS) to format each partition to be a logical drive. A hard disk can contain up to four primary partitions. Because this apportioning scheme would otherwise limit a disk to four logical drives, a special partition type, called an extended partition, further allocates up to four additional partitions within the primary partitions. Extended partitions can include extended partitions, which can contain extended partitions, and so on, making the number of drives an OS can place on a disk effectively infinite. Figure 1, page 60, gives an example of a hard disk layout.

Physical disks are addressed in units known as sectors. A hard-disk sector on an IBM-compatible PC is 512 bytes (sectors can be 1024 bytes on Alpha systems). Utilities that prepare hard disks for the definition of logical drives, including the DOS FDISK utility or the NT Setup program, write a sector of data called a Master Boot Record (MBR) to the first sector on a hard disk. The MBR includes a fixed amount of space that contains executable instructions and a table with four entries that define the locations of the primary partitions on the disk. When IBM-compatible computers boot, the first code they execute is called the BIOS, which is encoded into the computers' ROM. The BIOS reads the MBR off the first sector of a hard disk into memory and transfers control to the code in the MBR.

The MBRs that Microsoft partitioning tools write go through a similar process. First, an MBR's code scans through the primary partition table and locates the first partition with a flag that signals the partition is bootable. When the MBR finds at least one such flag, it reads the first sector from the flagged partition into memory and transfers control to code within the partition. The first sector of such a defined partition is called a boot sector.

OSs generally write boot sectors to disks without a user's involvement. For example, when NT Setup writes the MBR to a hard disk, it also writes a boot record to the first bootable partition of the disk. If you're familiar with the DOS SYS command, you've probably used it to manually write DOS boot sectors to disks. NT Setup checks to see whether the boot sector it will overwrite with an NT boot sector is a valid DOS boot sector. If the boot sector is a valid DOS boot sector, NT Setup copies the boot sector's contents to a file named bootsect.dos in the root directory of the partition. I'll discuss the role bootsect.dos plays in dual-boot environments shortly.

Before writing a partition's boot sector, NT Setup ensures that the partition is formatted with a file system that NT supports, such as FAT and NTFS (NT 5.0 will also support FAT32). NT Setup formats the boot partition--and any other partition with a file system type you specify. If partitions are already formatted, you can instruct Setup to leave them alone. After Setup formats the boot partition, setup copies the files NT uses to the logical drive, including two files that are part of the boot sequence, NTLDR and ntdetect.com.

Another of Setup's roles is to create a boot menu file, boot.ini, in the root directory of the boot partition. This file contains options for starting the version of NT that Setup installs and any preexisting NT installations. If bootsect.dos contains a valid DOS boot sector, one of the entries boot.ini creates is to boot into DOS. Listing 1 shows an example boot.ini file from a dual-boot computer on which DOS is installed before NT.

The Boot Sector and NTLDR
Setup must know the partition format before it writes a boot sector, because the contents of the boot sector depend on the format. For example, if the boot partition is a FAT partition, NT writes code to the boot sector that understands the FAT file system. But if the partition is in NTFS format, NT writes NTFS-capable code. The role of the boot-sector code is to give NT information about the structure and format of a logical drive, and to read in the NTLDR file from the root directory of the logical drive. Thus, the boot-sector code contains just enough read-only file system code to accomplish this task. After the boot sector code loads NTLDR into memory, it transfers control to NTLDR's entry point. If the boot sector code can't find NTLDR in the boot partition's root directory, the boot sector code prints the error message BOOT: Couldn't find NTLDR if the boot file system is FAT, or A kernel file is missing from the disk if the file system is NTFS.

NTLDR begins its existence while a system is executing in an x86-operating mode called Real-Mode. In Real-Mode, no virtual to physical translation of memory addresses occurs, which means that programs that use the addresses interpret them as physical addresses, and only the first 640KB of the computer's physical memory is accessible. Simple DOS programs execute in a Real-Mode environment. However, the first action NTLDR takes is to switch the system to Protected-Mode. Still no virtual-to-physical translation occurs at this point in the boot process, but a full 32 bits of memory becomes accessible. After it is in Protected-Mode, NTLDR can access all of physical memory. After creating enough page tables to make memory below 1MB accessible with paging turned on, NTLDR enables paging. Protected-Mode with paging enabled is the mode in which NT executes in normal operation. (For information about paging and page tables, see "Inside Memory Management, Part 1," August 1998.)

After NTLDR enables paging, NTLDR is fully operational. It next reads the boot.ini file from the root directory using built-in file-system code. Like the boot sector's code, NTLDR contains read-only NTFS and FAT code; unlike the boot sector's code, NTLDR's file- system code can read subdirectories. NTLDR clears the screen and presents the user with the boot selection menu. If the user doesn't select an entry within the timeout period the boot.ini file specifies, NTLDR chooses a default selection. A boot.ini line directs NTLDR to the partition on which the NT system directory () of the selected installation resides. This partition might be the same as the boot partition, or it might be another primary partition.

If the boot.ini line refers to a DOS installation (i.e., by referring to C:\ as the system partition), NTLDR reads the contents of the bootsect.dos file into memory and executes a warm reboot. This action causes the code to execute after the computer reinitializes as if the MBR had read the code from disk. Code in bootsect.dos continues a DOS-specific boot, such as one into Windows 98 or Win95 on a computer on which these OSs are installed with NT.

A line in boot.ini can include option arguments that NTLDR and other components involved in the boot process interpret. Table 1, page 62, shows a complete list of these options and their effects. If the /MAXMEM= argument is present in the boot selection a system's user chooses, NTLDR discards the amount of memory specified in the internal tables it uses to keep track of physical memory allocations. Options such as /MAXMEM= are useful for device-driver developers who want to stress their drivers under various operating conditions.

NTLDR next loads and executes the ntdetect.com program, which prints a message to the screen such as NTDETECT V4.0 Checking Hardware. Ntdetect.com is a standard DOS-style program that uses a system's BIOS to query the computer for basic device and configuration information. This information includes the time and date information stored in the system's CMOS (nonvolatile memory); the types of buses (e.g., ISA, PCI, EISA, Micro Channel Architecture--MCA) on the system and identifiers for devices attached to the buses; the number, size, and type of disk drives on the system; the types of mouse input devices connected to the system; and the number and type of parallel ports configured on the system. This information is gathered into internal data structures that will become the HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION Registry key later in the boot.

NTLDR clears the screen and prints its version information: OSLOADER V4.0. The first two files that NTLDR loads make up NT's core: ntoskrnl.exe and hal.dll. Both files are located in the \system32 directory. Ntoskrnl.exe contains the Kernel and Executive subsystems (e.g., Memory Manager, Cache Manager, Object Manager), and hal.dll contains code that interfaces NT to the computer hardware. Hardware abstraction layers (HALs) can provide interfaces to proprietary hardware, so Microsoft makes it possible for OEMs to supply custom HAL files. If NTLDR fails to load either of these files, it prints the message Windows NT could not start because the following file was missing or corrupt, followed by the name of the file.

Now the user has the option to select the Last Known Good configuration by pressing the spacebar. After a successful boot completes, NT makes a copy of the Registry tree that contains static and dynamic system and driver configuration information, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet, and marks it as the Last Known Good configuration. Because device drivers load based on information under the Services Registry key, this key is especially crucial. If a driver installs and at the next reboot prevents the system from starting, when the user selects the Last Known Good configuration, NT reverts to using the copy of the Registry tree that existed before the driver installed. Because the good copy does not include commands to load the driver, a boot using that copy will likely succeed.

After the user selects the Last Known Good configuration or a timeout of a few seconds expires, NTLDR proceeds to read in the HKEY_LOCAL_MACHINE\SYSTEM Registry hive (a hive is a file that contains a Registry subtree) that is located at \system32\config\system. NTLDR splices the hardware configuration information it gathered earlier into the in-memory image of the SYSTEM Registry key, then NTLDR begins to load other files necessary for the boot.

The next files NTLDR loads are device drivers that function as boot drivers. Every device driver has a Registry subkey under HKEY_LOCAL_MACHINE\SYSTEM\Services. For example, NTFS has a subkey named Ntfs, which Screen 1 shows. A driver's subkey contains several values that NT examines when it determines when to load the driver. The value with the most general effect on the driver's load time is that driver's Start value. A Start value can have one of five possible settings, which Table 2, page 66, shows. NTLDR scans the in-memory Registry image and locates all drivers that have Start values of SERVICE_BOOT_START (Boot Start) and loads them into memory. NTLDR also loads the file system driver responsible for implementing the code for the file system's type of partition, on which the installation directory resides (FAT or NTFS). NTLDR must load these drivers at this time because otherwise the Kernel would require the drivers to load themselves, a requirement that introduces a circular dependency. Boot drivers include the disk drivers for the system partition. NTLDR prints a period to the screen for every file it loads, unless the /SOS switch is specified in the boot.ini selection, in which case NTLDR displays the filenames. Note that the drivers are loaded but not initialized at this time—they initialize later in the boot sequence.

This action is the end of NTLDR's role in the boot. After preparing processor registers for the Kernel, NTLDR locates the main function in ntoskrnl.exe's in-memory image and transfers control to ntoskrnl.exe. The sole parameter NTLDR passes to the Kernel is a data structure relating to the information NTLDR gathered during its execution. This data structure contains a copy of the line in boot.ini NTLDR selected, a pointer to the memory tables NTLDR generated to describe the physical memory on the system, a pointer to the in-memory HKEY_LOCAL_MACHINE Registry tree (which contains the HARDWARE and SYSTEM subkeys), and a pointer to the list of boot drivers NTLDR loaded.

The process I've described to this point pertains to x86 systems and is only partially applicable to Alpha systems. On an Alpha, the MBR does not contain boot codes. Instead, the Alpha firmware plays an active role in the boot. (Advanced RISC Consortium—ARC—defined functionality in the firmware of RISC computers.) NT Setup programs Alpha firmware to contain the boot menu entries that boot.ini contains on x86 systems. The programmed firmware code understands how to read FAT drives, so that when a user makes a boot selection, the firmware reads the boot partition to load osloader.exe, Alpha's equivalent of NTLDR. The firmware also loads the HAL from the boot partition, rather than from the NT installation directory (where the HAL resides on x86 systems), and reads in a PAL file. A PAL file contains code that NT uses to interface to a specific Alpha machine's microcode. The Alpha firmware doesn't understand NTFS drives, which is why you must create a minimal FAT partition on Alphas to contain osloader.exe and the HAL and PAL code. OSLOADER performs the same steps on Alphas as NTLDR performs on x86 systems, but OSLOADER has no ntdetect.com. Instead, the Alpha firmware's code performs detection and hands the information to OSLOADER after it loads.

Stay Tuned
Next time, I'll pick up where I've left off and discuss the steps ntoskrnl.exe goes through to initialize various Executive subsystems, such as the Memory Manager, Object Manager, and Process Manager. I'll also describe how NTOSKRNL loads more device drivers and initializes them and the boot drivers that NTLDR loaded. I'll conclude this tour of the NT boot process by showing you how ntoskrnl.exe initializes the user-mode side of the boot by loading winlogon, CSRSS (the Win32 subsystem), and services.