blob: 0f11809297cf1286bd28d9c5072dd7f785581841 [file] [log] [blame]
Angel Pons6bc13742020-04-05 15:46:38 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin7d14af82017-02-07 11:33:56 -06002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Aaron Durbin7d14af82017-02-07 11:33:56 -06004#include <bootstate.h>
Andrey Petrovc5f36852017-03-12 00:51:34 -08005#include <commonlib/region.h>
Aaron Durbin7d14af82017-02-07 11:33:56 -06006#include <console/console.h>
Andrey Petrovc5f36852017-03-12 00:51:34 -08007#include <fmap.h>
Andrey Petrovb1aded22017-03-03 08:12:36 -08008#include <intelblocks/cse.h>
Furquan Shaikhd2c2f832018-11-07 10:24:31 -08009#include <intelblocks/p2sb.h>
10#include <intelblocks/pcr.h>
11#include <soc/heci.h>
12#include <soc/iomap.h>
13#include <soc/pcr_ids.h>
Aaron Durbin7d14af82017-02-07 11:33:56 -060014#include <soc/pci_devs.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020015#include <device/pci_ops.h>
Aaron Durbin7d14af82017-02-07 11:33:56 -060016#include <stdint.h>
17
Andrey Petrovb1aded22017-03-03 08:12:36 -080018#define MKHI_GROUP_ID_MCA 0x0a
19#define READ_FILE 0x02
20#define READ_FILE_FLAG_DEFAULT (1 << 0)
21#define READ_FILE_FLAG_HASH (1 << 1)
22#define READ_FILE_FLAG_EMULATED (1 << 2)
23#define READ_FILE_FLAG_HW (1 << 3)
24
25#define MCA_MAX_FILE_PATH_SIZE 64
26
27#define FUSE_LOCK_FILE "/fpf/intel/SocCfgLock"
28
Andrey Petrovc5f36852017-03-12 00:51:34 -080029/* Status values are made in such a way erase is not needed */
30static enum fuse_flash_state {
31 FUSE_FLASH_FUSED = 0xfc,
32 FUSE_FLASH_UNFUSED = 0xfe,
33 FUSE_FLASH_UNKNOWN = 0xff,
34} g_fuse_state;
35
36#define FPF_STATUS_FMAP "FPF_STATUS"
Andrey Petrovb1aded22017-03-03 08:12:36 -080037
38/*
39 * Read file from CSE internal filesystem.
40 * size is maximum length of provided buffer buff, which is updated with actual
41 * size of the file read. flags indicate whether real file or fuse is used.
42 * Returns 1 on success and 0 otherwise.
43 */
44static int read_cse_file(const char *path, void *buff, size_t *size,
45 size_t offset, uint32_t flags)
46{
Andrey Petrovb1aded22017-03-03 08:12:36 -080047 size_t reply_size;
48
Andrey Petrovb1aded22017-03-03 08:12:36 -080049 struct mca_command {
Sridhar Siricillaf35eee92019-09-23 19:38:21 +053050 struct mkhi_hdr hdr;
Andrey Petrovb1aded22017-03-03 08:12:36 -080051 char file_name[MCA_MAX_FILE_PATH_SIZE];
52 uint32_t offset;
53 uint32_t data_size;
54 uint8_t flags;
Stefan Reinauer6a001132017-07-13 02:20:27 +020055 } __packed msg;
Andrey Petrovb1aded22017-03-03 08:12:36 -080056
57 struct mca_response {
Sridhar Siricillaf35eee92019-09-23 19:38:21 +053058 struct mkhi_hdr hdr;
Andrey Petrovb1aded22017-03-03 08:12:36 -080059 uint32_t data_size;
60 uint8_t buffer[128];
Stefan Reinauer6a001132017-07-13 02:20:27 +020061 } __packed rmsg;
Andrey Petrovb1aded22017-03-03 08:12:36 -080062
63 if (sizeof(rmsg.buffer) < *size) {
64 printk(BIOS_ERR, "internal buffer is too small\n");
65 return 0;
66 }
67
Hannah Williams58810c72017-08-02 18:13:33 -070068 if (strnlen(path, sizeof(msg.file_name)) >= sizeof(msg.file_name)) {
69 printk(BIOS_ERR, "path too big for msg.file_name buffer\n");
70 return 0;
71 }
Andrey Petrovb1aded22017-03-03 08:12:36 -080072 strncpy(msg.file_name, path, sizeof(msg.file_name));
Sridhar Siricillaf35eee92019-09-23 19:38:21 +053073 msg.hdr.group_id = MKHI_GROUP_ID_MCA;
74 msg.hdr.command = READ_FILE;
Andrey Petrovb1aded22017-03-03 08:12:36 -080075 msg.flags = flags;
76 msg.data_size = *size;
77 msg.offset = offset;
78
Andrey Petrovb1aded22017-03-03 08:12:36 -080079 reply_size = sizeof(rmsg);
Andrey Petrovb1aded22017-03-03 08:12:36 -080080
Sridhar Siricilla6836da22022-02-23 23:36:45 +053081 if (heci_send_receive(&msg, sizeof(msg), &rmsg, &reply_size, HECI_MKHI_ADDR)) {
Rizwan Qureshi957857d2021-08-30 16:43:57 +053082 printk(BIOS_ERR, "HECI: Failed to read file\n");
Andrey Petrovb1aded22017-03-03 08:12:36 -080083 return 0;
84 }
85
86 if (rmsg.data_size > *size) {
87 printk(BIOS_ERR, "reply is too large\n");
88 return 0;
89 }
90
91 memcpy(buff, rmsg.buffer, rmsg.data_size);
92 *size = rmsg.data_size;
93
94 return 1;
95}
96
Andrey Petrovc5f36852017-03-12 00:51:34 -080097static enum fuse_flash_state load_cached_fpf(struct region_device *rdev)
98{
99 enum fuse_flash_state state;
100 uint8_t buff;
101
102 state = FUSE_FLASH_UNKNOWN;
103
104 if (rdev_readat(rdev, &buff, 0, sizeof(buff)) >= 0) {
105 state = read8(&buff);
106 return state;
107 }
108
109 printk(BIOS_WARNING, "failed to load cached FPF value\n");
110
111 return state;
112}
113
114static
115int save_fpf_state(enum fuse_flash_state state, struct region_device *rdev)
116{
117 uint8_t buff;
118
119 write8(&buff, (uint8_t) state);
120 return rdev_writeat(rdev, &buff, 0, sizeof(buff));
121}
122
Andrey Petrovb1aded22017-03-03 08:12:36 -0800123static void fpf_blown(void *unused)
124{
Andrey Petrovc5f36852017-03-12 00:51:34 -0800125 uint8_t fuse;
126 struct region_device rdev;
Andrey Petrovb1aded22017-03-03 08:12:36 -0800127 size_t sz = sizeof(fuse);
Andrey Petrovc5f36852017-03-12 00:51:34 -0800128 bool rdev_valid = false;
Andrey Petrovb1aded22017-03-03 08:12:36 -0800129
Andrey Petrovc5f36852017-03-12 00:51:34 -0800130 if (fmap_locate_area_as_rdev_rw(FPF_STATUS_FMAP, &rdev) == 0) {
131 rdev_valid = true;
132 g_fuse_state = load_cached_fpf(&rdev);
133 if (g_fuse_state != FUSE_FLASH_UNKNOWN)
134 return;
Andrey Petrovb1aded22017-03-03 08:12:36 -0800135 }
Andrey Petrovc5f36852017-03-12 00:51:34 -0800136
137 if (!read_cse_file(FUSE_LOCK_FILE, &fuse, &sz, 0, READ_FILE_FLAG_HW))
138 return;
139
140 g_fuse_state = fuse == 1 ? FUSE_FLASH_FUSED : FUSE_FLASH_UNFUSED;
141
142 if (rdev_valid && (save_fpf_state(g_fuse_state, &rdev) < 0))
143 printk(BIOS_CRIT, "failed to save FPF state\n");
Andrey Petrovb1aded22017-03-03 08:12:36 -0800144}
145
Aaron Durbin7d14af82017-02-07 11:33:56 -0600146static uint32_t dump_status(int index, int reg_addr)
147{
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530148 uint32_t reg;
149
150 reg = me_read_config32(reg_addr);
Aaron Durbin7d14af82017-02-07 11:33:56 -0600151
152 printk(BIOS_DEBUG, "CSE FWSTS%d: 0x%08x\n", index, reg);
153
154 return reg;
155}
156
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800157static void dump_cse_state(void)
Aaron Durbin7d14af82017-02-07 11:33:56 -0600158{
159 uint32_t fwsts1;
160
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530161 if (!is_cse_enabled())
162 return;
163
Aaron Durbin7d14af82017-02-07 11:33:56 -0600164 fwsts1 = dump_status(1, PCI_ME_HFSTS1);
165 dump_status(2, PCI_ME_HFSTS2);
166 dump_status(3, PCI_ME_HFSTS3);
167 dump_status(4, PCI_ME_HFSTS4);
168 dump_status(5, PCI_ME_HFSTS5);
169 dump_status(6, PCI_ME_HFSTS6);
170
171 /* Minimal decoding is done here in order to call out most important
172 pieces. Manufacturing mode needs to be locked down prior to shipping
173 the product so it's called out explicitly. */
174 printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n",
175 (fwsts1 & (1 << 0x4)) ? "YES" : "NO");
Aaron Durbin7d14af82017-02-07 11:33:56 -0600176
Andrey Petrovb1aded22017-03-03 08:12:36 -0800177 printk(BIOS_DEBUG, "ME: FPF status : ");
Andrey Petrovc5f36852017-03-12 00:51:34 -0800178 switch (g_fuse_state) {
179 case FUSE_FLASH_UNFUSED:
Andrey Petrovb1aded22017-03-03 08:12:36 -0800180 printk(BIOS_DEBUG, "unfused");
181 break;
Andrey Petrovc5f36852017-03-12 00:51:34 -0800182 case FUSE_FLASH_FUSED:
Andrey Petrovb1aded22017-03-03 08:12:36 -0800183 printk(BIOS_DEBUG, "fused");
184 break;
185 default:
Andrey Petrovc5f36852017-03-12 00:51:34 -0800186 case FUSE_FLASH_UNKNOWN:
Andrey Petrovb1aded22017-03-03 08:12:36 -0800187 printk(BIOS_DEBUG, "unknown");
188 }
189 printk(BIOS_DEBUG, "\n");
190}
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800191
192#define PCR_PSFX_T0_SHDW_PCIEN 0x1C
193#define PCR_PSFX_T0_SHDW_PCIEN_FUNDIS (1 << 8)
194
Subrata Banikea47c6b2022-01-28 13:12:58 +0530195void soc_disable_heci1_using_pcr(void)
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800196{
197 pcr_or32(PID_PSF3, PSF3_BASE_ADDRESS + PCR_PSFX_T0_SHDW_PCIEN,
198 PCR_PSFX_T0_SHDW_PCIEN_FUNDIS);
199}
200
201void heci_cse_lockdown(void)
202{
203 dump_cse_state();
204
205 /*
206 * It is safe to disable HECI1 now since we won't be talking to the ME
207 * anymore.
208 */
Subrata Banik206b0bc2022-01-06 09:34:43 +0000209 if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
Subrata Banikea47c6b2022-01-28 13:12:58 +0530210 heci1_disable();
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800211}
212
Andrey Petrovb1aded22017-03-03 08:12:36 -0800213BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, fpf_blown, NULL);
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530214BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, print_me_fw_version, NULL);