Supported Architectures and Custom Architecture Configuration
About 1109 wordsAbout 4 min
2026-03-23
EDK2 Supported Architectures
EDK2 supports six CPU architectures. Each has dedicated packages, CPU driver libraries, and toolchain support in tools_def.txt.
Architecture Overview Table
| Arch Tag | ISA | Key Package | Typical Platform |
|---|---|---|---|
X64 | x86-64 (AMD64) | UefiCpuPkg, MdeModulePkg | OVMF, PC servers, Intel NUC |
IA32 | x86 32-bit | UefiCpuPkg | Legacy 32-bit x86 targets |
AARCH64 | ARM 64-bit (ARMv8-A) | ArmPkg, ArmPlatformPkg | RPi4, Ampere Altra, Snapdragon |
ARM | ARM 32-bit (ARMv7-A/R) | ArmPkg, ArmPlatformPkg | Legacy ARM SoCs |
RISCV64 | RISC-V 64-bit (RV64GC) | RiscVPkg | SiFive Unmatched, QEMU virt |
LOONGARCH64 | LoongArch 64-bit | LoongArchPkg | Loongson 3A6000 |
Architecture-Specific Boot Mechanism
x86 / X64
- CPU starts in 16-bit real mode at reset vector
0xFFFF_FFF0 - SEC module (
ResetVector/) runs in real mode, transitions to 32-bit protected mode, then 64-bit long mode - Cache-As-RAM (CAR) via MTRRs for temporary PEI stack before DRAM init
- SMM (System Management Mode) handled by
UefiCpuPkg/PiSmmCpuDxeSmm - ACPI as mandatory hardware description
AARCH64
- CPU starts at reset in EL3 (highest exception level) or EL2
- TF-A typically runs at EL3 (BL1–BL31), hands off to EDK2 at EL2 (BL33)
- EDK2 SEC/PEI implemented in
ArmPlatformPkg/PrePi/(PEI-less) or via full PEI - ARM GICv2/GICv3 interrupt controller driver in
ArmPkg/Drivers/ArmGic/ - ACPI + DTB both valid; SBSA/SBBR compliance defines mandatory interfaces
- AArch64 exception vectors:
ArmPkg/Library/ArmExceptionLib/
RISC-V 64
- CPU starts at Machine mode (M-mode), highest privilege
- OpenSBI runs at M-mode as the Supervisor Execution Environment (SEE)
- EDK2 runs at S-mode, using OpenSBI via SBI calls
- RISC-V UEFI spec requires Flattened Device Tree (FDT) and ACPI mandated for servers
RiscVPkg/contains RISC-V CPU dxe driver, timer, and reset
CPU Architecture Support in Code
Architecture-Specific Libraries
Each architecture provides implementations of abstract library classes:
ArmPkg/Library/
├── ArmLib/ArmBaseLib.inf ← BaseLib extensions for ARM
├── ArmMmuLib/ArmMmuBaseLib.inf ← MMU/page table manipulation
├── CpuLib/ArmCpuLib.inf ← CpuLib for ARM (cache flush, WFI)
├── ArmGicLib/ArmGicNonSecLib.inf ← GIC Non-secure interrupt lib
├── ArmSmcLib/ArmSmcLib.inf ← SMC calling convention (TF-A)
├── ArmHvcLib/ArmHvcLib.inf ← HVC calling convention
└── SynchronizationLib/ArmSynchronizationLib.inf ← atomic operations
UefiCpuPkg/Library/
├── BaseUefiCpuLib/BaseUefiCpuLib.inf ← x86 microarchitecture utilities
├── CpuPageTableLib/CpuPageTableLib.inf ← x86 paging
└── MpInitLib/MpInitLib.inf ← Multi-processor initIn a DSC, architecture-specific library bindings use section qualifiers:
[LibraryClasses.AARCH64]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
CpuLib|ArmPkg/Library/CpuLib/ArmCpuLib.inf
CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf
DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
[LibraryClasses.X64]
CpuLib|UefiCpuPkg/Library/BaseCpuLib/BaseCpuLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.infCreating a Custom Architecture Configuration
"Custom architecture configuration" in EDK2 means defining how your specific hardware platform (SoC + board) is represented in the build system, including PCDs, library bindings, FDF regions, and architecture-specific flags. This is platform porting, but the architecture-config aspect focuses on the DSC mechanics.
Step 1: Define the Platform Scope in DSC [Defines]
[Defines]
PLATFORM_NAME = MySoCPlatform
PLATFORM_GUID = A1B2C3D4-E5F6-7890-ABCD-EF1234567890
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x0001001c
OUTPUT_DIRECTORY = Build/MySoCPlatform
SUPPORTED_ARCHITECTURES = AARCH64 # Only architectures this platform builds for
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT|BOARD_REV_A|BOARD_REV_B
FLASH_DEFINITION = MySoCPkg/MySoCPlatform.fdfSUPPORTED_ARCHITECTURES restricts which -a arguments are valid for this DSC. Attempting to build X64 for an ARM-only platform will produce an error.
Step 2: Architecture-Specific PCD Overrides
PCDs that depend on the target architecture — base addresses, stack sizes, memory map constants — are overridden per-arch:
[PcdsFixedAtBuild.AARCH64]
# GIC base addresses for this SoC
gArmTokenSpaceGuid.PcdGicDistributorBase|0x08000000
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x08010000
gArmTokenSpaceGuid.PcdGicRedistributorsBase|0x080A0000 # GICv3
# Timer frequency
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|24000000
# UART base for PL011
gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase|0x09000000
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200
# DDR layout
gArmTokenSpaceGuid.PcdSystemMemoryBase|0x40000000
gArmTokenSpaceGuid.PcdSystemMemorySize|0x40000000 # 1 GiB
[PcdsFixedAtBuild.X64]
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|2Step 3: Architecture-Specific Components
Include platform modules only for the relevant architecture:
[Components.AARCH64]
ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
ArmPkg/Drivers/TimerDxe/TimerDxe.inf
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
MySoCPkg/Drivers/MySoCUartDxe/MySoCUartDxe.inf
MySoCPkg/Drivers/MySoCGpioDxe/MySoCGpioDxe.inf
[Components.X64]
UefiCpuPkg/CpuDxe/CpuDxe.inf
PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
MySoCPkg/Drivers/MySoCPcieDxe/MySoCPcieDxe.infStep 4: Architecture-Specific Build Options
Control compiler flags per architecture and module type:
[BuildOptions.AARCH64]
GCC:*_*_AARCH64_CC_FLAGS = -DMYPLATFORM_AARCH64 -DGIC_VERSION=3
GCC:*_*_AARCH64_DLINK_FLAGS = -z max-page-size=0x1000
[BuildOptions.AARCH64.DXE_RUNTIME_DRIVER]
GCC:*_*_AARCH64_CC_FLAGS = -DRUNTIME_DRIVER
[BuildOptions.common.PEIM]
GCC:*_*_*_CC_FLAGS = -DPEI_PHASE_BUILD
# Release-specific flags
[BuildOptions]
RELEASE_GCC:*_*_*_CC_FLAGS = -DNDEBUG -Os
DEBUG_GCC:*_*_*_CC_FLAGS = -DDEBUG_BUILD -gStep 5: SKU-Based Multi-Board Configuration
SKUs allow one DSC to produce different configurations for different board variants without separate DSC files.
[SkuIds]
0|DEFAULT # Always required
1|BOARD_REV_A|DEFAULT # Board Rev A inherits DEFAULT
2|BOARD_REV_B|DEFAULT # Board Rev B inherits DEFAULT
[PcdsFixedAtBuild.AARCH64]
# Default: use GICv2
gArmTokenSpaceGuid.PcdGicDistributorBase|0x08000000|UINT64|DEFAULT
# Board Rev B has GIC at different address
gArmTokenSpaceGuid.PcdGicDistributorBase|0x09000000|UINT64|BOARD_REV_BBuild with a specific SKU:
build -p MySoCPkg/MySoCPlatform.dsc -a AARCH64 -t GCC5 -D SKUID=BOARD_REV_BOr set in target.txt:
SKUID_IDENTIFIER = BOARD_REV_BAdding AARCH64 SEC/PrePi Entry Point
The very first code that runs on an AARCH64 platform must be compiled for XIP execution. EDK2 provides two models:
Model 1: Full PEI (SEC → PEI Core → PEIMs)
Used by platforms that need full PEI infrastructure (multiple PEIMs, HOB-based communication). The SEC module is in ArmPlatformPkg/Sec/.
# In DSC [Components.AARCH64]
ArmPlatformPkg/Sec/Sec.inf {
<LibraryClasses>
ArmPlatformLib|MySoCPkg/Library/MySoCPlatformLib/MySoCPlatformLib.inf
}ArmPlatformLib must implement:
// Called from SEC to determine if we're the primary CPU
UINTN ArmPlatformIsPrimaryCore (IN UINTN MpId);
// Called from PEI to initialize DRAM
RETURN_STATUS ArmPlatformInitializeSystemMemory (VOID);
// Return the start/size of trusted SRAM (pre-DRAM stack)
VOID ArmPlatformGetVirtualMemoryMap (OUT ARM_MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap);Model 2: PrePi (PEI-less Lightweight Startup)
Used by simple platforms (ArmVirtPkg, RPi). ArmPlatformPkg/PrePi/ is a single module that acts as both SEC and a simplified PEI Core:
# In DSC [Components.AARCH64]
ArmPlatformPkg/PrePi/PeiUniCore.inf {
<LibraryClasses>
ArmPlatformLib|MySoCPkg/Library/MySoCPlatformLib/MySoCPlatformLib.inf
MemoryInitPeiLib|MySoCPkg/Library/MySoCMemoryInitLib/MySoCMemoryInitLib.inf
}The PrePi model skips the PEI Core and directly transitions to DXE, producing HOBs that DXE Core consumes.
FDF Entry for SEC
The SEC module must be at the entry point of the SECFV firmware volume and executed first:
## In .fdf file
[FV.SECFV]
FvBaseAddress = 0x00008000 # XIP address in NOR flash
FvForceRebase = TRUE
INF RESET_VECTOR_ADDRESS = 0x00008000 ArmPlatformPkg/PrePi/PeiUniCore.infNew Architecture Definition (Hypothetical)
If EDK2 ever needed to support a new CPU architecture (like a future 128-bit ISA), the changes required illustrate the architecture boundary in the build system:
- Add arch tag to
buildcommand parsing:Build/buildoptions.py - tools_def.txt: Add toolchain definitions for
NEWARCH - New package
NewArchPkg/with:- CPU exception handler
- MMU library
- Timer library
BaseLibintrinsics for the new ISA
- Compiler intrinsics in
MdePkg/Library/CompilerIntrinsicLib/ - Linker scripts in
BaseTools/Scripts/ - Reset vector assembly in
NewArchPkg/Sec/ResetVector/ - MdePkg Include headers for the new arch's registers/calling convention
The architecture coverage in MdePkg headers:
MdePkg/Include/
├── Ia32/ ← x86 32-bit processor bindings
├── X64/ ← x86-64 processor bindings
├── Arm/ ← ARM 32-bit processor bindings (deprecated)
├── AArch64/ ← ARM 64-bit processor bindings
├── RiscV64/ ← RISC-V 64-bit processor bindings
└── LoongArch64/ ← LoongArch 64-bit processor bindingsEach arch directory contains:
ProcessorBind.h— fundamental types (UINTN,INTN,MAX_ADDRESS,MAX_BIT, alignment macros)<arch>GccInline.hor similar — inline assembly intrinsics
ProcessorBind.h is the critical file binding the abstract EDK2 type system to the real machine word size.