LOADER_PARAMETER_BLOCK

The LOADER_PARAMETER_BLOCK is the structure through
which the kernel and HAL learn the initialisation data that was gathered by the
loader.

Historically, and for most practical purposes even in recent Windows versions,
there is only ever the one instance of this structure. It is prepared by the loader
as its means of handing over to the kernel. When the loader calls the kernel’s initialisation
routine, the address of the loader block is the one argument. The kernel saves the
address for a while in the exported variable KeLoaderBlock.
At the end of the kernel’s initialisation, the structure gets freed and the variable
gets cleared. Meanwhile, especially while debugging device driver initialisation,
knowledge of this structure can be very helpful.

Variability

Perhaps because the LOADER_PARAMETER_BLOCK is accessible
through an exported variable and is vital as shared data between the loader, kernel
and HAL, it was highly stable for many Windows versions, certainly in comparison
with other undocumented structures. Since version 5.2, however, each change of version
brings a change of size:

Version

Size (x86)

Size (x64)

3.10 to 4.0

0x64

5.0 to 5.2

0x68

0xC8

6.0

0x7C

0xE8

6.1

0x88

0xF0

6.2

0xA0

0x0118

6.3

0xAC

0x0128

10.0

0xBC

0x0148

The growth from version 4.0 to 5.0 and again from 6.2 to 6.3 involves no additions,
removals or rearrangements to the structure’s own members, just growth within a
member, and in both cases within the member that was at the time the structure’s
last. Version 6.0 brought a straightforward appending of one member. Such growth
only at the end allows for backwards compatibility. A new loader can prepare the
structure in its new layout but safely pass it to an old kernel. This was indeed
depended on for multi-boot configurations in the days when the one NTLDR in the
root directory of the bootable partition might load the kernel of any earlier Windows
version (if not of a later one).

Version 6.0 separated the booting of Windows into a boot manager, e.g., BOOTMGR,
and a boot loader, e.g., WINLOAD. The boot manager selects which Windows installation
to proceed with. Each Windows version provides its own boot loader. This is what
prepares the LOADER_PARAMETER_BLOCK and it only has
to do so for the matching kernel. Backwards compatibility is no longer an issue
for the structure. Most changes since are not just from growth at the end: members
are inserted and removed without regard for continuity. Notably, version 6.1 inserted
version numbers and a size at the structure’s very start, surely to provide some
easy and reliable means for future kernels to validate that the structure received
from the loader is plausibly what that kernel expects. This defence was apparently
thought important enough to warrant its own bug-check, LOADER_BLOCK_MISMATCH (0x0100).

Layout

Until recently, Microsoft’s names for the LOADER_PARAMETER_BLOCK
members and types were known only from type information in the symbol files for
occasional Windows versions: first for Windows 2000 SP3 and SP4, then for all releases
of Windows Vista and Windows 7, but for none since. How the type information gets
into symbol files for some versions but not others is not known. Windows 10, however,
brings something new…

A header file, ARC.H, in the Windows Driver Kit (WDK) for Windows 10 supplies
a C-language definition of the LOADER_PARAMETER_BLOCK.
This appears to be Microsoft’s first formal disclosure of the structure’s layout.
It comes with no conditional compilation blocks for accommodating earlier versions.
As supplied, it is immediately useful only for programming that targets Windows
10 specifically, yet doesn’t say so. Add that the header is beneath a subdirectory
named “um”, presumably to mean user-mode, but that the LOADER_PARAMETER_BLOCK
is long gone by the time any user-mode software gets to execute, and one might wonder
if this structure’s definition was published by mistake.

Still, published it is. The following table presents the layout of the
LOADER_PARAMETER_BLOCK for the original release of Windows
10 (build 10240), as inferred from Microsoft’s header. For earlier versions, the
layout is directly from type information in symbol files, if available. Names, types
and offsets for other versions are something of a guess from assuming continuity
except where inspection of the loader or kernel shows that members have come and
gone.

The C-language definition in Microsoft’s ARC.H shows Reserved
as being now put to use as OsLoaderSecurityVersion—which
indeed it is, but for the build 10586 of version 10.0 from the 1511 release. Working
out how to present developments now that Microsoft says all future Windows releases
will be version 10.0 is a problem I leave for another time.

The u union is presented only for the versions that
have type information in symbol files or for which Microsoft publishes a C-language
definition. Members other than I386 presumably change
with Microsoft’s choice of supported processor architectures and these notes are
derived from inspection of the i386 and amd64 architectures only.

I386_LOADER_BLOCK

Since the I386_LOADER_BLOCK seems to have no purpose
outside the LOADER_PARAMETER_BLOCK, it may as well be
presented here:

Offset (x86)

Offset (x64)

Definition

Versions

0x00

0x00

PVOID CommonDataArea;

all

0x04

0x08

ULONG MachineType;

all

0x08

0x0C

ULONG VirtualBias;

5.0 to 6.1

The kernel’s use of the CommonDataArea seems to have
stopped for version 6.2. A comment in the C-language definition for Windows 10 would
have it that the MachineType is “Temporary only”. In
all known versions it is the source of what the 32-bit kernel exports as the
KeI386MachineType variable.

The VirtualBias member was added for version 5.0,
which is the first to allow for increasing user-mode address space at the expense
of kernel-mode (via the /3GB switch in the BOOT.INI
configuration file).

FIRMWARE_INFORMATION_LOADER_BLOCK

The FIRMWARE_INFORMATION_LOADER_BLOCK is also thought
to have no independent existence.

The first of the bit flags selected from the union u
according to the firmware type. Windows 10 added more to support Isolated User Mode
(IUM) and the security of memory that is saved during hibernation.

Mask

Definition

Versions

0x00000001

ULONG FirmwareTypeEfi : 1;

6.0 and higher

0x00000002

ULONG EfiRuntimeUseIum : 1;

10.0 and higher

0x00000004

ULONG EfiRuntimePageProtectionEnabled : 1;

10.0 and higher

0x00000008

ULONG EfiRuntimePageProtectionSupported : 1;

10.0 and higher

ULONG Reserved : 31;

6.0 to 6.3

ULONG Reserved : 28;

10.0 and higher

The PCAT_FIRMWARE_INFORMATION structure has just
the one member, a ULONG named PlaceHolder.
The business of the FIRMWARE_INFORMATION_LOADER_BLOCK
has always been to provide EFI_FIRMWARE_INFORMATION:

Offset (x86)

Offset (x64)

Definition

Versions

0x00

0x00

ULONG FirmwareVersion;

6.0 and higher

0x04

0x08

VIRTUAL_EFI_RUNTIME_SERVICES *VirtualEfiRuntimeServices;

6.0 and higher

0x08

0x10

NTSTATUS SetVirtualAddressMapStatus;

6.0 and higher

0x0C

0x14

ULONG MissedMappingsCount;

6.0 and higher

0x10

0x18

LIST_ENTRY FirmwareResourceList;

6.2 and higher

0x18

0x28

PVOID EfiMemoryMap;

6.3 and higher

0x1C

0x30

ULONG EfiMemoryMapSize;

6.3 and higher

0x20

0x34

ULONG EfiMemoryMapDescriptorSize;

6.3 and higher

This page was created on 28th
April 2016 and was last modified on
4th June 2017.