From 388fb318add4257a74714e11b670a53aa367fe02 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 3 Nov 2025 18:40:45 -0600 Subject: [PATCH] soc/intel/common: Add opt-in runtime control for BIOS SMM write protection Add support for runtime control of BIOS lock (BOOTMEDIA_SMM_BWP) via the CFR option API. This allows users to enable/disable BIOS write protection in SMM through the setup menu when explicitly enabled. The implementation adds a new "bios_lock" CFR option that: - Controls SMM BIOS write protection at runtime - Sets EISS (Enable InSMM.STS) when enabled - Enables SPI/LPC write protection in SMM - Prevents unauthorised BIOS modifications outside SMM Security model: - Runtime control is opt-in via BOOTMEDIA_SMM_BWP_RUNTIME_OPTION config - When disabled, the option is suppressed in CFR (not exposed in UI) - Compile-time CONFIG(BOOTMEDIA_SMM_BWP) serves as the default/fallback - Protects against unauthorised EFI variable modifications, bypassing BIOS lock when the runtime option is not enabled The option is integrated into Intel's common lockdown code and SMI handlers, replacing compile-time-only checks with conditional runtime lookups where BOOTMEDIA_SMM_BWP_RUNTIME_OPTION is enabled. Change-Id: Ie3b63462501e0d204c33dc3f8a006b73da0899d3 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/89919 Reviewed-by: Werner Zeh Tested-by: build bot (Jenkins) --- src/security/lockdown/Kconfig | 8 ++++++++ src/security/lockdown/lockdown.h | 16 ++++++++++++++++ .../common/block/include/intelblocks/cfr.h | 19 +++++++++++++++++++ src/soc/intel/common/block/smm/smihandler.c | 6 ++++-- src/soc/intel/common/pch/lockdown/lockdown.c | 6 ++++-- src/southbridge/intel/common/finalize.c | 4 +++- src/southbridge/intel/common/spi.c | 4 +++- 7 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 src/security/lockdown/lockdown.h diff --git a/src/security/lockdown/Kconfig b/src/security/lockdown/Kconfig index 95a768a148..ec76cea213 100644 --- a/src/security/lockdown/Kconfig +++ b/src/security/lockdown/Kconfig @@ -107,6 +107,14 @@ config BOOTMEDIA_SMM_BWP while also preventing unauthorized writes through the internal controller. Note that this breaks flashconsole, since the flash becomes read-only. +config BOOTMEDIA_SMM_BWP_RUNTIME_OPTION + bool "Boot media only writable in SMM can be controlled via option API" + depends on BOOTMEDIA_SMM_BWP + depends on DRIVERS_OPTION_CFR + help + Provide a runtime option "bios_lock" to enable or disable SMM BIOS Write Protection + via the option API. + choice prompt "SPI Flash write protection duration" default BOOTMEDIA_SPI_LOCK_REBOOT diff --git a/src/security/lockdown/lockdown.h b/src/security/lockdown/lockdown.h new file mode 100644 index 0000000000..b81e636c32 --- /dev/null +++ b/src/security/lockdown/lockdown.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SECURITY_LOCKDOWN_LOCKDOWN_H +#define SECURITY_LOCKDOWN_LOCKDOWN_H + +#include +#include + +static inline bool enable_smm_bios_protection(void) +{ + if (CONFIG(BOOTMEDIA_SMM_BWP_RUNTIME_OPTION)) + return get_uint_option("bios_lock", CONFIG(BOOTMEDIA_SMM_BWP)); + return CONFIG(BOOTMEDIA_SMM_BWP); +} + +#endif /* SECURITY_LOCKDOWN_LOCKDOWN_H */ diff --git a/src/soc/intel/common/block/include/intelblocks/cfr.h b/src/soc/intel/common/block/include/intelblocks/cfr.h index 15dcacab23..e31af7f4c9 100644 --- a/src/soc/intel/common/block/include/intelblocks/cfr.h +++ b/src/soc/intel/common/block/include/intelblocks/cfr.h @@ -150,5 +150,24 @@ static const struct sm_object intel_tme = SM_DECLARE_BOOL({ .default_value = CONFIG(INTEL_TME), }, WITH_CALLBACK(update_intel_tme)); +/* BIOS Lock */ +static void update_smm_bwp(struct sm_object *new) +{ + if (!CONFIG(BOOTMEDIA_SMM_BWP_RUNTIME_OPTION)) + new->sm_bool.flags |= CFR_OPTFLAG_SUPPRESS; +} + +static const struct sm_object bios_lock = SM_DECLARE_ENUM({ + .opt_name = "bios_lock", + .ui_name = "BIOS Lock", + .ui_helptext = "Enable BIOS write protection in SMM. When enabled, the boot media" + " (SPI flash) is only writable in System Management Mode, preventing" + " unauthorized writes through the internal controller.", + .default_value = CONFIG(BOOTMEDIA_SMM_BWP), + .values = (const struct sm_enum_value[]) { + { "Disabled", false }, + { "Enabled", true }, + SM_ENUM_VALUE_END }, +}, WITH_CALLBACK(update_smm_bwp)); #endif /* SOC_INTEL_CMN_CFR_H */ diff --git a/src/soc/intel/common/block/smm/smihandler.c b/src/soc/intel/common/block/smm/smihandler.c index cd78de26c3..1af03739d2 100644 --- a/src/soc/intel/common/block/smm/smihandler.c +++ b/src/soc/intel/common/block/smm/smihandler.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -352,7 +354,7 @@ static void finalize(void) /* Re-init SPI driver to handle locked BAR */ fast_spi_init(); - if (CONFIG(BOOTMEDIA_SMM_BWP)) { + if (enable_smm_bios_protection()) { fast_spi_enable_wp(); set_insmm_sts(false); } @@ -443,7 +445,7 @@ void smihandler_southbridge_tco( fast_spi_clear_sync_smi_status(); /* If enabled, enforce SMM BIOS write protection */ - if (CONFIG(BOOTMEDIA_SMM_BWP) && fast_spi_wpd_status()) { + if (enable_smm_bios_protection() && fast_spi_wpd_status()) { /* * BWE is RW, so the SMI was caused by a * write to BWE, not by a write to the BIOS diff --git a/src/soc/intel/common/pch/lockdown/lockdown.c b/src/soc/intel/common/pch/lockdown/lockdown.c index eec3beb01b..ff7ca959fc 100644 --- a/src/soc/intel/common/pch/lockdown/lockdown.c +++ b/src/soc/intel/common/pch/lockdown/lockdown.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -81,7 +83,7 @@ static void fast_spi_lockdown_cfg(int chipset_lockdown) fast_spi_set_bios_interface_lock_down(); /* Only allow writes in SMM */ - if (CONFIG(BOOTMEDIA_SMM_BWP)) { + if (enable_smm_bios_protection()) { fast_spi_set_eiss(); fast_spi_enable_wp(); } @@ -102,7 +104,7 @@ static void lpc_lockdown_config(int chipset_lockdown) lpc_set_bios_interface_lock_down(); /* Only allow writes in SMM */ - if (CONFIG(BOOTMEDIA_SMM_BWP)) { + if (enable_smm_bios_protection()) { lpc_set_eiss(); lpc_enable_wp(); } diff --git a/src/southbridge/intel/common/finalize.c b/src/southbridge/intel/common/finalize.c index 490bdae74e..759ab8ea2d 100644 --- a/src/southbridge/intel/common/finalize.c +++ b/src/southbridge/intel/common/finalize.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -45,7 +47,7 @@ void intel_pch_finalize_smm(void) pci_write_config32(PCI_DEV(0, 27, 0), 0x74, pci_read_config32(PCI_DEV(0, 27, 0), 0x74)); - if (CONFIG(BOOTMEDIA_SMM_BWP)) + if (enable_smm_bios_protection()) write_pmbase16(SMI_EN, read_pmbase16(SMI_EN) | TCO_EN); write_pmbase16(TCO1_CNT, read_pmbase16(TCO1_CNT) | TCO_LOCK); diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index bcdcaa9158..089e3ce234 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -1116,7 +1118,7 @@ void spi_finalize_ops(void) } writew_(optype, cntlr.optype); - spi_set_smm_only_flashing(CONFIG(BOOTMEDIA_SMM_BWP)); + spi_set_smm_only_flashing(enable_smm_bios_protection()); } __weak void intel_southbridge_override_spi(struct intel_swseq_spi_config *spi_config)