diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/intel/common/block/smm/Kconfig | 5 | ||||
-rw-r--r-- | src/soc/intel/common/block/smm/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/intel/common/block/smm/smitraphandler.c | 128 |
3 files changed, 134 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/smm/Kconfig b/src/soc/intel/common/block/smm/Kconfig index 003fc24cd8..035578003a 100644 --- a/src/soc/intel/common/block/smm/Kconfig +++ b/src/soc/intel/common/block/smm/Kconfig @@ -2,3 +2,8 @@ config SOC_INTEL_COMMON_BLOCK_SMM bool help Intel Processor common SMM support + +config SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP + bool + help + Intel Processor trap flag if it is supported diff --git a/src/soc/intel/common/block/smm/Makefile.inc b/src/soc/intel/common/block/smm/Makefile.inc index 13793ee891..e50562513e 100644 --- a/src/soc/intel/common/block/smm/Makefile.inc +++ b/src/soc/intel/common/block/smm/Makefile.inc @@ -1,2 +1,3 @@ ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMM) += smm.c smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMM) += smihandler.c +smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP) += smitraphandler.c diff --git a/src/soc/intel/common/block/smm/smitraphandler.c b/src/soc/intel/common/block/smm/smitraphandler.c new file mode 100644 index 0000000000..4a51cdebfc --- /dev/null +++ b/src/soc/intel/common/block/smm/smitraphandler.c @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2015-2017 Intel Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <console/console.h> +#include <cpu/x86/smm.h> +#include <intelblocks/fast_spi.h> +#include <intelblocks/pcr.h> +#include <intelblocks/smihandler.h> +#include <soc/gpio.h> +#include <soc/iomap.h> +#include <soc/nvs.h> +#include <soc/pcr_ids.h> +#include <soc/pm.h> +#include <soc/pmc.h> + +/* IO Trap PCRs */ +/* Trap status Register */ +#define PCR_PSTH_TRPST 0x1E00 +/* Trapped cycle */ +#define PCR_PSTH_TRPC 0x1E10 +/* Trapped write data */ +#define PCR_PSTH_TRPD 0x1E18 + +/* Inherited from cpu/x86/smm.h resulting in a different signature */ +int southbridge_io_trap_handler(int smif) +{ + global_nvs_t *gnvs = smm_get_gnvs(); + switch (smif) { + case 0x32: + printk(BIOS_DEBUG, "OS Init\n"); + /* + * gnvs->smif: + * - On success, the IO Trap Handler returns 0 + * - On failure, the IO Trap Handler returns a value != 0 + */ + gnvs->smif = 0; + return 1; /* IO trap handled */ + } + + /* Not handled */ + return 0; +} + +void smihandler_southbridge_mc( + const struct smm_save_state_ops *save_state_ops) +{ + u32 reg32 = inl(ACPI_BASE_ADDRESS + SMI_EN); + + /* Are microcontroller SMIs enabled? */ + if ((reg32 & MCSMI_EN) == 0) + return; + + printk(BIOS_DEBUG, "Microcontroller SMI.\n"); +} + +void smihandler_southbridge_monitor( + const struct smm_save_state_ops *save_state_ops) +{ +#define IOTRAP(x) (trap_sts & (1 << x)) + u32 trap_cycle; + u32 data, mask = 0; + u8 trap_sts; + int i; + /* TRSR - Trap Status Register */ + trap_sts = pcr_read8(PID_PSTH, PCR_PSTH_TRPST); + /* Clear trap(s) in TRSR */ + pcr_write8(PID_PSTH, PCR_PSTH_TRPST, trap_sts); + + /* TRPC - Trapped cycle */ + trap_cycle = pcr_read32(PID_PSTH, PCR_PSTH_TRPC); + for (i = 16; i < 20; i++) { + if (trap_cycle & (1 << i)) + mask |= (0xff << ((i - 16) << 2)); + } + + /* IOTRAP(3) SMI function call */ + if (IOTRAP(3)) { + if (gnvs && gnvs->smif) + io_trap_handler(gnvs->smif); + return; + } + + /* + * IOTRAP(2) currently unused + * IOTRAP(1) currently unused + */ + + /* IOTRAP(0) SMIC */ + if (IOTRAP(0)) { + if (!(trap_cycle & (1 << 24))) { /* It's a write */ + printk(BIOS_DEBUG, "SMI1 command\n"); + /* Trapped write data */ + data = pcr_read32(PID_PSTH, PCR_PSTH_TRPD); + data &= mask; + } + } + + printk(BIOS_DEBUG, " trapped io address = 0x%x\n", + trap_cycle & 0xfffc); + for (i = 0; i < 4; i++) + if (IOTRAP(i)) + printk(BIOS_DEBUG, " TRAP = %d\n", i); + printk(BIOS_DEBUG, " AHBE = %x\n", (trap_cycle >> 16) & 0xf); + printk(BIOS_DEBUG, " MASK = 0x%08x\n", mask); + printk(BIOS_DEBUG, " read/write: %s\n", + (trap_cycle & (1 << 24)) ? "read" : "write"); + + if (!(trap_cycle & (1 << 24))) { + /* Write Cycle */ + data = pcr_read32(PID_PSTH, PCR_PSTH_TRPD); + printk(BIOS_DEBUG, " iotrap written data = 0x%08x\n", data); + } +#undef IOTRAP +} |