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 <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89919
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Matt DeVillier 2025-11-03 18:40:45 -06:00
commit 388fb318ad
7 changed files with 57 additions and 6 deletions

View file

@ -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

View file

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef SECURITY_LOCKDOWN_LOCKDOWN_H
#define SECURITY_LOCKDOWN_LOCKDOWN_H
#include <option.h>
#include <types.h>
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 */

View file

@ -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 */

View file

@ -20,6 +20,8 @@
#include <intelblocks/smihandler.h>
#include <intelblocks/tco.h>
#include <intelblocks/uart.h>
#include <option.h>
#include <security/lockdown/lockdown.h>
#include <smmstore.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
@ -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

View file

@ -8,6 +8,8 @@
#include <intelblocks/systemagent.h>
#include <intelpch/lockdown.h>
#include <intelblocks/gpmr.h>
#include <option.h>
#include <security/lockdown/lockdown.h>
#include <soc/pci_devs.h>
#include <soc/pcr_ids.h>
#include <soc/soc_chip.h>
@ -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();
}

View file

@ -2,6 +2,8 @@
#include <console/console.h>
#include <device/pci_ops.h>
#include <option.h>
#include <security/lockdown/lockdown.h>
#include <southbridge/intel/common/pmbase.h>
#include <southbridge/intel/common/pmutil.h>
#include <southbridge/intel/common/rcba.h>
@ -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);

View file

@ -13,6 +13,8 @@
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <option.h>
#include <security/lockdown/lockdown.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <timer.h>
@ -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)