Skip to content

Commit

Permalink
soc/intel/lockdown: Allow locking down SPI and LPC in SMM
Browse files Browse the repository at this point in the history
Heads payload uses APM_CNT_FINALIZE SMI to set and lock down the SPI
controller with PR0 flash protection for pre-Skylake platforms.

Add new option to skip LPC and FAST SPI lock down in coreboot and move
it to APM_CNT_FINALIZE SMI handler. Reuse the INTEL_CHIPSET_LOCKDOWN
option to prevent issuing APM_CNT_FINALIZE SMI on normal boot path,
like it was done on pre-Skylake platforms. As the locking on modern
SOCs became more complicated, separate the SPI and LPC locking into
new modules to make linking to SMM easier.

The expected configuration to leverage the feautre is to unselect
INTEL_CHIPSET_LOCKDOWN and select SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM.

Testing various microarchitectures happens on heads repository:
linuxboot/heads#1818

TEST=Lock the SPI flash using APM_CNT_FINALIZE in heads on Alder Lake
(Protectli VP66xx) and Comet Lake (Protectli VP46xx) platforms. Check
if flash is unlocked in the heads recovery console. Check if flash is
locked in the kexec'ed OS.

Change-Id: Icbcc6fcde90e5b0a999aacb720e2e3dc2748c838
Signed-off-by: Michał Żygowski <[email protected]>
  • Loading branch information
miczyg1 authored and mkopec committed Jan 15, 2025
1 parent 9443006 commit a4f9bd2
Show file tree
Hide file tree
Showing 19 changed files with 211 additions and 67 deletions.
4 changes: 3 additions & 1 deletion src/soc/intel/alderlake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ static void soc_finalize(void *unused)
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

tbt_finalize();
if (CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT) &&
CONFIG(USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE))
Expand Down
4 changes: 3 additions & 1 deletion src/soc/intel/cannonlake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ static void soc_finalize(void *unused)
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT) &&
CONFIG(SOC_INTEL_COMMON_BLOCK_HECI1_DISABLE_USING_PMC_IPC))
heci1_disable();
Expand Down
4 changes: 4 additions & 0 deletions src/soc/intel/common/block/lpc/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_LPC) += lpc_lib.c

ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_LPC) += lpc_lib.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_LPC) += lpc.c

ifeq ($(CONFIG_SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM),y)
smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_LPC) += lpc_lib.c
endif
10 changes: 10 additions & 0 deletions src/soc/intel/common/block/smm/smihandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
#include <device/pci_def.h>
#include <device/pci_ops.h>
#include <elog.h>
#include <intelblocks/cfg.h>
#include <intelblocks/fast_spi.h>
#include <intelblocks/oc_wdt.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/smihandler.h>
#include <intelblocks/tco.h>
#include <intelblocks/uart.h>
#include <intelpch/lockdown.h>
#include <smmstore.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
Expand Down Expand Up @@ -347,6 +349,14 @@ static void finalize(void)
}
finalize_done = 1;

if (CONFIG(SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM)) {
/* SPI lock down configuration */
fast_spi_lockdown_bios(CHIPSET_LOCKDOWN_COREBOOT);

/* LPC/eSPI lock down configuration */
lpc_lockdown_config(CHIPSET_LOCKDOWN_COREBOOT);
}

if (CONFIG(SPI_FLASH_SMM))
/* Re-init SPI driver to handle locked BAR */
fast_spi_init();
Expand Down
3 changes: 3 additions & 0 deletions src/soc/intel/common/pch/include/intelpch/lockdown.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ int get_lockdown_config(void);
*/
void soc_lockdown_config(int chipset_lockdown);

void fast_spi_lockdown_bios(int chipset_lockdown);
void lpc_lockdown_config(int chipset_lockdown);

#endif /* SOC_INTEL_COMMON_PCH_LOCKDOWN_H */
15 changes: 15 additions & 0 deletions src/soc/intel/common/pch/lockdown/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,22 @@
config SOC_INTEL_COMMON_PCH_LOCKDOWN
bool
default n
select HAVE_INTEL_CHIPSET_LOCKDOWN
help
This option allows to have chipset lockdown for DMI, FAST_SPI and
soc_lockdown_config() to implement any additional lockdown as PMC,
LPC for supported PCH.

config SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM
bool "Lock down SPI controller in SMM"
default n
depends on HAVE_SMI_HANDLER && !INTEL_CHIPSET_LOCKDOWN
select SPI_FLASH_SMM
help
This option allows to have chipset lockdown for FAST_SPI and LPC for
supported PCH. If selected, coreboot will skip locking down the SPI
and LPC controller. The payload or OS is responsible for locking it
using APM_CNT_FINALIZE SMI. Used by heads to set and lock PR0 flash
protection.

If unsure, say N.
5 changes: 5 additions & 0 deletions src/soc/intel/common/pch/lockdown/Makefile.mk
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
## SPDX-License-Identifier: GPL-2.0-only
ramstage-$(CONFIG_SOC_INTEL_COMMON_PCH_LOCKDOWN) += lockdown.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_PCH_LOCKDOWN) += lockdown_lpc.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_PCH_LOCKDOWN) += lockdown_spi.c

smm-$(CONFIG_SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM) += lockdown_lpc.c
smm-$(CONFIG_SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM) += lockdown_spi.c
49 changes: 5 additions & 44 deletions src/soc/intel/common/pch/lockdown/lockdown.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <bootstate.h>
#include <dasharo/options.h>
#include <intelblocks/cfg.h>
#include <intelblocks/fast_spi.h>
#include <intelblocks/lpc_lib.h>
Expand Down Expand Up @@ -61,56 +60,17 @@ static void fast_spi_lockdown_cfg(int chipset_lockdown)
/* Set FAST_SPI opcode menu */
fast_spi_set_opcode_menu();

/* Discrete Lock Flash PR registers */
fast_spi_pr_dlock();

/* Check if SPI transaction is pending */
fast_spi_cycle_in_progress();

/* Clear any outstanding status bits like AEL, FCERR, FDONE, SAF etc. */
fast_spi_clear_outstanding_status();

/* Lock FAST_SPIBAR */
fast_spi_lock_bar();

/* Set Vendor Component Lock (VCL) */
fast_spi_vscc0_lock();

/* Set BIOS Interface Lock, BIOS Lock */
if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT) {
/* BIOS Interface Lock */
fast_spi_set_bios_interface_lock_down();

/* Only allow writes in SMM */
if (CONFIG(BOOTMEDIA_SMM_BWP) && is_smm_bwp_permitted()) {
fast_spi_set_eiss();
fast_spi_enable_wp();
}

/* BIOS Lock */
fast_spi_set_lock_enable();

/* EXT BIOS Lock */
fast_spi_set_ext_bios_lock_enable();
}
}

static void lpc_lockdown_config(int chipset_lockdown)
{
/* Set BIOS Interface Lock, BIOS Lock */
if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT) {
/* BIOS Interface Lock */
lpc_set_bios_interface_lock_down();

/* Only allow writes in SMM */
if (CONFIG(BOOTMEDIA_SMM_BWP) && is_smm_bwp_permitted()) {
lpc_set_eiss();
lpc_enable_wp();
}

/* BIOS Lock */
lpc_set_lock_enable();
}
if (!CONFIG(SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM))
fast_spi_lockdown_bios(chipset_lockdown);
}

static void sa_lockdown_config(int chipset_lockdown)
Expand All @@ -136,8 +96,9 @@ static void platform_lockdown_config(void *unused)
/* SPI lock down configuration */
fast_spi_lockdown_cfg(chipset_lockdown);

/* LPC/eSPI lock down configuration */
lpc_lockdown_config(chipset_lockdown);
if (!CONFIG(SOC_INTEL_COMMON_SPI_LOCKDOWN_SMM))
/* LPC/eSPI lock down configuration */
lpc_lockdown_config(chipset_lockdown);

/* GPMR lock down configuration */
gpmr_lockdown_cfg();
Expand Down
24 changes: 24 additions & 0 deletions src/soc/intel/common/pch/lockdown/lockdown_lpc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <dasharo/options.h>
#include <intelblocks/cfg.h>
#include <intelblocks/lpc_lib.h>
#include <intelpch/lockdown.h>

void lpc_lockdown_config(int chipset_lockdown)
{
/* Set BIOS Interface Lock, BIOS Lock */
if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT) {
/* BIOS Interface Lock */
lpc_set_bios_interface_lock_down();

/* Only allow writes in SMM */
if (CONFIG(BOOTMEDIA_SMM_BWP) && is_smm_bwp_permitted()) {
lpc_set_eiss();
lpc_enable_wp();
}

/* BIOS Lock */
lpc_set_lock_enable();
}
}
33 changes: 33 additions & 0 deletions src/soc/intel/common/pch/lockdown/lockdown_spi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <dasharo/options.h>
#include <intelblocks/cfg.h>
#include <intelblocks/fast_spi.h>
#include <intelpch/lockdown.h>

void fast_spi_lockdown_bios(int chipset_lockdown)
{
/* Discrete Lock Flash PR registers */
fast_spi_pr_dlock();

/* Lock FAST_SPIBAR */
fast_spi_lock_bar();

/* Set BIOS Interface Lock, BIOS Lock */
if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT) {
/* BIOS Interface Lock */
fast_spi_set_bios_interface_lock_down();

/* Only allow writes in SMM */
if (CONFIG(BOOTMEDIA_SMM_BWP) && is_smm_bwp_permitted()) {
fast_spi_set_eiss();
fast_spi_enable_wp();
}

/* BIOS Lock */
fast_spi_set_lock_enable();

/* EXT BIOS Lock */
fast_spi_set_ext_bios_lock_enable();
}
}
3 changes: 2 additions & 1 deletion src/soc/intel/denverton_ns/lpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ static const struct pci_driver lpc_driver __pci_driver = {

static void finalize_chipset(void *unused)
{
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);
}

BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, finalize_chipset, NULL);
Expand Down
4 changes: 3 additions & 1 deletion src/soc/intel/elkhartlake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ static void soc_finalize(void *unused)
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

if (CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT) &&
CONFIG(USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE))
heci_finalize();
Expand Down
3 changes: 2 additions & 1 deletion src/soc/intel/jasperlake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ static void soc_finalize(void *unused)
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

/* Indicate finalize step with post code */
post_code(POSTCODE_OS_BOOT);
Expand Down
4 changes: 3 additions & 1 deletion src/soc/intel/meteorlake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ static void soc_finalize(void *unused)
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

tbt_finalize();
sa_finalize();
if (CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT) &&
Expand Down
84 changes: 84 additions & 0 deletions src/soc/intel/pantherlake/finalize.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <arch/io.h>
#include <bootstate.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <device/mmio.h>
#include <device/pci.h>
#include <intelblocks/cse.h>
#include <intelblocks/lpc_lib.h>
#include <intelblocks/pcr.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/systemagent.h>
#include <intelblocks/tco.h>
#include <intelblocks/thermal.h>
#include <intelpch/lockdown.h>
#include <soc/p2sb.h>
#include <soc/pci_devs.h>
#include <soc/pcr_ids.h>
#include <soc/pm.h>
#include <soc/smbus.h>
#include <soc/soc_chip.h>
#include <soc/systemagent.h>
#include <spi-generic.h>
#include <timer.h>

static void pch_finalize(void)
{
/* TCO Lock down */
tco_lockdown();

pmc_clear_pmcon_sts();
}

static void tbt_finalize(void)
{
int i;
const struct device *dev;

/* Disable Thunderbolt PCIe root ports bus master */
for (i = 0; i < NUM_TBT_FUNCTIONS; i++) {
dev = pcidev_path_on_root(PCI_DEVFN_TBT(i));
if (dev)
pci_dev_disable_bus_master(dev);
}
}

static void sa_finalize(void)
{
if (get_lockdown_config() == CHIPSET_LOCKDOWN_COREBOOT)
sa_lock_pam();
}

static void heci_finalize(void)
{
heci_set_to_d0i3();
if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
heci1_disable();
}

static void soc_finalize(void *unused)
{
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

tbt_finalize();
sa_finalize();
if (CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT) &&
CONFIG(USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE))
heci_finalize();

/* Indicate finalize step with post code */
post_code(POSTCODE_OS_BOOT);
}

BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, soc_finalize, NULL);
/*
* The purpose of this change is to accommodate more time to push out sending
* CSE EOP messages at post.
*/
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, soc_finalize, NULL);
3 changes: 2 additions & 1 deletion src/soc/intel/skylake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ static void soc_finalize(void *unused)
pch_finalize_script(dev);

soc_lockdown(dev);
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

/* Indicate finalize step with post code */
post_code(POSTCODE_OS_BOOT);
Expand Down
4 changes: 3 additions & 1 deletion src/soc/intel/tigerlake/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ static void soc_finalize(void *unused)
printk(BIOS_DEBUG, "Finalizing chipset.\n");

pch_finalize();
apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

tbt_finalize();
if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
heci1_disable();
Expand Down
4 changes: 3 additions & 1 deletion src/soc/intel/xeon_sp/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ static void soc_finalize(void *unused)
if (!CONFIG(USE_PM_ACPI_TIMER))
setbits8(pmc_mmio_regs() + PCH_PWRM_ACPI_TMR_CTL, ACPI_TIM_DIS);

apm_control(APM_CNT_FINALIZE);
if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3())
apm_control(APM_CNT_FINALIZE);

lock_pam0123();

if (CONFIG_MAX_SOCKET > 1) {
Expand Down
Loading

0 comments on commit a4f9bd2

Please sign in to comment.