Patrick Rudolph has uploaded this change for review.

View Change

[WIP]security/intel: Add option to eanble SMM flash access only

On platforms where the boot media can be updated externally, for 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 the SMMSTORE working for the use in payloads.

UNTESTED.

Change-Id: I157db885b5f1d0f74009ede6fb2342b20d9429fa
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
M src/security/lockdown/Kconfig
M src/soc/intel/common/pch/lockdown/lockdown.c
M src/southbridge/intel/bd82x6x/lpc.c
M src/southbridge/intel/common/spi.c
M src/southbridge/intel/common/spi.h
M src/southbridge/intel/ibexpeak/lpc.c
M src/southbridge/intel/lynxpoint/lpc.c
M src/southbridge/intel/lynxpoint/smi.c
8 files changed, 52 insertions(+), 43 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/30/40830/1
diff --git a/src/security/lockdown/Kconfig b/src/security/lockdown/Kconfig
index d24c5e5..dbe6840 100644
--- a/src/security/lockdown/Kconfig
+++ b/src/security/lockdown/Kconfig
@@ -99,3 +99,13 @@
possible. This option prevents using write protecting facilities in
ramstage, like the MRC cache for example.
Use this option if you don't trust code running after verstage.
+
+config BOOTMEDIA_SMM_BWP
+ bool "Boot media only writable in SMM"
+ depends on ARCH_X86
+ depends on HAVE_SMI_HANDLER
+ select SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE if SOC_INTEL_COMMON_BLOCK
+ help
+ Enable flash writes in SMM only. Select this if you want to secure
+ the SMM_STORE and don't need to update coreboot using the
+ internal controller.
diff --git a/src/soc/intel/common/pch/lockdown/lockdown.c b/src/soc/intel/common/pch/lockdown/lockdown.c
index a00e5c0..768c4cd 100644
--- a/src/soc/intel/common/pch/lockdown/lockdown.c
+++ b/src/soc/intel/common/pch/lockdown/lockdown.c
@@ -62,6 +62,12 @@
/* BIOS Interface Lock */
fast_spi_set_bios_interface_lock_down();

+ /* Only allow writes in SMM */
+ if (CONFIG(BOOTMEDIA_SMM_BWP)) {
+ fast_spi_set_eiss();
+ fast_spi_enable_wp();
+ }
+
/* BIOS Lock */
fast_spi_set_lock_enable();
}
diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c
index 278e90a..78bfb39 100644
--- a/src/southbridge/intel/bd82x6x/lpc.c
+++ b/src/southbridge/intel/bd82x6x/lpc.c
@@ -416,16 +416,6 @@
}
}

-static void pch_disable_smm_only_flashing(struct device *dev)
-{
- u8 reg8;
-
- printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
- reg8 = pci_read_config8(dev, BIOS_CNTL);
- reg8 &= ~(1 << 5);
- pci_write_config8(dev, BIOS_CNTL, reg8);
-}
-
static void pch_fixups(struct device *dev)
{
u8 gen_pmcon_2;
@@ -579,8 +569,6 @@
/* Interrupt 9 should be level triggered (SCI) */
i8259_configure_irq_trigger(9, 1);

- pch_disable_smm_only_flashing(dev);
-
pch_set_acpi_mode();

pch_fixups(dev);
diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c
index 5e967af..253d33f 100644
--- a/src/southbridge/intel/common/spi.c
+++ b/src/southbridge/intel/common/spi.c
@@ -35,6 +35,10 @@
#define HSFC_FCYCLE (0x3 << HSFC_FCYCLE_OFF)
#define HSFC_FDBC_OFF 8 /* 8-13: Flash Data Byte Count */
#define HSFC_FDBC (0x3f << HSFC_FDBC_OFF)
+#define BIOS_CNTL 0xdc
+#define LPC_BC_WE (1 << 0) /* WE */
+#define LPC_BC_LE (1 << 1) /* LE */
+#define LPC_BC_EISS (1 << 5) /* EISS */

static int spi_is_multichip(void);

@@ -293,7 +297,6 @@

void spi_init(void)
{
- uint8_t bios_cntl;
struct ich9_spi_regs *ich9_spi;
struct ich7_spi_regs *ich7_spi;
uint16_t hsfs;
@@ -345,10 +348,7 @@

if (CONFIG(SOUTHBRIDGE_INTEL_I82801GX) || CONFIG(SOUTHBRIDGE_INTEL_COMMON_SPI_ICH9)) {
/* Disable the BIOS write protect so write commands are allowed. */
- bios_cntl = pci_read_config8(dev, 0xdc);
- /* Deassert SMM BIOS Write Protect Disable. */
- bios_cntl &= ~(1 << 5);
- pci_write_config8(dev, 0xdc, bios_cntl | 0x1);
+ spi_smm_only_flashing(0);
}
}

@@ -1108,12 +1108,35 @@
writeb_(spi_config->ops[i].op, &cntlr.opmenu[i]);
}
writew_(optype, cntlr.optype);
+
+ spi_smm_only_flashing(CONFIG(BOOTMEDIA_SMM_BWP));
}

__weak void intel_southbridge_override_spi(struct intel_swseq_spi_config *spi_config)
{
}

+void spi_smm_only_flashing(bool enable)
+{
+ pci_devfn_t dev = PCI_DEV(0, 31, 0);
+ u8 reg8 = pci_read_config8(dev, BIOS_CNTL);
+
+ if (reg8 & LPC_BC_LE)
+ return;
+
+ if (enable) {
+ reg8 |= LPC_BC_EISS;
+ reg8 &= ~LPC_BC_WE;
+ } else {
+ reg8 &= ~LPC_BC_EISS;
+ reg8 |= LPC_BC_WE;
+ }
+ pci_write_config8(dev, BIOS_CNTL, reg8);
+
+ printk(BIOS_SPEW, "BIOS updates outside of SMM %s\n",
+ enable ? "enabled" : "disabled");
+}
+
static const struct spi_ctrlr spi_ctrlr = {
.xfer_vector = xfer_vectors,
.max_xfer_size = member_size(struct ich9_spi_regs, fdata),
diff --git a/src/southbridge/intel/common/spi.h b/src/southbridge/intel/common/spi.h
index 3b8410c..ad1cb27 100644
--- a/src/southbridge/intel/common/spi.h
+++ b/src/southbridge/intel/common/spi.h
@@ -32,6 +32,7 @@
struct intel_spi_op ops[8];
};

+void spi_smm_only_flashing(bool enable);
void spi_finalize_ops(void);
void intel_southbridge_override_spi(struct intel_swseq_spi_config *spi_config);

diff --git a/src/southbridge/intel/ibexpeak/lpc.c b/src/southbridge/intel/ibexpeak/lpc.c
index 395919e..67c03fa 100644
--- a/src/southbridge/intel/ibexpeak/lpc.c
+++ b/src/southbridge/intel/ibexpeak/lpc.c
@@ -420,16 +420,6 @@
}
}

-static void pch_disable_smm_only_flashing(struct device *dev)
-{
- u8 reg8;
-
- printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
- reg8 = pci_read_config8(dev, BIOS_CNTL);
- reg8 &= ~(1 << 5);
- pci_write_config8(dev, BIOS_CNTL, reg8);
-}
-
static void pch_fixups(struct device *dev)
{
/*
@@ -482,8 +472,6 @@
/* Interrupt 9 should be level triggered (SCI) */
i8259_configure_irq_trigger(9, 1);

- pch_disable_smm_only_flashing(dev);
-
pch_set_acpi_mode();

pch_fixups(dev);
diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c
index d9ef5cc..dafb901 100644
--- a/src/southbridge/intel/lynxpoint/lpc.c
+++ b/src/southbridge/intel/lynxpoint/lpc.c
@@ -481,16 +481,6 @@
}
}

-static void pch_disable_smm_only_flashing(struct device *dev)
-{
- u8 reg8;
-
- printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
- reg8 = pci_read_config8(dev, BIOS_CNTL);
- reg8 &= ~(1 << 5);
- pci_write_config8(dev, BIOS_CNTL, reg8);
-}
-
static void pch_fixups(struct device *dev)
{
u8 gen_pmcon_2;
@@ -549,8 +539,6 @@
/* Interrupt 9 should be level triggered (SCI) */
i8259_configure_irq_trigger(9, 1);

- pch_disable_smm_only_flashing(dev);
-
pch_set_acpi_mode();

pch_fixups(dev);
diff --git a/src/southbridge/intel/lynxpoint/smi.c b/src/southbridge/intel/lynxpoint/smi.c
index 05b5bb5..82e96f3 100644
--- a/src/southbridge/intel/lynxpoint/smi.c
+++ b/src/southbridge/intel/lynxpoint/smi.c
@@ -40,6 +40,8 @@

void smm_southbridge_enable_smi(void)
{
+ u32 mask;
+
printk(BIOS_DEBUG, "Enabling SMIs.\n");
/* Configure events */
enable_pm1(PWRBTN_EN | GBL_EN);
@@ -49,11 +51,14 @@
* - on APMC writes (io 0xb2)
* - on writes to SLP_EN (sleep states)
* - on writes to GBL_RLS (bios commands)
+ * - on TCO events
* No SMIs:
* - on microcontroller writes (io 0x62/0x66)
- * - on TCO events
*/
- enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS);
+ mask = APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS;
+ if (CONFIG(BOOTMEDIA_SMM_BWP))
+ mask |= TCO_EN;
+ enable_smi(mask);
}

static void __unused southbridge_trigger_smi(void)

To view, visit change 40830. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I157db885b5f1d0f74009ede6fb2342b20d9429fa
Gerrit-Change-Number: 40830
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-MessageType: newchange