Intel Top Swap based A and B redundancy

This document describes a simple firmware A and B redundancy scheme based on Intel PCH Top Swap. The scheme maintains two firmware slots and uses the Top Swap control bit to choose which bootblock runs on boot. Each bootblock then continues booting from a matching CBFS region, so switching the Top Swap state switches the active slot.

The Intel Top Swap feature allows the PCH to take two physically topmost chunks of the BIOS flash chip, and decide in which order to map them - effectively allowing to swap the two chunks, and deciding which of them lands at the reset vector.

For background on the hardware mechanism, consult the Intel documentation for your PCH and platform and search for sections named similarly to “Top Swap”, “Top Swap Block Size (TSBS)”, or “Boot Block Update Scheme”. The exact document title and section naming varies between generations. The Alder Lake implementation for example has been developed basing mainly on ADL-P EDS Vol 1&2, sections:

  • 3.2.1 Boot Block Update Scheme,

  • 9.70 PCH Descriptor Record 69 (Flash Descriptor Records),

  • 31.3.2 Backed Up Control (BUC),

  • 2.1.17 BIOS Control (ESPI_BC)

Flash layout and CBFS regions

The implementation assumes four FMAP regions that are CBFS formatted and that use the following names.

The bootblocks live in BOOTBLOCK and TOPSWAP. Each of these is a relatively small CBFS region that contains a bootblock image and any additional files that must reside next to it for early boot on a given platform. These regions must exist in the board’s .fmd file and must be sized with headroom for growth

  • keeping in mind the FIT table and Boot Guard ACM’s must reside in the same region as the bootblock.

The main firmware CBFS regions are COREBOOT and COREBOOT_TS. COREBOOT is typically the base slot and is often placed under write protection, along with BOOTBLOCK. COREBOOT_TS is the alternate slot and is typically left writable so it can be replaced by an update mechanism, along with TOPSWAP.

The BOOTBLOCK and TOPSWAP regions are expected to be placed in the flash area covered by the Top Swap configuration. The sizes of the regions must match and be equal to the corresponding field in the IFD. coreboot can adjust the The Top Swap size (also called Top Swap Block Size in Intel’s documentation) field in the descriptor during the build. This is controlled by CONFIG_INTEL_IFD_SET_TOP_SWAP_BOOTBLOCK_SIZE and uses CONFIG_INTEL_TOP_SWAP_BOOTBLOCK_SIZE as the requested size.

Kconfig options

The option CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK creates two copies of the bootblock.

The option CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS changes where the bootblocks are stored. When it is disabled, both are stored in the primary CBFS region as on existing platforms. When it is enabled, they are placed in the BOOTBLOCK TOPSWAP FMAP regions. It also places copies of the following stages and required files from the COREBOOT region in the COREBOOT_TS region.

If CBFS verification is enabled, the image build checks verification status for all main CBFS regions that are part of the redundancy configuration, not only for COREBOOT.

The option CONFIG_INTEL_TOP_SWAP_OPTION_CONTROL enables runtime control of the Top Swap control bit based on a CMOS option. In tree, this option is constrained to specific Intel SoCs. For a board to use it, the SoC bootblock must apply the setting early enough for writes to the Top Swap control bit to take effect.

To reduce per board configuration burden, CONFIG_TOP_SWAP_REDUNDANCY exists as a convenience option that selects the relevant pieces for Top Swap based redundancy. Even with this convenience option enabled, a board still must provide an appropriate .fmd layout and a cmos.layout entry as described below.

Boards that use Top Swap based redundancy must enable CMOS option support and ensure the option backend can read options at boot time. The symbol MAINBOARD_NEEDS_CMOS_OPTIONS exists to indicate this dependency. Please note that not every SoC supports this functionality.

CMOS option and when it is applied

Runtime Top Swap selection is controlled by a CMOS option named attempt_slot_b. The name is defined as TOP_SWAP_ENABLE_CMOS_OPTION in src/soc/intel/common/block/include/intelblocks/rtc.h. A board enabling CONFIG_INTEL_TOP_SWAP_OPTION_CONTROL must provide a CMOS entry with this exact name in its cmos.layout file.

The function sync_rtc_buc_top_swap() in src/soc/intel/common/block/rtc/rtc.c implements the synchronization logic. It reads the CMOS option via get_uint_option(), reads the current Top Swap state from the RTC BUC register, compares the two, and if they differ it programs the new state and resets the platform. The reset is intentional and ensures the new Top Swap state is in effect from the beginning of the subsequent boot.

The SoC bootblock must call sync_rtc_buc_top_swap() early in bootblock_soc_init() when CONFIG_INTEL_TOP_SWAP_OPTION_CONTROL is enabled. This must happen before the platform locks down the relevant interfaces such that Top Swap state changes no longer take effect.

Because the CMOS option is applied in bootblock, a mismatch between the requested slot and the current Top Swap state causes a very early reset. The next boot then starts directly from the selected slot.

CBFS region selection

The choice of the main CBFS region is made in cbfs_get_boot_device() in src/lib/cbfs.c. Instead of always locating COREBOOT, the code calls cbfs_fmap_region_hint() to obtain the FMAP region name and then locates that region.

The default cbfs_fmap_region_hint() implementation is a weak symbol that returns COREBOOT, so platforms that do not override it retain the existing behavior.

Intel Top Swap platforms provide a strong definition of cbfs_fmap_region_hint() in src/soc/intel/common/block/rtc/rtc.c. When CONFIG_INTEL_TOP_SWAP_OPTION_CONTROL is enabled and the Top Swap control bit is set, it returns COREBOOT_TS. Otherwise it returns COREBOOT. cbfs_get_boot_device() logs the selected region and stops with an error if the region cannot be found in FMAP.

This is deliberately based on the actual hardware Top Swap state rather than on reading CMOS again. At the point where cbfs_fmap_region_hint() is used, the option table is not reliably available, because the cmos_layout.bin backing the option table is itself stored in CBFS.

For the override to apply in a given stage, the RTC block code must be linked into that stage. The common RTC block is built into multiple stages and is also built into postcar to ensure the hint function is available when CBFS is accessed there.

Boot flow summary

A typical update and rollback sequence is as follows.

The platform starts in slot A with Top Swap disabled. The hardware boots from the BOOTBLOCK and coreboot continues from the COREBOOT CBFS region.

An update writes into the TOPSWAP and COREBOOT_TS regions, then sets the attempt_slot_b CMOS option.

On the next boot, sync_rtc_buc_top_swap() observes that the CMOS request differs from the current hardware Top Swap state, programs the new Top Swap state, and resets the platform.

After the reset, the hardware starts from the bootblock corresponding to the new Top Swap state. When coreboot later initializes its boot device, cbfs_fmap_region_hint() sees the Top Swap state and selects COREBOOT_TS, so the remainder of the boot uses the updated slot.

Clearing CMOS or resetting attempt_slot_b triggers the same sequence in the opposite direction, returning the platform to COREBOOT without requiring external flashing.

Troubleshooting notes

If the platform does not switch slots as expected, confirm that the attempt_slot_b entry exists in cmos.layout and that the option table backend is in use so get_uint_option() can read it in bootblock.

If the platform resets but still boots from COREBOOT, confirm that the RTC block implementation providing cbfs_fmap_region_hint() is linked into the stage that performs CBFS initialization on your platform.

If the build fails to boot after enabling separate regions, confirm that the .fmd file defines BOOTBLOCK, TOPSWAP, COREBOOT, and COREBOOT_TS as CBFS regions and that the platform Top Swap configuration matches the reserved bootblock and Top Swap region placement and sizing.

Serial logs should show the CMOS request and the RTC BUC control bit values during bootblock, followed by a log line indicating which CBFS region is being used.