UEFI Application Binaries vs Standard PE Executables

At a foundational level, UEFI application binaries adopt the Microsoft Portable Executable/Common Object File Format (PE/COFF or PE32+) structure, but they serve an entirely different execution environment than standard Windows PE executables. While standard PE files rely on an operating system kernel, dynamic link libraries (DLLs), and user-mode subsystems, UEFI binaries operate directly on bare-metal firmware. This fundamental difference shapes how the PE headers are populated, how memory relocation is handled, and how APIs are linked and invoked.

The Subsystem Field

The most explicit structural difference within the file header is located in the PE Optional Header's Subsystem field. Standard Windows executables typically declare:

  • IMAGE_SUBSYSTEM_WINDOWS_GUI (value 2)
  • IMAGE_SUBSYSTEM_WINDOWS_CUI (value 3, for command-line programs)

UEFI images target specific pre-boot environments and must declare one of the following subsystem values:

  • IMAGE_SUBSYSTEM_EFI_APPLICATION (value 10): A standalone program that unloads when it exits.
  • IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER (value 11): A driver that remains resident until the OS loader calls ExitBootServices().
  • IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER (value 12): A driver that remains in memory even after the operating system boots.
  • IMAGE_SUBSYSTEM_EFI_ROM (value 13): Firmware intended to be executed from a ROM chip.

The UEFI firmware boot manager inspects this field to determine memory allocation rules, execution lifetime, and permission boundaries before running the image.

Import and Export Tables

Standard PE executables rely heavily on the Import Address Table (IAT) to link against user-space dynamic libraries such as ntdll.dll or kernel32.dll. The Windows loader resolves these external symbols dynamically at runtime.

In contrast, UEFI binaries do not use an external dynamic linker or OS-provided DLLs. As a result:

  • The Import Table is generally absent, empty, or unpopulated.
  • UEFI applications access system APIs through function pointers provided in the EFI_SYSTEM_TABLE structure passed directly to the binary's entry point.
  • Communication between different UEFI modules occurs via "Protocols" discovered dynamically at runtime through GUID lookups rather than named PE imports.

Relocation Section Requirements

While modern 64-bit Windows PE files can sometimes omit base relocations if they support fixed base addresses, the relocation section (.reloc) is strictly mandatory for UEFI binaries.

UEFI firmware initializes memory dynamically at boot. Because memory layouts vary significantly between hardware platforms and motherboard designs, the firmware can load a binary at virtually any arbitrary physical memory address. The UEFI image loader requires base relocation data to patch absolute addresses in the code during load time; a UEFI binary missing its .reloc section will fail to execute.

Entry Point Signature and Calling Convention

Standard PE binaries compile to an entry point that expects conventional C runtime initialization (such as mainCRTStartup or WinMainCRTStartup), which sets up thread environments, handles, and command-line arguments.

A UEFI binary requires a standardized entry point adhering to the UEFI specification:

EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable);

The binary's headers point to this function, which takes an image handle and a pointer to the system table as parameters. The standard Microsoft x64 calling convention is preserved in 64-bit UEFI binaries, ensuring CPU register consistency during function calls even before an operating system is present.

Execution Environment Constraints

Standard PE executables are mapped into isolated virtual address spaces using paging mechanisms managed by the OS kernel, generally executing in Ring 3 (User Mode).

UEFI application binaries execute in Ring 0 (Privileged Mode) on flat, identity-mapped physical memory. They possess direct access to CPU control registers, I/O ports, and hardware devices, operating without the thread management, security tokens, or memory isolation native to conventional PE execution.