Geoff Chappell, Software Analyst
The I386_LOADER_BLOCK is a structure within the x86 and x64 builds of the LOADER_PARAMETER_BLOCK, which is in turn the structure through which the kernel and HAL learn the initialisation data that was gathered by the loader.
The I386_LOADER_BLOCK has changed just once, in the version 4.0 from Windows NT 4.0 SP3. This extended it from 0x08 to 0x0C bytes in 32-bit Windows but left its size unchanged at 0x10 bytes in 64-bit Windows. Offsets, names and types in the table that follows are from type information in public symbol files for occasional Windows versions: first for Windows 2000 SP3 and SP4; next for all releases of Windows Vista and Windows 7; and most recently for the 1803 release of Windows 10. How the type information gets into symbol files for some versions but not others is not known. A C-language definition has been published in a header named ARC.H from the Enterprise edition of the Windows Driver Kit (WDK) for Windows 10 Version 1511.
|Offset (x86)||Offset (x64)||Definition||Versions|
|late 4.0 and higher|
The CommonDataArea is for the 32-bit kernel’s use of the Advanced BIOS (ABIOS) through the exported functions KeI386AbiosCall and KeI386GetLid. The ABIOS was a Basic I/O System (BIOS) that could operate peripheral devices from protected mode without needing a reversion to real-mode addressing. That all the necessary details for using a computer’s hardware are built into firmware by the computer’s manufacturer may have seemed attractive to the manufacturer of an operating system. ABIOS support was important enough that it was given its own NTSTATUS codes: eight of them, starting with STATUS_ABIOS_NOT_PRESENT. That the kernel’s functions for ABIOS support never got documented may mean they were important as an internal detail to be kept just for Microsoft to use for its own system-supplied drivers or that they were soon seen as not worth bothering with. In some sense it no longer matters, perhaps not even as history. All ABIOS support was removed from the kernel for version 6.2. But this had been a long time coming: the loader lost its code for preparing the CommonDataArea in version 5.1. And this too was a holdover: only one driver from Microsoft, named ABIOSDSK.SYS, is known to have used ABIOS support, and it had not survived even to version 5.0.
A comment in the C-language definition that Microsoft published for Windows 10 would have it that the MachineType is “Temporary only”. This comment may be very old. The low byte of the MachineType, zero-extended to a dword, is the source of what all versions of the 32-bit kernel export as the KeI386MachineType variable, but it is very many years since either had any known usefulness to anyone. The last driver from Microsoft that is known to have used the KeI386MachineType variable is SETUPDD.SYS, and it stopped this for Windows XP. The kernel has its own use for the variable in versions 4.0 to 5.2. Further study may be justified.
Except for initialising the kernel’s KeI386MachineType, the last-known use of the MachineType is by the HAL. Up to and including Windows Vista, the HAL interprets the low byte of the MachineType as a bus type. Early versions depend on knowing this bus type for correctly initialising such vital peripherals as the Programmable Interrupt Controller (PIC), so much so that most HAL variants before Windows Vista stop Windows at startup (with the MISMATCHED_HAL bug check) if the MachineType is incompatible with whether the HAL does or does not support the Micro Channel Architecture (MCA). Aside from this particular interpretation within the HAL, most HAL variants map the undocumented MachineType to the documented INTERFACE_TYPE for the HAL’s report of resource usage, such as persists under the registry key HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\Hardware Abstraction Layer:
|MACHINE_TYPE_ISA (0)||Isa (1)||3.10 to 6.0|
|MACHINE_TYPE_EISA (1)||Eisa (2)||3.10 to 6.0|
|MACHINE_TYPE_MCA (2)||Internal (0)||3.10 to 3.50 for some variants, e.g., HALCBUS|
|MicroChannel (3)||3.10 to 6.0|
|else||PCIBus (5)||5.1 to 6.0 for some variants, e.g., HALAACPI, HALAPIC, HALMACPI, HALMPS|
|Internal (0)||3.10 to 6.0|
Be aware, however, that some HAL variants ignore the MachineType for this purpose and instead report a hard-coded INTERFACE_TYPE. Notable examples are: Internal by HALBORG; Eisa by HALAST, HALOLI, HALSP and HALWYSE7; and MicroChannel by HALNCR. None of these particular cases are known beyond Windows XP, but their ignoring of the MachineType becomes the generality in Windows 7, both of whose HALs are hard-coded to report Isa as if the MachineType could only be zero. Windows 8 and higher have just the one HAL: it changes the hard coding to Internal, as if a valid MachineType were not provided.
Windows 8 thus formalised that the MachineType had been meaningless for years. In the reworking from NTLDR and its embedded OSLOADER to a separate BOOTMGR and WINLOAD for Windows Vista, the loader simply stopped setting the MachineType. Where Windows Vista shows Isa as the Interface Type among the Resource Lists for the HAL, as in
it’s not that there actually is an ISA bus: it’s just that the loader leaves the MachineType as zero-initialised.
Even before Windows Vista, the loader had long before cut down on what it can set for the MachineType. The work of determining the machine type is done during real-mode execution by the NTLDR and is passed as input to the protected-mode OSLOADER.EXE (which is embedded in the NTLDR binary). Though the OSLOADER before Windows Vista and the HAL before Windows 7 have code that would vary their behaviour if the machine type is MCA, it’s redundant in Windows XP and higher, since the NTLDR no longer bothers with Micro Channel detection.
The VirtualBias member was added in version 4.0, apparently for Windows NT 4.0 SP3, to allow for increasing user-mode address space at the expense of kernel-mode (via the /3GB switch in the BOOT.INI configuration file). What contortions await the kernel for fitting its work into a system address space that may be only half of the usual 2GB are a long way off, but some adjustment is needed by the loader just for choosing where to place the kernel. The loader would ordinarily treat 0x80000000 as a base address for what it prepares of the system address space. The VirtualBias tells how much higher the loader chose instead.