summaryrefslogtreecommitdiff
path: root/src/soc/intel/common
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2021-02-10 17:12:05 +0100
committerPatrick Rudolph <siro@das-labor.org>2021-06-21 08:11:11 +0000
commitd21b463fb058deccef3a2c2ad80d771b5aba9f19 (patch)
treefdb4d134ffe185f67500f3419960996f0cbb8679 /src/soc/intel/common
parent44a4c0a58dd4ef725c7ff24f9889b12d42a4c5f2 (diff)
security/intel: Add option to enable SMM flash access only
On platforms where the boot media can be updated externally, e.g. using a BMC, add the possibility to enable writes in SMM only. This allows to protect the BIOS region even without the use of vboot, but keeps SMMSTORE working for use in payloads. Note that this breaks flashconsole, since the flash becomes read-only. Tested on Asrock B85M Pro4 and HP 280 G2, SMM BIOS write protection works as expected, and SMMSTORE can still be used. Change-Id: I157db885b5f1d0f74009ede6fb2342b20d9429fa Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/40830 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi.c11
-rw-r--r--src/soc/intel/common/block/include/intelblocks/fast_spi.h4
-rw-r--r--src/soc/intel/common/block/smm/smihandler.c56
-rw-r--r--src/soc/intel/common/pch/lockdown/lockdown.c6
4 files changed, 50 insertions, 27 deletions
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi.c b/src/soc/intel/common/block/fast_spi/fast_spi.c
index 15cd26e2e2..843071e2a8 100644
--- a/src/soc/intel/common/block/fast_spi/fast_spi.c
+++ b/src/soc/intel/common/block/fast_spi/fast_spi.c
@@ -418,3 +418,14 @@ void fast_spi_enable_wp(void)
bios_cntl &= ~SPI_BIOS_CONTROL_WPD;
pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
}
+
+/* Disable SPI Write Protect. */
+void fast_spi_disable_wp(void)
+{
+ const pci_devfn_t dev = PCH_DEV_SPI;
+ uint8_t bios_cntl;
+
+ bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
+ bios_cntl |= SPI_BIOS_CONTROL_WPD;
+ pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
+}
diff --git a/src/soc/intel/common/block/include/intelblocks/fast_spi.h b/src/soc/intel/common/block/include/intelblocks/fast_spi.h
index d0442566b3..d5d3cd560c 100644
--- a/src/soc/intel/common/block/include/intelblocks/fast_spi.h
+++ b/src/soc/intel/common/block/include/intelblocks/fast_spi.h
@@ -77,6 +77,10 @@ bool fast_spi_wpd_status(void);
*/
void fast_spi_enable_wp(void);
/*
+ * Disable SPI Write protect.
+ */
+void fast_spi_disable_wp(void);
+/*
* Get base and size of extended BIOS decode window used at runtime in host address space. If
* the BIOS region is not greater than 16MiB, then this function returns 0 for both base and
* size.
diff --git a/src/soc/intel/common/block/smm/smihandler.c b/src/soc/intel/common/block/smm/smihandler.c
index 91142a51ce..5789b4843e 100644
--- a/src/soc/intel/common/block/smm/smihandler.c
+++ b/src/soc/intel/common/block/smm/smihandler.c
@@ -44,31 +44,6 @@ __weak int smihandler_soc_disable_busmaster(pci_devfn_t dev)
return 1;
}
-/*
- * Needs to implement the mechanism to know if an illegal attempt
- * has been made to write to the BIOS area.
- */
-static void smihandler_soc_check_illegal_access(
- uint32_t tco_sts)
-{
- if (!((tco_sts & (1 << 8)) && CONFIG(SPI_FLASH_SMM)
- && fast_spi_wpd_status()))
- return;
-
- /*
- * BWE is RW, so the SMI was caused by a
- * write to BWE, not by a write to the BIOS
- *
- * This is the place where we notice someone
- * is trying to tinker with the BIOS. We are
- * trying to be nice and just ignore it. A more
- * resolute answer would be to power down the
- * box.
- */
- printk(BIOS_DEBUG, "Switching back to RO\n");
- fast_spi_enable_wp();
-}
-
/* Mainboard overrides. */
__weak void mainboard_smi_gpi_handler(
@@ -301,9 +276,19 @@ static void southbridge_smi_store(
/* Parameter buffer in EBX */
reg_ebx = save_state_ops->get_reg(io_smi, RBX);
+ const bool wp_enabled = !fast_spi_wpd_status();
+ if (wp_enabled) {
+ fast_spi_disable_wp();
+ /* Not clearing SPI sync SMI status here results in hangs */
+ fast_spi_clear_sync_smi_status();
+ }
+
/* drivers/smmstore/smi.c */
ret = smmstore_exec(sub_command, (void *)(uintptr_t)reg_ebx);
save_state_ops->set_reg(io_smi, RAX, ret);
+
+ if (wp_enabled)
+ fast_spi_enable_wp();
}
static void finalize(void)
@@ -320,6 +305,9 @@ static void finalize(void)
/* Re-init SPI driver to handle locked BAR */
fast_spi_init();
+ if (CONFIG(BOOTMEDIA_SMM_BWP))
+ fast_spi_enable_wp();
+
/*
* HECI is disabled in smihandler_soc_at_finalize() which also locks down the side band
* interface. Some boards may require this interface in mainboard_smi_finalize(),
@@ -401,12 +389,26 @@ 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()) {
+ /*
+ * BWE is RW, so the SMI was caused by a
+ * write to BWE, not by a write to the BIOS
+ *
+ * This is the place where we notice someone
+ * is trying to tinker with the BIOS. We are
+ * trying to be nice and just ignore it. A more
+ * resolute answer would be to power down the
+ * box.
+ */
+ printk(BIOS_DEBUG, "Switching SPI back to RO\n");
+ fast_spi_enable_wp();
+ }
+
/* Any TCO event? */
if (!tco_sts)
return;
- smihandler_soc_check_illegal_access(tco_sts);
-
if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */
/* Handle TCO timeout */
printk(BIOS_DEBUG, "TCO Timeout.\n");
diff --git a/src/soc/intel/common/pch/lockdown/lockdown.c b/src/soc/intel/common/pch/lockdown/lockdown.c
index d9495a432b..87f36fc91c 100644
--- a/src/soc/intel/common/pch/lockdown/lockdown.c
+++ b/src/soc/intel/common/pch/lockdown/lockdown.c
@@ -65,6 +65,12 @@ static void fast_spi_lockdown_cfg(int chipset_lockdown)
/* BIOS Interface Lock */
fast_spi_set_bios_interface_lock_down();
+ /* Only allow writes in SMM */
+ if (CONFIG(BOOTMEDIA_SMM_BWP)) {
+ //fast_spi_set_eiss(); /* TODO */
+ fast_spi_enable_wp();
+ }
+
/* BIOS Lock */
fast_spi_set_lock_enable();