Patina Requirements
The Patina DXE Core has several functional and implementation differences from the Platform Initialization (PI) Spec and EDK II DXE Core implementation.
- The Patina Readiness Tool validates many of these requirements.
- The Patina DXE Core Requirements Platform Checklist provides an easy way for platform integrators to track if they have met all requirements.
- The Patina DXE Core Integration Guide provides a detailed guide of how to integrate the DXE core into a platform.
Platform Requirements
Platforms should ensure the following specifications are met when transitioning over to the Patina DXE core:
1. Dispatcher Requirements
The following are the set of requirements the Patina DXE Core has in regard to driver dispatch.
1.1 No Traditional SMM
Traditional System Management Mode (SMM) is not supported in Patina. Standalone MM is supported.
Traditional SMM is not supported to prevent coupling between the DXE and MM environments. This is error prone, unnecessarily increases the scopes of DXE responsibilities, and can lead to security vulnerabilities.
Standalone MM should be used instead. The combined drivers have not gained traction in actual implementations due to their lack of compatibility for most practical purposes, increased likelihood of coupling between core environments, and user error when authoring those modules. The Patina DXE Core focuses on modern use cases and simplification of the overall DXE environment.
This specifically means that the following SMM module types that require cooperation between the SMM and DXE dispatchers are not supported:
EFI_FV_FILETYPE_SMM(0xA)EFI_FV_FILETYPE_SMM_CORE(0xD)
Further, combined DXE modules will not be dispatched. These include:
EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER(0x8)EFI_FV_FILETYPE_COMBINED_SMM_DXE(0xC)
DXE drivers and Firmware volumes will be dispatched:
EFI_FV_FILETYPE_DRIVER(0x7)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE(0xB)
Because Traditional SMM is not supported, events such as the gEfiEventDxeDispatchGuid defined in the PI spec and used
in the EDK II DXE Core to signal the end of a DXE dispatch round so SMM drivers with DXE dependency expressions could be
reevaluated will not be signaled.
Dependency expressions such as EFI_SECTION_SMM_DEPEX will not be evaluated on firmware volumes.
The use of Traditional SMM and combined drivers is detected by the Patina DXE Readiness Tool, which will report this as an issue requiring remediation before Patina can be used.
Additional resources:
Guidance: Platforms must transition to Standalone MM (or not use MM at all, as applicable) using the provided guidance. All combined modules must be dropped in favor of single phase modules.
1.2 A Priori Driver Dispatch Is Not Allowed
The Patina DXE Core does not support A Priori driver dispatch as described in the PI spec and supported in EDK II. See the Dispatcher Documentation for details and justification. Patina will dispatch drivers in FFS listed order.
Guidance: A Priori sections must be removed and proper driver dispatch must be ensured using depex statements. Drivers may produce empty protocols solely to ensure that other drivers can use that protocol as a depex statement, if required. Platforms may also list drivers in FFSes in the order they should be dispatched, though it is recommended to rely on depex statements.
1.3 Driver Section Alignment Must Be a Multiple of 4 KB
Patina relies on using a 4 KB page size and as a result requires that the C based drivers it dispatches have a multiple of 4KB as a page size in order to apply image memory protections. The EDK II DXE Core cannot apply image memory protections on images without this section alignment requirement, but it will dispatch them, depending on configuration.
AArch64 DXE_RUNTIME_DRIVERs must have a multiple of 64 KB image section alignment per UEFI spec requirements. This is required to boot operating systems with 16 KB or 64 KB page sizes.
Patina components will have 4 KB section alignment by nature of being compiled into Patina.
The DXE Readiness Tool validates all drivers have a multiple of 4 KB section alignment and reports an error if not. It will also validate that AArch64 DXE_RUNTIME_DRIVERs have a multiple of 64KB section alignment.
Guidance: All C based drivers must be compiled with a linker flag that enforces a multiple of 4 KB section alignment. For MSVC/CLANGPDB, this linker flag is
/ALIGN:0x1000for GCC/CLANGDWARF, the flag is-z common-page-size=0x1000. It is recommended to use 4 KB for everything except for AArch64 DXE_RUNTIME_DRIVERs which should use 64 KB i.e.,/ALIGN:0x10000for MSVC/CLANGPDB and-z common-page-size=0x10000for GCC/CLANGDWARF.
2. Hand Off Block (HOB) Requirements
The following are the Patina DXE Core HOB requirements.
2.1 Resource Descriptor HOB v2
Patina uses the Resource Descriptor HOB v2, which is in process of being added to the PI spec, instead of the EFI_HOB_RESOURCE_DESCRIPTOR.
Platforms need to exclusively use the Resource Descriptor HOB v2 and not EFI_HOB_RESOURCE_DESCRIPTOR. Functionally, this just requires adding an additional field to the v1 structure that describes the cacheability attributes to set on this region.
Patina requires cacheability attribute information for memory ranges because it implements full control of memory management and cache hierarchies in order to provide a cohesive and secure implementation of memory protection. This means that pre-DXE paging/caching setups will be superseded by Patina and Patina will rely on the Resource Descriptor HOB v2 structures as the canonical description of memory rather than attempting to infer it from page table/cache control state.
Patina will ignore any EFI_HOB_RESOURCE_DESCRIPTORs. The Patina DXE Readiness Tool verifies that all EFI_HOB_RESOURCE_DESCRIPTORs produced have a v2 HOB covering that region of memory and that all of the EFI_HOB_RESOURCE_DESCRIPTOR fields match the corresponding v2 HOB fields for that region.
The DXE Readiness Tool also verifies that a single valid cacheability attribute is set in every Resource Descriptor HOB v2. The accepted attributes are EFI_MEMORY_UC, EFI_MEMORY_WC, EFI_MEMORY_WT, EFI_MEMORY_WB, and EFI_MEMORY_WP. EFI_MEMORY_UCE, while defined as a cacheability attribute in the UEFI spec, is not implemented by modern architectures and so is prohibited. The DXE Readiness Tool will fail if EFI_MEMORY_UCE is present in a v2 HOB.
Guidance: Platforms must produce Resource Descriptor HOB v2s with a single valid cacheability attribute set. These can be the existing Resource Descriptor HOB fields with the cacheability attribute set as the only additional field in the v2 HOB.
2.2 MMIO and Reserved Regions Require Resource Descriptor HOB v2s
All memory resources used by the system require Resource Descriptor HOB v2s. Patina needs this information to map MMIO and reserved regions as existing EDK II based drivers expect to be able to touch these memory types without allocating it first; EDK II does not require Resource Descriptor HOBs for these regions.
This cannot be tested in the DXE Readiness Tool because the tool does not know what regions may be reserved or MMIO without the platform telling it and the only mechanism for a platform to do that is through a Resource Descriptor HOB v2. Platforms will see page faults if a driver attempts to access an MMIO or reserved region that does not have a Resource Descriptor HOB v2 describing it.
Guidance: Platforms must create Resource Descriptor HOB v2s for all memory resources including MMIO and reserved memory with a valid cacheability attribute set.
2.2.1 Resource Descriptor Hob v2 Guidance
Resource Descriptor HOBs are produced by a platform to describe ranges that compose the system's memory map. Historically, some platforms have only described memory that is in use, but the HOBs should describe the entire system memory map, as it stands, at the end of the HOB-producer phase. This includes caching attributes in V2 resource descriptor HOBs so that Patina is able to consume the data and provide enhanced memory protections from the start of DXE.
PEI Video Region Example
By the start of DXE, most system memory should be configured as Write Back (EFI_MEMORY_WB), and most Memory Mapped I/O should be configured as uncached (EFI_MEMORY_UC). There are exceptions to this, based upon platform level decisions.
One example is a PEI Video driver. If PEI configured a video device and displayed a logo on the screen, the memory region associated with the frame buffer would usually be configured as write combined (EFI_MEMORY_WC) for performance. If the video region was not configured as write combined, then attempting to display anything on the screen would be extremely slow. The caching attributes for this region would need to be reported through a non-overlapping resource descriptor HOB for that region.
The write combined cache setting would persist throughout the rest of the boot process, including after GOP drivers start managing the video device. The other transition point would be prior to handing off to the OS. At that point, the region would transition to uncached (EFI_MEMORY_UC). The OS would then be responsible to managing caching attributes.
Firmware Devices
SPI flash accessible through MMIO is another complex example.
Consider the following scenario:
- 64MB SPI part, mapped to 0xFC00_0000 - 0xFFFF_FFFF.
- FVs in the SPI part
- 0xFD00_0000 - 0xFD04_FFFF - Non Volatile Ram
- 0xFD05_0000 - 0xFE40_FFFF - DXE code
- 0xFF00_0000 - 0xFFFF_FFFF - PEI code
- HPET enabled, mapped to 0xFED0_0000 - 0xFED0_03FF.
Note: Both the HPET region and the FV hobs overlaps with the SPI region.
The HPET should have a MMIO resource descriptor HOB for its region, with cache type uncached (EFI_MEMORY_UC). The SPI flash can be reported around the HPET region as MMIO resources with the uncached attribute (EFI_MEMORY_UC) and with the memory type write protect (EFI_MEMORY_WP).
2.3 Overlapping HOBs Prohibited
Patina does not allow there to be overlapping Resource Descriptor HOB v2s in the system and the DXE Readiness Tool will fail if that is the case. Patina cannot choose which HOB should be valid for the overlapping region; the platform must decide this and correctly build its resource descriptor HOBs to describe system resources.
The EDK II DXE CORE silently ignores overlapping HOBs, which leads to unexpected behavior when a platform believes both HOBs or part of both HOBs, is being taken into account.
Guidance: Platforms must produce non-overlapping HOBs by splitting up overlapping HOBs into multiple HOBs and eliminating duplicates.
2.4 No Memory Allocation HOB for Page 0
Patina does not allow there to be a memory allocation HOB for page 0. The EDK II DXE Core allows allocations within page 0. Page 0 must be unmapped in the page table to catch null pointer dereferences and this cannot be safely done if a driver has allocated this page.
The DXE Readiness Tool will fail if a Memory Allocation HOB is discovered that covers page 0.
Guidance: Platforms must not allocate page 0.
3. Miscellaneous Requirements
This section details requirements that do not fit under another category.
3.1 Exit Boot Services Memory Allocations Are Not Allowed
When EXIT_BOOT_SERVICES is signaled, the memory map is not allowed to change. See
Exit Boot Services Handlers. The EDK II DXE Core does
not prevent memory allocations at this point, which causes hibernate resume failures, among other bugs.
The DXE Readiness Tool is not able to detect this anti-pattern because it requires driver dispatching and specific target configurations to trigger the memory allocation/free.
Guidance: Platforms must ensure all memory allocations/frees take place before exit boot services callbacks.
3.2 All Code Must Support Native Address Width
By default, the Patina DXE Core allocates memory top-down in the available memory space. Other DXE implementations such as EDK II allocate memory bottom-up. This means that all code storing memory addresses (including C and Rust code) must support storing that address in a variable as large as the native address width.
For example, in a platform with free system memory > 4GB, EDK II may have never returned a buffer address greater than
4GB so UINT32 variables were sufficient (though bad practice) for storing the address. Since Patina allocates memory
top-down, addresses greater than 4GB will be returned if suitable memory is available in that range and code must
be able to accommodate that.
Guidance: All DXE code (including all C modules) must support storing native address width memory addresses.
Note: The Patina DXE Readiness Tool does not perform this check.
3.3 ConnectController() Must Explicitly Be Called For Handles Created/Modified During Image Start
To maintain compatibility with UEFI drivers that are written to the EFI 1.02 Specification, the EDK II StartImage()
implementation is extended to monitor the handle database before and after each image is started. If any handles are
created or modified when an image is started, then EFI_BOOT_SERVICES.ConnectController() is called with the
Recursive parameter set to TRUE for each of the newly created or modified handles before StartImage() returns.
Patina does not implement this behavior. Images and platforms dependent on this behavior will need to be modified to
explicitly call ConnectController() on any handles that they create or modify.
3.4 EFI_MEMORY_UC Memory Must Be Non-Executable
Patina will automatically apply EFI_MEMORY_XP to all SetMemorySpaceAttributes(), CpuArchProtocol->SetMemoryAttributes(), and MemoryAttributesProtocol->SetMemoryAttributes() calls that pass in EFI_MEMORY_UC. In the DXE time frame, no uncached memory (typically representing device memory) should be marked as executable. For AArch64, the ARM ARM v8 B2.7.2 states that having executable device memory (what EFI_MEMORY_UC maps to) is a programming error and has been observed to cause crashes due to speculative execution trying instruction fetches from memory that is not ready to be touched or should never be touched. For x86 platforms, these regions are still protected to prevent devices having access to executable memory.
4. Architectural Requirements
This section details Patina requirements that are specific to a particular CPU architectural requirements.
4.1 CpuDxe Is No Longer Used
EDK II supplies a driver named CpuDxe that provides CPU related functionality to a platform. In Patina DXE Core, this
is part of the core, not offloaded to a driver. As a result, the CPU Arch and memory attributes protocols are owned by
the Patina DXE Core. MultiProcessor (MP) Services are not part of the core (see following sections for specific
guidance on MP Service enabling for specific architectures).
Guidance: Platforms must not include
CpuDxein their platforms and instead use CPU services from Patina DXE Core and MP Services from a separate C based driver such asMpDxefor X64 systems orArmPsciMpServicesDxe.
4.2 AArch64-specific requirements
This section details Patina requirements specific to the AArch64 architecture.
4.2.1 AArch64 Generic Interrupt Controller (GIC)
On AArch64 systems, when Patina assumes ownership of CpuDxe it also encompasses the functionality provided by the
ArmGicDxe driver which configures the AArch64 GIC. This is because GIC support is a prerequisite for CpuDxe to
handle interrupts correctly. As such, AArch64 platforms also should not include the ArmGicDxe driver.
In addition, different AArch64 platforms can place the GIC register set at different locations in the system memory map.
Consequently, AArch64 platforms must supply the base addresses associated with the GIC as part of the CpuInfo struct
that is part of core configuration.
Guidance: AArch64 platforms should not use the
ArmGicDxedriver and must supply the base addresses of the GIC in theCpuInfostructure.
4.2.2 AArch64 Memory Caching Attribute Requirements for Device Memory
AArch64 brings with it specific architectural requirements around the caching attributes for MMIO peripheral memory. For example, marking a region as "Device" may activate alignment checks on memory access to that region, or not marking a peripheral MMIO region as Device may allow speculative execution to that region. Since Patina will configure the cache attributes of the memory map at startup (rather than, for example, relying on the paging structures that were set up prior to DXE start), special care must be taken to ensure that the caching attributes in the Resource HOB v2 that the platform produces are appropriate for the regions of memory that they describe.
Guidance: Ensure that the memory map as described via the Resource V2 HOBs is correct for the system, taking into account the special requirements for peripheral memory.
4.3 X64-specific requirements
As described in the general architectural requirements. X64 systems must exclude CpuDxe. In addition
MpDxe should be included in the
platform flash file as it is used to install the MP Services protocol.
Note: The
patina-mtrrrepo provides pure-Rust MTRR support for X64 platforms. This can be used indpendently of the Patina DXE Core. It is intended to provide generic MTRR support for Rust-based UEFI environments on X64 platforms.
4.3.1 X64 MM Core and MM Driver Requirements
Due to the No Traditional SMM requirement, X64 platforms must ensure that the MM core is of
module type MM_CORE_STANDALONE and all MM drivers are of module type MM_STANDALONE. X64 platforms can optionally
use the MM communication code in the patina_mm
crate to facilitate communication between DXE and MM during the DXE phase. However, this component does not provide
support during runtime. This is because Patina components are currently not supported during runtime. Because of this,
it is recommended to use the MM communication code produced by a DXE_RUNTIME_DRIVER such as
(StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe)
for C-driver communication support during boot and the MmCommunicator
component provided in patina_mm for MM communication in Patina components.
5. Known Limitations
This section details requirements Patina currently has due to limitations in implementation, but that support will be added for in the future.
5.1 Synchronous Exception Stack Size limitation on AArch64 Platforms
Presently a hard stack size limitation of 64KB applies to synchronous exceptions on AArch64 platforms. This means, for example, that platform panic handlers should not make large allocations on the stack. The following issue tracks this: 781