soc/amd/common/block/psp: Add BIOS SPI flash semaphore
When coreboot is operating on the SPI flash lock the bus by
setting SPI_SEMAPHORE_BIOS_LOCKED in SPI_MISC_CNTRL. This prevents
SMM from accidentally corrupting SPI CTRL registers, even though
SMM backups and restores SPI CTRL registers.
TEST: Booted an AMD glinda and observed SMM not accessing the SPI
controller as long as ring 0 is operating on it.
Signed-off-by: Patrick Rudolph <patrick.rudolph@amd.com>
Change-Id: Iaeda356b55d3f203c75f4056da7bde2abacebc41
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88438
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
This commit is contained in:
parent
038262155e
commit
a17a41559a
3 changed files with 50 additions and 1 deletions
|
|
@ -89,6 +89,7 @@ enum spi100_speed {
|
||||||
/* AMD has re-purposed this unused SPI controller register bit as a semaphore to synchronize
|
/* AMD has re-purposed this unused SPI controller register bit as a semaphore to synchronize
|
||||||
access to the SPI controller between SMM and non-SMM software/OS driver. */
|
access to the SPI controller between SMM and non-SMM software/OS driver. */
|
||||||
#define SPI_SEMAPHORE_DRIVER_LOCKED BIT(4)
|
#define SPI_SEMAPHORE_DRIVER_LOCKED BIT(4)
|
||||||
|
#define SPI_SEMAPHORE_BIOS_LOCKED BIT(3)
|
||||||
|
|
||||||
struct spi_config {
|
struct spi_config {
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,14 @@ static enum mbox_p2c_status find_psp_spi_flash_device_region(uint64_t target_nv_
|
||||||
|
|
||||||
static bool spi_controller_busy(void)
|
static bool spi_controller_busy(void)
|
||||||
{
|
{
|
||||||
bool busy = false;
|
bool busy;
|
||||||
|
|
||||||
|
/* When the firmware is using the SPI controller stop here */
|
||||||
|
busy = (spi_read8(SPI_MISC_CNTRL) & SPI_SEMAPHORE_BIOS_LOCKED);
|
||||||
|
if (busy) {
|
||||||
|
printk(BIOS_NOTICE, "PSP: SPI controller blocked by coreboot (ring 0)\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When ring0 is operating on the SPI flash and the controller is
|
* When ring0 is operating on the SPI flash and the controller is
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <spi_flash.h>
|
#include <spi_flash.h>
|
||||||
#include <soc/pci_devs.h>
|
#include <soc/pci_devs.h>
|
||||||
#include <amdblocks/lpc.h>
|
#include <amdblocks/lpc.h>
|
||||||
|
#include <amdblocks/smi.h>
|
||||||
#include <amdblocks/spi.h>
|
#include <amdblocks/spi.h>
|
||||||
#include <device/pci_ops.h>
|
#include <device/pci_ops.h>
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
|
|
@ -122,6 +123,10 @@ static uint8_t fifo[SPI_FIFO_DEPTH];
|
||||||
|
|
||||||
void fch_spi_backup_registers(void)
|
void fch_spi_backup_registers(void)
|
||||||
{
|
{
|
||||||
|
/* When bus is locked no need for backup */
|
||||||
|
if (ENV_SMM && (spi_read8(SPI_MISC_CNTRL) & SPI_SEMAPHORE_BIOS_LOCKED))
|
||||||
|
return;
|
||||||
|
|
||||||
cmd_code = spi_read8(SPI_CMD_CODE);
|
cmd_code = spi_read8(SPI_CMD_CODE);
|
||||||
tx_byte_count = spi_read8(SPI_TX_BYTE_COUNT);
|
tx_byte_count = spi_read8(SPI_TX_BYTE_COUNT);
|
||||||
rx_byte_count = spi_read8(SPI_RX_BYTE_COUNT);
|
rx_byte_count = spi_read8(SPI_RX_BYTE_COUNT);
|
||||||
|
|
@ -132,6 +137,10 @@ void fch_spi_backup_registers(void)
|
||||||
|
|
||||||
void fch_spi_restore_registers(void)
|
void fch_spi_restore_registers(void)
|
||||||
{
|
{
|
||||||
|
/* When bus is locked no need for backup */
|
||||||
|
if (ENV_SMM && (spi_read8(SPI_MISC_CNTRL) & SPI_SEMAPHORE_BIOS_LOCKED))
|
||||||
|
return;
|
||||||
|
|
||||||
spi_write8(SPI_CMD_CODE, cmd_code);
|
spi_write8(SPI_CMD_CODE, cmd_code);
|
||||||
spi_write8(SPI_TX_BYTE_COUNT, tx_byte_count);
|
spi_write8(SPI_TX_BYTE_COUNT, tx_byte_count);
|
||||||
spi_write8(SPI_RX_BYTE_COUNT, rx_byte_count);
|
spi_write8(SPI_RX_BYTE_COUNT, rx_byte_count);
|
||||||
|
|
@ -308,7 +317,39 @@ static int fch_spi_flash_protect(const struct spi_flash *flash, const struct reg
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Block PSP SMI while operating on the SPI flash */
|
||||||
|
static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
|
||||||
|
{
|
||||||
|
uint8_t reg8;
|
||||||
|
|
||||||
|
if (CONFIG(SOC_AMD_COMMON_BLOCK_PSP_SMI)) {
|
||||||
|
if (ENV_RAMSTAGE || ENV_SMM) {
|
||||||
|
reg8 = spi_read8(SPI_MISC_CNTRL);
|
||||||
|
|
||||||
|
if (reg8 & SPI_SEMAPHORE_BIOS_LOCKED)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ENV_RAMSTAGE)
|
||||||
|
spi_write8(SPI_MISC_CNTRL, reg8 | SPI_SEMAPHORE_BIOS_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow PSP SMI when not operating on the SPI flash */
|
||||||
|
static void spi_ctrlr_release_bus(const struct spi_slave *slave)
|
||||||
|
{
|
||||||
|
uint8_t reg8;
|
||||||
|
|
||||||
|
if (ENV_RAMSTAGE && CONFIG(SOC_AMD_COMMON_BLOCK_PSP_SMI)) {
|
||||||
|
reg8 = spi_read8(SPI_MISC_CNTRL);
|
||||||
|
spi_write8(SPI_MISC_CNTRL, reg8 & ~SPI_SEMAPHORE_BIOS_LOCKED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct spi_ctrlr fch_spi_flash_ctrlr = {
|
static const struct spi_ctrlr fch_spi_flash_ctrlr = {
|
||||||
|
.claim_bus = spi_ctrlr_claim_bus,
|
||||||
|
.release_bus = spi_ctrlr_release_bus,
|
||||||
.xfer_vector = xfer_vectors,
|
.xfer_vector = xfer_vectors,
|
||||||
.max_xfer_size = SPI_FIFO_DEPTH,
|
.max_xfer_size = SPI_FIFO_DEPTH,
|
||||||
.flags = SPI_CNTRLR_DEDUCT_CMD_LEN | SPI_CNTRLR_DEDUCT_OPCODE_LEN,
|
.flags = SPI_CNTRLR_DEDUCT_CMD_LEN | SPI_CNTRLR_DEDUCT_OPCODE_LEN,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue