Patina Requirements

The Patina DXE Core has several functional and implementation differences from the Platform Initialization (PI) Spec and EDK II DXE Core implementation.

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:0x1000 for 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:0x10000 for MSVC/CLANGPDB and -z common-page-size=0x10000 for 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 CpuDxe in their platforms and instead use CPU services from Patina DXE Core and MP Services from a separate C based driver such as MpDxe for X64 systems or ArmPsciMpServicesDxe.

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 ArmGicDxe driver and must supply the base addresses of the GIC in the CpuInfo structure.

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-mtrr repo 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