soc/intel/common/block/rtc/rtc.c: control Top Swap via CMOS option

Toggle the RTC BUC control bit for Top Swap bootblock selection based on
the "attempt_slot_b" flag CMOS option, allowing to select which of the
BOOTBLOCK or TOP_SWAP regions to boot from.

This means that after an update, the CMOS option can be set to boot from
the newer TOP_SWAP bootblock. In case of failure, CMOS can be cleared to
revert to the known-good base BOOTBLOCK.

This is part of ongoing implementation of a redundancy feature proposed
on the mailing list:
https://mail.coreboot.org/archives/list/coreboot@coreboot.org/thread/C6JN2PB7K7D67EG7OIKB6BBERZU5YV35/

Switching between identical bootblocks doesn't impact further boot flow,
i.e. selecting which FMAP region to load consecutive stages from.
That is to be enabled in following patches.

So far tested and enabled for the Alder Lake SoC.

TEST=Boot VP6650, setting the attempt_slot_b flag to different values,
observing that it resets/continues booting correctly.

Change-Id: Ib183a1f72ee8585b2c4ad4376344de33ff54cbb9
Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90042
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
This commit is contained in:
Filip Lewiński 2025-11-21 12:18:58 +01:00 committed by Matt DeVillier
commit 51e99de558
4 changed files with 37 additions and 1 deletions

View file

@ -2,6 +2,7 @@
#include <bootblock_common.h>
#include <intelblocks/fast_spi.h>
#include <intelblocks/rtc.h>
#include <intelblocks/systemagent.h>
#include <intelblocks/tco.h>
#include <intelblocks/uart.h>
@ -30,4 +31,7 @@ void bootblock_soc_init(void)
/* Programming TCO_BASE_ADDRESS and TCO Timer Halt */
tco_configure();
if (CONFIG(INTEL_TOP_SWAP_OPTION_CONTROL))
sync_rtc_buc_top_swap();
}

View file

@ -57,6 +57,15 @@ config INTEL_TOP_SWAP_SEPARATE_REGIONS
facilitate firmware updates using the Top Swap as Slot A/Slot B redundancy.
Requires a custom .fmd with the regions added at the end.
config INTEL_TOP_SWAP_OPTION_CONTROL
bool "Toggle the Top Swap functionality using a CMOS option"
depends on INTEL_TOP_SWAP_SEPARATE_REGIONS && USE_OPTION_TABLE && SOC_INTEL_ALDERLAKE
default n
help
Switch between the Top Swap bootblocks using the "attempt_slot_b" CMOS
option. Note that the option must be present in the board's cmos.layout.
file.
endif
config SOC_INTEL_COMMON

View file

@ -3,6 +3,8 @@
#ifndef SOC_INTEL_COMMON_BLOCK_RTC_H
#define SOC_INTEL_COMMON_BLOCK_RTC_H
#define TOP_SWAP_ENABLE_CMOS_OPTION "attempt_slot_b"
/* Top swap feature enable/disable config */
enum ts_config {
TS_DISABLE,
@ -32,6 +34,11 @@ void configure_rtc_buc_top_swap(enum ts_config ts_state);
*/
enum ts_config get_rtc_buc_top_swap_status(void);
/*
* Set/unset the top swap bit based on TOP_SWAP_ENABLE_CMOS_OPTION state
*/
void sync_rtc_buc_top_swap(void);
/* Set RTC Configuration BILD bit. */
void rtc_conf_set_bios_interface_lockdown(void);
#endif /* SOC_INTEL_COMMON_BLOCK_RTC_H */

View file

@ -2,8 +2,10 @@
#include <intelblocks/pcr.h>
#include <intelblocks/rtc.h>
#include <soc/pcr_ids.h>
#include <option.h>
#include <pc80/mc146818rtc.h>
#include <reset.h>
#include <soc/pcr_ids.h>
/* RTC PCR configuration */
#define PCR_RTC_CONF 0x3400
@ -53,4 +55,18 @@ enum ts_config get_rtc_buc_top_swap_status(void)
else
return TS_DISABLE;
}
void sync_rtc_buc_top_swap(void)
{
uint8_t cmos_slotb_option, topswap_control_bit;
cmos_slotb_option = get_uint_option(TOP_SWAP_ENABLE_CMOS_OPTION, 0);
topswap_control_bit = get_rtc_buc_top_swap_status();
printk(BIOS_INFO, "Top Swap: CMOS option state: %d\n", cmos_slotb_option);
printk(BIOS_INFO, "Top Swap: RTC BUC control bit: %d\n", topswap_control_bit);
if (cmos_slotb_option != topswap_control_bit) {
configure_rtc_buc_top_swap(cmos_slotb_option);
printk(BIOS_INFO, "Top Swap: RTC BUC control bit set to: %d, platform reset is necessary\n", get_rtc_buc_top_swap_status());
board_reset();
}
}
#endif