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 to 1709

0xBC

0x0148

1803 and higher

0xC8

0x0160

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, and then for all
releases of Windows Vista and Windows 7. 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. Then, just as that seemed to be the end of disclosure,
perhaps forever, Microsoft’s names and types returned to the public symbol files
for the 1803 release of Windows 10.

The following table presents the layout of the LOADER_PARAMETER_BLOCK
for the 1803 release of Windows 10, as given by the public symbol files, and for
the 1511 release of Windows 10, as given by Microsoft’s ARC.H. For earlier versions,
the layout is directly from type information in symbol files, if available. Names,
types and offsets for all 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 that
Reserved as known from the Windows 7 symbol files is
put to use, starting with the 1511 release, as an OsLoaderSecurityVersion.
The only version yet known is 1.

Members of the u union are 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.

The three new members for the 1803 release elaborate the ancient
ArcBootDeviceName and ArcHalDeviceName
members, now adding ARC paths for the Boot Status Data (BSD) log and for whatever
devices are given by the osdatadevice and
windowssyspartboot options.

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 and higher

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 selects from the union u
according to the firmware type. Windows 10 adds more bit flags to support Isolated
User Mode (IUM) and the security of memory that is saved during hibernation (and
whose protection is thus dependent on firmware).

Mask

Definition

Versions

0x00000001

ULONG FirmwareTypeEfi : 1;

6.0 to some 10.0

ULONG FirmwareTypeUefi : 1;

some 10.0 and higher

0x00000002

ULONG EfiRuntimeUseIum : 1;

10.0 and higher

0x00000004 (10.0 to 1511)

ULONG EfiRuntimePageProtectionEnabled : 1;

10.0 to 1511

0x00000008 (10.0 to 1511);
0x00000004

ULONG EfiRuntimePageProtectionSupported : 1;

10.0 and higher

ULONG Reserved : 31;

6.0 to 6.3

ULONG Reserved : 28;

10.0 to 1511

ULONG Reserved : 29;

1607 and higher

Which Windows 10 is the one for which Microsoft renamed
FirmwareTypeEfi is not known.

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
9th September 2018.