Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/soc/intel/alderlake/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ config SOC_INTEL_ALDERLAKE
select SOC_INTEL_COMMON_BLOCK_CPU_SMMRELOCATE
select SOC_INTEL_COMMON_BLOCK_DTT
select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT
select SOC_INTEL_COMMON_BLOCK_GPIO_HAS_PLTRST_PAD
select SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_SBI
select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
select SOC_INTEL_COMMON_BLOCK_SCS if SOC_INTEL_ALDERLAKE_PCH_N
Expand Down
1 change: 1 addition & 0 deletions src/soc/intel/alderlake/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ ramstage-y += xhci.c
ramstage-$(CONFIG_SOC_INTEL_CRASHLOG) += crashlog.c

smm-y += elog.c
smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_PLTRST_PAD) += gpio_lock.c
smm-y += p2sb.c
smm-y += pmutil.c
smm-y += smihandler.c
Expand Down
21 changes: 21 additions & 0 deletions src/soc/intel/alderlake/gpio_lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <gpio.h>
#include <intelblocks/gpio.h>
#include <types.h>

/*
* GPP_B13 drives PLTRST# as its native function 1 on Alder Lake PCH-P/N as
* well as on PCH-S. Locking the pad configuration keeps system software from
* switching the pad to GPIO mode and pulsing it, which would reset a discrete
* TPM without restarting the measured boot chain.
*/
static const struct gpio_lock_config pltrst_pad[] = {
{ .pad = GPP_B13, .lock_action = GPIO_LOCK_CONFIG },
};

const struct gpio_lock_config *soc_gpio_lock_config(size_t *num)
{
*num = ARRAY_SIZE(pltrst_pad);
return pltrst_pad;
}
31 changes: 31 additions & 0 deletions src/soc/intel/common/block/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,37 @@ config SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_PCR
Starting with MTL SoC, the recommendation is to use PCR for locking down the
GPIO configuration.

# Selected by SoCs that return the pad driving PLTRST# from
# soc_gpio_lock_config().
config SOC_INTEL_COMMON_BLOCK_GPIO_HAS_PLTRST_PAD
bool

config SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_PLTRST_PAD
bool "Lock the PLTRST# pad configuration"
default y
depends on SOC_INTEL_COMMON_BLOCK_GPIO_HAS_PLTRST_PAD
depends on HAVE_SMI_HANDLER
depends on INTEL_CHIPSET_LOCKDOWN
depends on SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_SBI || \
SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_PCR
select SOC_INTEL_COMMON_BLOCK_SMM_LOCK_GPIO_PADS
help
PLTRST# is the native function of a GPIO pad. As long as that pad
configuration stays writable, system software can switch the pad to
GPIO mode and drive a platform reset edge. A discrete TPM is reset by
that edge while the host keeps running, so its PCRs are cleared
without restarting the measured boot chain and can be replayed with
arbitrary values.

Lock the pad configuration from the SMM finalize handler, i.e. after
FSP has run its notify phases, so the pad mode can no longer be
changed. Only the configuration is locked. The Tx state is left
writable, as it has no effect while the pad drives PLTRST#.

Say N on a board that does not use this pad for PLTRST#, or that uses
it as a GPIO: locking the configuration of a pad that already is in
GPIO mode does not keep software from driving it.

# Indicate if SoC supports 4 bits Pad Mode with PAD_CFG_DW0 registers
config SOC_INTEL_COMMON_BLOCK_GPIO_PMODE_4BITS
bool
Expand Down
83 changes: 62 additions & 21 deletions src/soc/intel/common/block/gpio/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,29 @@ int gpio_tx_get(gpio_t gpio_num)
return !!(reg & PAD_CFG0_TX_STATE);
}

static int
gpio_pad_config_lock_verify(const struct gpio_lock_config *pad_info,
uint8_t pid, uint16_t offset, const uint32_t bit_mask)
{
int ret = 0;

if ((pad_info->lock_action & GPIO_LOCK_CONFIG) == GPIO_LOCK_CONFIG &&
!(pcr_read32(pid, offset) & bit_mask)) {
printk(BIOS_ERR, "%s: Error: pad %d configuration still unlocked!\n",
__func__, pad_info->pad);
ret = -1;
}

if ((pad_info->lock_action & GPIO_LOCK_TX) == GPIO_LOCK_TX &&
!(pcr_read32(pid, offset + sizeof(uint32_t)) & bit_mask)) {
printk(BIOS_ERR, "%s: Error: pad %d Tx state still unlocked!\n",
__func__, pad_info->pad);
ret = -1;
}

return ret;
}

static void
gpio_pad_config_lock_using_sbi(const struct gpio_lock_config *pad_info,
uint8_t pid, uint16_t offset, const uint32_t bit_mask)
Expand Down Expand Up @@ -601,12 +624,32 @@ gpio_pad_config_lock_using_sbi(const struct gpio_lock_config *pad_info,
}
}

static void
gpio_pad_config_lock_using_pcr(const struct gpio_lock_config *pad_info,
uint8_t pid, uint16_t offset, const uint32_t bit_mask)
{
if ((pad_info->lock_action & GPIO_LOCK_CONFIG) == GPIO_LOCK_CONFIG) {
if (CONFIG(DEBUG_GPIO))
printk(BIOS_INFO, "%s: Locking pad %d configuration\n",
__func__, pad_info->pad);
pcr_or32(pid, offset, bit_mask);
}

if ((pad_info->lock_action & GPIO_LOCK_TX) == GPIO_LOCK_TX) {
if (CONFIG(DEBUG_GPIO))
printk(BIOS_INFO, "%s: Locking pad %d TX state\n",
__func__, pad_info->pad);
pcr_or32(pid, offset + sizeof(uint32_t), bit_mask);
}
}

int gpio_lock_pads(const struct gpio_lock_config *pad_list, const size_t count)
{
const struct pad_community *comm;
uint16_t offset;
size_t rel_pad;
gpio_t pad;
int ret = 0;

if (!CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_LOCK_GPIO_PADS))
return -1;
Expand Down Expand Up @@ -645,29 +688,21 @@ int gpio_lock_pads(const struct gpio_lock_config *pad_list, const size_t count)

const uint32_t bit_mask = gpio_bitmask_within_group(comm, rel_pad);

gpio_pad_config_lock_using_sbi(&pad_list[x], comm->port, offset, bit_mask);
/* Use the lock method the SoC selected, as done outside of SMM */
if (CONFIG(SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_PCR))
gpio_pad_config_lock_using_pcr(&pad_list[x], comm->port, offset,
bit_mask);
else
gpio_pad_config_lock_using_sbi(&pad_list[x], comm->port, offset,
bit_mask);

if (gpio_pad_config_lock_verify(&pad_list[x], comm->port, offset, bit_mask))
ret = -1;
}

p2sb_hide();
}

static void
gpio_pad_config_lock_using_pcr(const struct gpio_lock_config *pad_info,
uint8_t pid, uint16_t offset, const uint32_t bit_mask)
{
if ((pad_info->lock_action & GPIO_LOCK_CONFIG) == GPIO_LOCK_CONFIG) {
if (CONFIG(DEBUG_GPIO))
printk(BIOS_INFO, "%s: Locking pad %d configuration\n",
__func__, pad_info->pad);
pcr_or32(pid, offset, bit_mask);
}

if ((pad_info->lock_action & GPIO_LOCK_TX) == GPIO_LOCK_TX) {
if (CONFIG(DEBUG_GPIO))
printk(BIOS_INFO, "%s: Locking pad %d TX state\n",
__func__, pad_info->pad);
pcr_or32(pid, offset + sizeof(uint32_t), bit_mask);
}
return ret;
}

static int gpio_non_smm_lock_pad(const struct gpio_lock_config *pad_info)
Expand Down Expand Up @@ -710,9 +745,10 @@ static int gpio_non_smm_lock_pad(const struct gpio_lock_config *pad_info)
} else {
printk(BIOS_ERR, "%s: Error: No pad configuration lock method is selected!\n",
__func__);
return -1;
}

return 0;
return gpio_pad_config_lock_verify(pad_info, comm->port, offset, bit_mask);
}

int gpio_lock_pad(const gpio_t pad, enum gpio_lock_action lock_action)
Expand All @@ -726,7 +762,12 @@ int gpio_lock_pad(const gpio_t pad, enum gpio_lock_action lock_action)
.lock_action = lock_action
};

if (!ENV_SMM && !CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_LOCK_GPIO_PADS))
/*
* gpio_lock_pads() only works in SMM. Pads locked while configuring
* them, i.e. from the pad tables in ramstage, have to go through the
* non-SMM path even when the SoC also locks pads from SMM.
*/
if (!ENV_SMM)
return gpio_non_smm_lock_pad(&pads);

return gpio_lock_pads(&pads, 1);
Expand Down
2 changes: 2 additions & 0 deletions src/soc/intel/tigerlake/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ config SOC_INTEL_TIGERLAKE
select SOC_INTEL_COMMON_BLOCK_CPU_SMMRELOCATE
select SOC_INTEL_COMMON_BLOCK_DTT
select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT
select SOC_INTEL_COMMON_BLOCK_GPIO_HAS_PLTRST_PAD
select SOC_INTEL_COMMON_BLOCK_GPIO_IOSTANDBY
select SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_SBI
select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
select SOC_INTEL_COMMON_BLOCK_HDA
select SOC_INTEL_COMMON_BLOCK_HECI1_DISABLE_USING_PMC_IPC
Expand Down
1 change: 1 addition & 0 deletions src/soc/intel/tigerlake/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ smm-y += pmutil.c
smm-y += smihandler.c
smm-y += uart.c
smm-y += elog.c
smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_PLTRST_PAD) += gpio_lock.c
smm-y += xhci.c

ifeq ($(CONFIG_SOC_INTEL_TIGERLAKE_PCH_H),y)
Expand Down
5 changes: 5 additions & 0 deletions src/soc/intel/tigerlake/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPP_A24,
.num_gpi_regs = NUM_GPIO_COM0_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand Down Expand Up @@ -121,6 +122,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = vI2S2_RXD,
.num_gpi_regs = NUM_GPIO_COM1_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -147,6 +149,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPD_DRAM_RESETB,
.num_gpi_regs = NUM_GPIO_COM2_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -171,6 +174,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPP_DBG_PMODE,
.num_gpi_regs = NUM_GPIO_COM4_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand Down Expand Up @@ -198,6 +202,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPP_CLK_LOOPBK,
.num_gpi_regs = NUM_GPIO_COM5_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand Down
21 changes: 21 additions & 0 deletions src/soc/intel/tigerlake/gpio_lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <gpio.h>
#include <intelblocks/gpio.h>
#include <types.h>

/*
* GPP_B13 drives PLTRST# as its native function 1 on Tiger Lake PCH-LP as
* well as on PCH-H. Locking the pad configuration keeps system software from
* switching the pad to GPIO mode and pulsing it, which would reset a discrete
* TPM without restarting the measured boot chain.
*/
static const struct gpio_lock_config pltrst_pad[] = {
{ .pad = GPP_B13, .lock_action = GPIO_LOCK_CONFIG },
};

const struct gpio_lock_config *soc_gpio_lock_config(size_t *num)
{
*num = ARRAY_SIZE(pltrst_pad);
return pltrst_pad;
}
6 changes: 6 additions & 0 deletions src/soc/intel/tigerlake/gpio_pch_h.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPIO_COM0_END,
.num_gpi_regs = NUM_GPIO_COM0_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -100,6 +101,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPIO_COM1_END,
.num_gpi_regs = NUM_GPIO_COM1_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -121,6 +123,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPIO_COM2_END,
.num_gpi_regs = NUM_GPIO_COM2_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -140,6 +143,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPIO_COM3_END,
.num_gpi_regs = NUM_GPIO_COM3_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -161,6 +165,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPIO_COM4_END,
.num_gpi_regs = NUM_GPIO_COM4_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand All @@ -180,6 +185,7 @@ static const struct pad_community tgl_communities[] = {
.last_pad = GPIO_COM5_END,
.num_gpi_regs = NUM_GPIO_COM5_GPI_REGS,
.pad_cfg_base = PAD_CFG_BASE,
.pad_cfg_lock_offset = PAD_CFG_LOCK_OFFSET,
.host_own_reg_0 = HOSTSW_OWN_REG_0,
.gpi_int_sts_reg_0 = GPI_INT_STS_0,
.gpi_int_en_reg_0 = GPI_INT_EN_0,
Expand Down
3 changes: 3 additions & 0 deletions src/soc/intel/tigerlake/include/soc/gpio_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
(NUM_GPIO_COM2_GPI_REGS) +\
(NUM_GPIO_COM4_GPI_REGS) +\
(NUM_GPIO_COM5_GPI_REGS))

#define PAD_CFG_LOCK_OFFSET 0x80

/*
* IOxAPIC IRQs for the GPIOs
*/
Expand Down
3 changes: 3 additions & 0 deletions src/soc/intel/tigerlake/include/soc/gpio_defs_pch_h.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
(NUM_GPIO_COM3_GPI_REGS) +\
(NUM_GPIO_COM4_GPI_REGS) +\
(NUM_GPIO_COM5_GPI_REGS))

#define PAD_CFG_LOCK_OFFSET 0x90

/*
* IOxAPIC IRQs for the GPIOs
*/
Expand Down
Loading