3. Platform Orchestration Layer (POL)

3.1. Introduction

The Platform Orchestration Layer (POL) is aimed to provide guidelines on writing platform code that leverage a Scalable Intel Firmware Support Package (sFSP) interface and payload to coordinate the overall platform initialization flow.

3.1.1. Motivation for POL

Following the Next Generation Firmware initiative, the Intel system firmware (BIOS) is evolving to be a multilayer, modular, scalable FW solution which fulfills all the modern FW requirements in a super complex HW IP centric world. The layers are shown in Figure 1.

The Platform Orchestration Layer sits between the SOC Abstraction Layer (SAL), as abstracted by the Scalable FSP interface, and the Payload Layer. The Platform Orchestration Layer coordinates the board-specific boot sequence, invoking the sFSP interfaces for any silicon specific work, and produces the interface to launch the payload environment along with industry standard tables that are an amalgam of silicon and platform, such as SMBIOS and ACPI.

_images/image3.png

Figure 2 Layers of Universal Scalable Firmware

Therefore, the missions of POL layer are:

  • Initialize the board by programming board specific resources and invoking the sFSP for SOC and/or XPU specific resources

  • Invoke payloads for OS boot environment and possible XPU and runtime.

3.1.2. POL Design Principles

POL is considered as the layer for platform code. It plays a major role in providing vendor specific features and mainboard-specific initialization, as distinct from the sFSP that is scoped to be SOC-specific. The POL will be the vehicle to convey policy into the sFSP, interact with the sFSP for initialization, and retrieve state information from the sFSP. The architectural design of a POL shall follow the below principles:

  • Compatibility - POL shall be compliant with FSP Specification and provide the configuration information into the sFSP and retrieve resultant output information from the sFSP.

  • Portability – POL will attempt to be as SOC independent as possible and allow for source level compatibility between different open source platform code frameworks such as EDKII, coreboot, oreboot, and U-Boot. The OS boot specific code is abstracted via payloads.

  • Determinism/Simplicity – POL should abstract SOC initialization through sFSP interfaces and have a simple boot flow.

3.1.3. Audience / Document scope

The audience for this document is BIOS/system firmware architects and developers that design or implement or consume Intel silicon initialization code. The document is intended to describe the architecture directions and requirements.

3.1.4. Terminology

Table 1: Terminology

Term

Definition

Config

Abstracted configuration information

Payload

OS boot container

sFSP

SOC initialization

3.1.5. Reference documents

The following documents are referenced in this specification.

Table 2: Reference Documents

Abbreviation

Document

Version

FSP_EAS

Intel® FSP External Architecture Specification v2.2: https://cdrdv2.intel.com/v1/dl/getContent/627153

Version 2.2 May 2020

PI_SPECS

Platform Initialization Specification: http://www.uefi.org/sites/default/files/resources/PI_1_4.zip

  • Volume I: PEI

  • Volume II: DXE CIS

  • Volume III: Shared Architecture Elements

  • Volume IV: SMM

  • Volume V: Standards

Version 1.4

April 2015

UEFI_SPEC

Unified Extensible Firmware Interface Specification: http://www.uefi.org/sites/default/files/resources/UEFI%202_5.pdf

Version 2.0 April 2015

FSP 2.3

https://cdrdv2.intel.com/v1/dl/getContent/644852

FSP Measurement

https://cdrdv2.intel.com/v1/dl/getContent/644001

YAML config

https://github.com/joshloo/fsp_yaml_cfg/tree/master/Tools/UserManuals

coreboot

https://github.com/coreboot/coreboot

Oreboot

https://github.com/oreboot/oreboot

Min platform

https://www.tianocore.org

u-boot

https://github.com/u-boot/u-boot

Slim bootloader

https://slimbootloader.github.io/

Payload

https://github.com/universalpayload/documentation

libspdm

https://github.com/DMTF/libspdm

3.2. Architecture

The following section describes the architecture of the POL.

3.2.1. POL Overview

Following the guiding principles in chapter 1.2, the high-level architecture of POL is shown in Figure 2. POL interfaces with the sFSP API specification, e.g. the 6 APIs and HOB/UPD defined in FSP 2.2 spec. On the other end, POL interfaces with the universal payload. It should invoke the payload API after providing board initialization.

Within the POL, it has several stages:

  • POL early initialization

    • Maps to

      • coreboot romstage

      • EDKII SEC/PEI

      • Slim bootloader stage 1

  • POL late initialization

    • Maps to

      • Coreboot ramstage

      • Slim bootloader stage 2

      • EDKII DXE

  • POL runtime

    • OEM SMM

POL High Level Architecture

Figure 3 POL High Level Architecture

Another aspect of the POL is to allow for maximum platform code re-use across different SOC generations.

POL re-use

Figure 4 POL re-use

Beyond re-use of platform code with different SOC’s, the POL should be re-useable across the most used or popular boot paradigms such as a full UEFI boot, LinuxBoot, VaultBoot or an embedded hypervisor.

Different Payloads

Figure 5 Different Payloads

The Universal Payload provides the right hand side interface. There could be additional payloads, such as an XPU initialization payload or a validation payload, such as FSP-V. But in either case the POL implementation should be largely independent of the SOC and the payload.

Finally, UFS allows for a world where there are various compositions of the firmware stack. This can include RUST-based firmware as either a payload or the platform layer implementation, as described in the figure below:

_images/image7.png

Figure 6 Modern language-based usage

This architecture is based upon https://github.com/jyao1/rust-firmware.

The rust API for FSP wrapper is at https://github.com/jyao1/rust-firmware/tree/master/rust-fsp-wrapper.

3.3. Configuration Introduction

The Platform Orchestration Layer (POL) is aimed to provide guidelines on writing platform code that leverage a Scalable Intel Firmware Support Package (sFSP) interface and payload to coordinate the overall platform initialization flow. It needs to expose configuration, as do the layers below.

To that end, YAML, which is a variant of JSON that allows for embedding comments, is employed in order to have a consistent language across various codebase configuration efforts.

3.3.1. Platform configuration

Goals of the Configuration Efforts

  • Normalize how configuration is done across various codebases and firmware domains (e.g. FSP, Boot Firmware, other on-board devices).

    • Deliver a unified API-based FW programming model across bootloaders for all Intel platforms, XPUs/SOCs, and IPs.

  • Make adoption by stakeholders/partners as pain-free as possible.

    • Prepare internal stakeholders, ecosystem partners, and customers to take advantage of the transition to a common configuration paradigm.

Why do this?

  • Intel has stakeholders and customers with investments in a variety of codebases, each of which have different underlying methods for firmware configuration.

  • This makes it difficult to have a consistent user/developer experience when configuring platforms based on various underlying firmware technologies. This is a problem for both internal stakeholders and Intel customers.

new common config tool diagram

New common config tool diagram

Tasks associated with the effort

Create a unified approach to configuring a platform regardless of the underlying codebase without requiring the product group to change what they’re doing in any significant way. Low touch/Enable via tools.

  • Assume no significant changes needed in the native codebase to support this solution.

  • Use YAML to express configuration data

  • Gap analysis between the various config methodologies

    • XML–>YAML, BSF–>YAML, VPD/HII/etc –> YAML

  • Create build-time tools to import codebase config data, modify it, and export it back into its native form.

    • This is especially important and useful when some codebases have config data scattered in many places, thus increasing the usability for developers in configuring the defaults of the codebase.

  • Runtime config

    • Scripting in runtime may be needed for manufacturing line usage etc – something to consider.

  • Telemetry?

    • Address how we expose necessary data from the machine.

  • Port ESRT content into an ACPI context.

    • More easily enable firmware updates without an underlying UEFI infrastructure/assumption.

Although the POL strives to be SOC independent, the system board’s SOC, with its respective sFSP, and the usage of payloads, may require different configuration. To that end, a consistent set of YAML based configuration will be exposed to the system board builder and platform user to configure the various elements.

3.3.1.1. YAML based settings

Although the POL strives to be SOC independent, the system board’s SOC, with its respective sFSP, and the usage of payloads, may require different configuration. To that end, a consistent set of YAML based configuration will be exposed to the system board builder and platform user to configure the various elements.

YAML based configuration will be provided to abstract all of the platform configurable elements

  • sFSP UPD

  • Platform configuration

    • PCD/VFR for EDKII

    • KConfig for coreboot/oreboot/u-boot

    • DSC for slim bootloader

    • YAML native for XPU payload

3.3.1.2. Example configuration

An example of an often configurable object for the platform developer is GPIO.

An example of GPIO configuration is as follows:

  • $ACTION :

page : GIO

  • GPIO_CFG_DATA :

  • !expand { CFGHDR_TMPL : [ GPIO_CFG_DATA, 0x400, 1, 0 ] }

  • GPIO_CFG_HDR :

  • GpioHeaderSize :

length : 0x01

value : _LENGTH_GPIO_CFG_HDR_

  • GpioBaseTableId :

length : 0x01

value : 0xFF

  • GpioItemSize :

length : 0x02

value : 8

  • GpioItemCount :

length : 0x02

value : (_LENGTH_GPIO_CFG_DATA_ - _LENGTH_GPIO_CFG_HDR_ - 8) / 8

# Bit start offset within each GPIO entry array to identify a GPIO pin uniquely. EX: GPIO group id + pad id

# Offset is 2nd DWORD BIT16 = 1 * 32 + 16 = 48

  • GpioItemIdBitOff :

length : 0x01

value : 48

# Bit length within each GPIO entry array to identify a GPIO pin uniquely.

# Length is 2nd DWORD BIT16 to BIT28 = 13

  • GpioItemIdBitLen :

length : 0x01

value : 13

# Bit offset within each GPIO entry array to indicate SKIP a GPIO programming

# Offset is 2nd DWORD BIT31 = 63

  • GpioItemValidBitOff :

length : 0x01

value : 63

  • GpioItemUnused :

length : 0x01

value : 0

# Need 1 bit per GPIO. So this mask byte length needs to be at least (GpioNumber + 7) / 8

# Padding can be added to let the whole length aligned at DWORD boundary

  • GpioBaseTableBitMask :

length : 38

value : {0}

  • GpioTableData :

length : 0

value : 0

3.3.2. 1.1.1 Example implementation

An example of implementation in EDKII is Intel Seamless Board Configuration (SBC). This feature provides a standardized and centralized interface for various board HW configuration, including GPIO, PCIe Clock, USB OC, DRAM, I2C, etc. The interface currently is leveraging Structured PCD in VPD which allows both manually and tool assisted modification for different HW setting in EDK2 Platform Payload.

SBC also supports multiple board configuration scenario with board identifier mapped to SkuId in EDKII PCD.

_images/image8.png

Figure 6 Board configuration

Example implementation with Structured PCD:

gBoardModuleTokenSpaceGuid.VpdPcdBoardGpioTable|*|{CODE({

{GPIO_PIN_1, {GpioSettingA,GpioSettingB, GpioSettingC, …}},
{GPIO_PIN_2, {GpioSettingA,GpioSettingB, GpioSettingC, …}},

{0x0} // terminator

})}

Components in EDKII Bootloader will consume these HW configuration while the configuration data is already selected based on SkuId during POST. Then these setting will be applied into silicon or board HW via sFSP. Necessary information will also be wrapped and passed to OS, such as GPIO related setting in ACPI Table.

3.3.3. Shareable platform code

For the platform implementation, there are two means of code sharing. One way to share content is via binary universal payloads, and the other is via source code.

TBD – example source code. Cite moving of PciBus DXE driver to slim bootloader stage 2 code

OpenSPDM example as source code for sharing across POL implementations.

Advanced features represent a set of platform technologies that are not needed for basic boot. These features provide a way to extend the platform firmware capabilities.

For these features to be sharable and extensible, they must adopt a high-cohesive, low-coupling design. This means an advanced feature should be mostly self-contained and expose a set of well defined interfaces that can be called by components outside the feature scope.

An advanced feature should not directly depend on another advanced feature. Such a dependency should be resolved via an integration layer (e.g. Board layer). The following represents a high level design of Advanced Features.

AFP1

AFP2

AFP3

AFP4

Board Layer

3.3.4. Advanced feature details

The low-level design and implementation of Advanced feature may vary based on boot loaders and other preferences.

The EDKII Min Platform boot loader follows a rich set of design guidelines conforming EDKII software framework and UEFI specification.

Examples of construction of a Min Platform can be found at https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/MinPlatformPkg/Docs/A_Tour_Beyond_BIOS_Open_Source_IA_Firmware_Platform_Design_Guide_in_EFI_Developer_Kit_II%20-%20V2.pdf

3.3.4.1. Shareable platform code - definition

+In this specification, the shareable platform code focuses on source code sharing. Binary sharing should be considered in scalable FSP.

  1. The shareable platform code SHALL be reusable by multiple bootloaders, including but not limited, to EDKII, slim bootloader, coreboot.

  2. The shareable platform code SHOULD be reusable across different boot phase, such as EDKII PEI/DXE/SMM phase, the coreboot ROM/RAM stage. This highly depends upon the use case.

  3. The shareable platform code MAY be used for other firmware. For example, the libspdm library may be used for system firmware, BMC firmware, or even device firmware. It also depends upon the use case – if there is business need for sharing.

3.3.4.2. Shareable platform code - guideline

  1. Don’t consume any boot load specific API. For example, UEFI boot services, PCI IO Protocol.

  2. Don’t consume standard C library. Not all boot load includes standard C library.

  3. Use static link library if possible. Don’t use dynamic link library.

  4. Use heap carefully. Some environment might not have heap.

  5. Use global variable carefully. Some environment may only support read-only variable because the code runs on the flash.

  6. Don’t use inline assembly. Some build environment may not support inline assembly.

  7. Another guideline is to not expose internal function in public header file. The internal header file should be hidden.

  8. Define the boot loader provided library dependency clearly, such as Hardware Abstract Layer (HAL). It can make library porting easier.

  9. Define the boot loader caller provided function dependency clearly, such as a callback function.

3.3.4.3. Shareable platform code – RUST binding API

  1. Include length parameter for any buffer.

  2. Have single owner for one buffer. If the caller allocates the buffer, the caller shall free the buffer.

  3. Define the contract between the caller and callee. E.g. If the input buffer is trusted or untrusted?

  4. Define the error behavior clearly. Return? Deadloop? Assert?

3.3.5. Interface definitions

3.3.5.1. Shareable platform code APIs

3.3.5.1.1. Min Platform Advanced Feature Packages (AFP) in EDKII, coreboot 3rd party directory code

Provide example of the Pci enumeration code/library

Show the generic code such as sharable libspdm

3.3.5.2. Shareable board ASL

3.3.5.2.1. TBD

3.3.5.3. Shareable platform code APIs – Rust bindings

A Rust library can be created on top of C - API. For example:

In firmware, we have below example:

  • r-efi defines a set of Rust style UEFI data structure.

  • uefi-rs provides a set of UEFI services interface in Rust.

  • rust-fsp-wrapper provides a set of Intel FSP APIs for the FSP wrapper.

3.4. XPU considerations

One of the goals of the USF effort is to help support all classes of silicon , namely XPU’s. An XPU can be a CPU, such as the SOC based upon Intel Core, Intel Atom, RISC-V or ARM. In addition, the XPU can include integrated or discrete graphics (iGFX/dGFX), FPGA, AI, networking, or acceleration.

To that end, there are various aspects of the XPU support.

These include configuration, update, monitoring, and access, both during the pre-OS and at OS runtime. In the future the latter may move into level 0, but for now the USF shall treat these.

Like other aspects of USF, XPU considerations are in the POL specification since the platform is where all of the system components come together.

3.4.1. Configuration

To configure the XPU, a canonical YAML based configuration file will be provided.

3.4.1.1. Build time

3.4.1.2. Post ship

3.4.1.2.1. Pre-OS
3.4.1.2.2. Runtime

3.4.2. Initialization

Initialization can include having the XPU as part of the sFSP, a dedicated payload, a UEFI or legacy BIOS option ROM, or some open source POL portable library.

3.4.2.1. Open source portable initialization code

3.4.2.2. Dedicated payload

3.4.2.3. Option ROM (e.g., dGFX or networking HBA)

3.4.2.4. sFSP element (e.g., iGFX in Core CPUs)

3.4.3. Update

It is critical to support both the factory time integration of the XPU support into the IFWI and/or post ship update of XPU support code.

3.4.3.1. Slim bootloader update payload

3.4.3.1.1. Overview

SBL embedded a built-in Firmware Update (FWU) payload to perform a secure and power fail-safe firmware update flow. It contains redundant boot partitions and depends on hardware assisted boot partition switch to support fail-safe update.

SBL provides abstracted ACPI/WMI interface to trigger FWU flow, EDK2 similar capsule update mechanism to pass the new firmware to bootloader, and EDK2 similar way to report the FWU status back to OS through ACPI table.

3.4.3.1.2. Firmware Update Flow

SBL firmware update flow utilizes redundant boot partition to perform firmware update in a reliable way. It involves the following high-level steps:

  • Boot from Partition A

  • Update Partition B

  • Activate Partition B

  • Reboot

  • Boot from Partition B

  • Update Partition A

  • Activate Partition A

  • Reboot

  • Report Firmware Update status

  • Terminate firmware update flow.

  • Reset system to continue booting to operating system.

Below is a detailed FWU flow chart for SBL.

_images/image9.png

Figure 7

  • Firmware Update capsule is copied to designated location. This location is configurable through SBL configuration options.

  • Firmware update is triggered from SBL shell or from Operating system and followed by a system reset.

  • SBL detects firmware update signal and sets platform into firmware update mode.

  • SBL identifies firmware update mode and loads firmware update payload to start update flow.

  • Firmware Update payload gathers capsule image from selected media and verifies capsule data. If successful, continues with firmware update.

  • Firmware update payload initializes state machine and identifies the update images in the capsule.

  • FWU payload loops through and updates each firmware identified in the capsule image.

  • FWU records update status after each firmware update.

  • If the firmware is requesting reset after update, reset the system to continue updating other firmware in the capsule.

  • In case of a power failure, FWU payload will use the state machine stored in flash to resume from the interrupted state.

3.4.3.1.3. Firmware Update Triggering

SBL provides a platform independent abstracted way of triggering firmware update from operating system through ACPI or WMI interfaces.

SBL provides common ACPI methods, DWMI.WQ00 for read and DWMI.WS00 for write to a platform specific chipset register that can survive a reset to signal firmware update. This ACPI method can be called by driver or application to request triggering a firmware update. On the following reboot flow, once the firmware update signal is detected, this signal will be stored into flash so that the following firmware update flow can resume in case of a power failure in the middle of the process.

For OS that supports WMI, such as Windows, SBL further exposes AcpiFirmwareCommunication WMI service through ACPI table to allow triggering firmware updates directly using WMI from applications.

3.4.3.1.4. Firmware Update Status

SBL reports firmware update status through custom defined Firmware Update status (FWST) ACPI table. FWST ACPI table will be available as part of RSDT and can be identified with a table signature “FWST”. FWST ACPI table makes use of EFI_SYSTEM_RESOURCE_TABLE defined in UEFI specification to report firmware update status. It adds additional ACPI header on top of it to make it conform to ACPI speciation. OS can use this ACPI table to retrieve the previous firmware update information.

3.4.3.2. UEFI capsule update

3.4.3.3. AB update of payload for coreboot

3.4.4. Monitoring

The ability to ascertain status of the platform and XPU’s has various modalities.

3.4.4.1. UEFI tables

3.4.4.2. ACPI

3.5. POL examples

This chapter gives a reference implementation of POL under EDKII framework. Below shows the code layout that POL has a dedicated package to hold all POL related code.

3.5.1. Slim bootloader

Slim Bootloader (SBL) is a flexible, lightweight, and open-source reference boot loader solution designed for Intel platforms. SBL is architected with a modular approach by providing very basic hardware initialization in bootloader, then launching a payload to boot to final OS or application. The payload is flexible and can be at user’s choice to meet special needs. The SBL overall architecture is shown in the diagram below:

_images/image10.png

Figure 8: SBL Architecture

SBL takes a linear staged boot approach to initialize the platform. As illustrated in the diagram below, in each stage, SBL utilizes Intel® FSP API interfaces to initialize the silicon and utilizes static library interfaces to initialize the board.

_images/image11.png

Figure 9: SBL Linear Staged Boot Approach

These static library interfaces are aligned with EDK2 base library implementation to the abstract board initialization API. For examples, see Figure 9 above and GPIO initialization, ACPI initialization, etc.

The detailed SBL stages are listed in the table below:

Stage

Description

Stage 1A

Stage 1A contains reset vector and is first stage to gain control. It is responsible for very basic platform execution environment initialization to enable following stage execution. It includes temporary memory, debug port, etc.

Stage 1B

Stage 1B is the “pre-memory” stage and is responsible for loading configuration data and initialization system main memory. After memory is available, it will load and verify Stage2 for execution.

Stage 2

Stage 2 is the “post-memory” stage and is responsible for all initialization the remaining platform, including chipset, CPU, I/O, ACPI, PCI, etc.

Payload

Payload is the bridge between bootloader and the OS. It provides standard boot device initialize to further load, verify and launch OS images. It also performs specific actions, such as firmware update.

As stated above, SBL utilizes static library class to abstract the API interfaces for platform initialization. These libraries are written in pure C language so that it can easily be shared between different boot solutions. For example, many base library instances in EDK2 MdePkg are directly leveraged by SBL. Many other libraries, such as SoC access libraries, feature libraries are also ported from corresponding EDK2 libraries through removing UEFI specific dependencies. In addition, ACPI ASL files are also borrowed from EDK2 directly. These sharable libraries and files make it easier to quickly enable a platform using the boot solution at user’s choice.

_images/image12.png

3.5.2. u-boot

U-Boot can be fabricated as a POL or a payload.

3.5.3. Oreboot

Oreboot is a RUST-based POL example

3.5.4. coreboot

coreboot is a POL example

3.5.5. EDKII

EDKII can also be used to create a payload, such as https://github.com/tianocore/edk2/tree/master/UefiPayloadPkg.

3.5.5.1. Components

Components in EDKII based firmware can be separated into three categories:

  • EDKII Bootloader

  • UEFI Universal Payload

  • EDKII UEFI Platform Payload (Optional)

_images/image13.png

Figure 10

The system boot starts from EDKII Bootloader where the FSP is invoked to initialize the silicon. Then the Bootloader follows the Payload specification to load and start UEFI Universal Payload. It may pass additional FV location information to UEFI Universal Payload which tells the optional EDKII UEFI Platform Payload.

EDKII Bootloader consists of reset vector code, necessary platform specific code and EDKII generic code that launches FSP. In the end of EDKII Bootloader, it transfers the control from EDKII Bootloader to UEFI Universal Payload through DxeIpl PEIM. Each platform vendor develops its EDKII Bootloader and the implementations for different platforms are different.

UEFI Universal Payload consists of all the platform agnostic drivers that prepare the UEFI OS booting environment. For example, the RTC driver to support UEFI time services, the MTC driver to support the UEFI Monotonic Counter services. The “Universal” in the name stands for the goal that the same payload binary can be used by different bootloaders and different platforms. There is only one implementation instance of the UEFI Universal Payload. For example, Slim bootloader and EDKII Bootloader can boot to UEFI OS by using the same UEFI Universal Payload. All the SOC and platform specific information is abstracted in EDKII Bootloader and passed to UEFI Universal Payload. The abstraction format is defined by Payload specification.

EDKII UEFI Platform Payload is an optional component. It consists of platform specific implementations:

_images/image14.png

that must be done in payload phase.

Theoretically this component can be eliminated by moving all implementations to EDKII Bootloader.

Figure 11

3.5.5.2. Data Flow

EDKII Bootloader passes SOC and platform information through HOBs to UEFI Universal Payload. UEFI Universal Payload interacts with EDKII UEFI Platform Payload through Protocols. EDKII Bootloader can use any mechanism to pass information to EDKII UEFI Platform Payload since both are owned by the platform vendor.

Universal Payload, UEFI Platform Payload, and EDKII Bootloader

Figure 12: Universal Payload, UEFI Platform Payload, and EDKII Bootloader