What Is EDK II and How to Build UEFI Firmware

This article provides an overview of EFI Development Kit II (EDK II), the industry-standard open-source implementation of the Unified Extensible Firmware Interface (UEFI). It explores the architecture of EDK II, breaks down its core components, and walks through the step-by-step process of using the kit to build bootable UEFI firmware images for virtualized environments and physical hardware platforms.


What Is EDK II?

EDK II (EFI Development Kit II) is an open-source, modern implementation of the UEFI and Platform Initialization (PI) specifications. Maintained under the TianoCore project, EDK II serves as the foundation for the firmware found in most modern PCs, servers, and embedded systems, effectively replacing legacy BIOS.

Written primarily in C, EDK II provides the low-level code required to initialize hardware components (such as the CPU, memory, and PCIe devices), enforce secure boot policies, and hand control of the system over to the operating system bootloader.

Core Components and File Structure

EDK II uses a modular, package-based architecture to organize source code and platform definitions. The primary configuration files include:

  • INF Files (.inf): Module Information files. These define individual modules (drivers, libraries, or applications), specifying source files, library dependencies, and target architectures.
  • DEC Files (.dec): Package Declaration files. These define public interfaces, structures, and globally unique identifiers (GUIDs) that can be shared across packages.
  • DSC Files (.dsc): Platform Description files. These orchestrate the build process by specifying which libraries, components, and drivers to compile for a specific platform.
  • FDF Files (.fdf): Flash Description files. These define the layout and binary structure of the final firmware image, detailing how compiled modules are placed into firmware volumes (FV) and the final firmware device (.fd) file.

Common standard packages in the repository include MdePkg (core definitions), MdeModulePkg (standard drivers and services), and OvmfPkg (Open Virtual Machine Firmware for QEMU/KVM).


How to Build UEFI Firmware with EDK II

Building firmware with EDK II involves preparing a toolchain, compiling EDK II's internal build tools, configuring the platform parameters, and running the build script to generate a firmware image.

1. Set Up the Build Environment

EDK II requires specific build tools and compilers. On Linux, this typically includes gcc, g++, make, python3, nasm, uuid-dev, and git. On Windows, the process requires Visual Studio, Python, and NASM.

Once the system prerequisites are installed, clone the EDK II repository along with its submodules:

git clone --recursive https://github.com/tianocore/edk2.git
cd edk2

2. Compile BaseTools

EDK II includes a set of custom tools called BaseTools, written in C and Python, that parse configuration files (.dsc, .fdf, .inf) and generate code. To build them:

make -C BaseTools

3. Configure the Environment

Source the environment setup script to initialize variables like WORKSPACE, EDK_TOOLS_PATH, and default paths:

source edksetup.sh

This command automatically generates default configuration templates inside the Conf/ directory, including target.txt and tools_def.txt.

4. Define the Build Target

You can configure the target platform by editing Conf/target.txt or by passing command-line arguments to the build tool. The key parameters are:

  • ACTIVE_PLATFORM: The .dsc file of the platform you are compiling (e.g., OvmfPkg/OvmfPkgX64.dsc).
  • TARGET: The build type, typically DEBUG or RELEASE.
  • TARGET_ARCH: The processor architecture, such as X64, IA32, or AARCH64.
  • TOOL_CHAIN_TAG: The compiler tag matching your installed toolchain (e.g., GCC5 or VS2019).

5. Execute the Build

Run the build command with the appropriate flags. For example, to build an x86_64 OVMF image using GCC:

build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -t GCC5 -b RELEASE

During this step, the build system:

  1. Validates dependencies via .dsc and .dec files.
  2. Compiles individual modules specified by .inf files into .efi binaries.
  3. Packages the .efi binaries into firmware volumes based on the .fdf file.
  4. Produces the final binary flash file (.fd).

6. Locate and Test the Firmware

The generated binary is placed in the Build/ directory (e.g., Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd).

You can test this virtual UEFI firmware using an emulator like QEMU:

qemu-system-x86_64 -bios Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd -net none

For physical hardware, platform-specific packages (often supplied by board vendors or silicon manufacturers) replace OvmfPkg, and the resulting .fd image is flashed directly to the target system's SPI flash memory.