Documentation/soc/intel/redundancy.md: add
Add documentation for the Intel PCH Top Swap based A/B redundancy mechanism. Describe the BOOTBLOCK and TOPSWAP bootblock regions, COREBOOT and COREBOOT_TS CBFS regions, the attempt_slot_b CMOS option and its application time, and how the active CBFS region is selected based on the Top Swap state. This follows the A/B redundancy proposal discussed on the coreboot mailing list: https://mail.coreboot.org/archives/list/coreboot@coreboot.org/thread/C6JN2PB7K7D67EG7OIKB6BBERZU5YV35/ Change-Id: I1b88989201e209b2f69964c067c432ff82a0057e Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/90412 Reviewed-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
aa16822643
commit
95461ee3df
2 changed files with 175 additions and 0 deletions
|
|
@ -17,4 +17,5 @@ Apollolake <apollolake/index.md>
|
|||
CSE FW Update <cse_fw_update/cse_fw_update.md>
|
||||
Xeon Scalable processor <xeon_sp/index.md>
|
||||
Skylake/Kaby Lake BootGuard bypass <deguard.md>
|
||||
Intel Top Swap based A/B redundancy <redundancy.md>
|
||||
```
|
||||
|
|
|
|||
174
Documentation/soc/intel/redundancy.md
Normal file
174
Documentation/soc/intel/redundancy.md
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue