summaryrefslogtreecommitdiff
path: root/src/soc/intel/common/block/smm/smitraphandler.c
blob: 75746000b81486157a546665a5a33b607f27f168 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */

#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;
	global_nvs_t *gnvs = smm_get_gnvs();

	/* 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, "  iotrap read data = 0x%08x\n", data);
		}
	}

	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
}