blob: 46bc8fb294858abaacf6504b62b0d4fcfa208fa4 [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>
Sean Rhodese71ea1e2022-07-19 11:20:05 +010011#include <soc/cse.h>
Furquan Shaikhd2c2f832018-11-07 10:24:31 -080012#include <soc/heci.h>
13#include <soc/iomap.h>
14#include <soc/pcr_ids.h>
Aaron Durbin7d14af82017-02-07 11:33:56 -060015#include <soc/pci_devs.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020016#include <device/pci_ops.h>
Aaron Durbin7d14af82017-02-07 11:33:56 -060017#include <stdint.h>
18
Andrey Petrovb1aded22017-03-03 08:12:36 -080019#define MKHI_GROUP_ID_MCA 0x0a
20#define READ_FILE 0x02
21#define READ_FILE_FLAG_DEFAULT (1 << 0)
22#define READ_FILE_FLAG_HASH (1 << 1)
23#define READ_FILE_FLAG_EMULATED (1 << 2)
24#define READ_FILE_FLAG_HW (1 << 3)
25
26#define MCA_MAX_FILE_PATH_SIZE 64
27
28#define FUSE_LOCK_FILE "/fpf/intel/SocCfgLock"
29
Andrey Petrovc5f36852017-03-12 00:51:34 -080030/* Status values are made in such a way erase is not needed */
31static enum fuse_flash_state {
32 FUSE_FLASH_FUSED = 0xfc,
33 FUSE_FLASH_UNFUSED = 0xfe,
34 FUSE_FLASH_UNKNOWN = 0xff,
35} g_fuse_state;
36
37#define FPF_STATUS_FMAP "FPF_STATUS"
Andrey Petrovb1aded22017-03-03 08:12:36 -080038
39/*
40 * Read file from CSE internal filesystem.
41 * size is maximum length of provided buffer buff, which is updated with actual
42 * size of the file read. flags indicate whether real file or fuse is used.
43 * Returns 1 on success and 0 otherwise.
44 */
45static int read_cse_file(const char *path, void *buff, size_t *size,
46 size_t offset, uint32_t flags)
47{
Andrey Petrovb1aded22017-03-03 08:12:36 -080048 size_t reply_size;
49
Andrey Petrovb1aded22017-03-03 08:12:36 -080050 struct mca_command {
Sridhar Siricillaf35eee92019-09-23 19:38:21 +053051 struct mkhi_hdr hdr;
Andrey Petrovb1aded22017-03-03 08:12:36 -080052 char file_name[MCA_MAX_FILE_PATH_SIZE];
53 uint32_t offset;
54 uint32_t data_size;
55 uint8_t flags;
Stefan Reinauer6a001132017-07-13 02:20:27 +020056 } __packed msg;
Andrey Petrovb1aded22017-03-03 08:12:36 -080057
58 struct mca_response {
Sridhar Siricillaf35eee92019-09-23 19:38:21 +053059 struct mkhi_hdr hdr;
Andrey Petrovb1aded22017-03-03 08:12:36 -080060 uint32_t data_size;
61 uint8_t buffer[128];
Stefan Reinauer6a001132017-07-13 02:20:27 +020062 } __packed rmsg;
Andrey Petrovb1aded22017-03-03 08:12:36 -080063
64 if (sizeof(rmsg.buffer) < *size) {
65 printk(BIOS_ERR, "internal buffer is too small\n");
66 return 0;
67 }
68
Hannah Williams58810c72017-08-02 18:13:33 -070069 if (strnlen(path, sizeof(msg.file_name)) >= sizeof(msg.file_name)) {
70 printk(BIOS_ERR, "path too big for msg.file_name buffer\n");
71 return 0;
72 }
Andrey Petrovb1aded22017-03-03 08:12:36 -080073 strncpy(msg.file_name, path, sizeof(msg.file_name));
Sridhar Siricillaf35eee92019-09-23 19:38:21 +053074 msg.hdr.group_id = MKHI_GROUP_ID_MCA;
75 msg.hdr.command = READ_FILE;
Andrey Petrovb1aded22017-03-03 08:12:36 -080076 msg.flags = flags;
77 msg.data_size = *size;
78 msg.offset = offset;
79
Andrey Petrovb1aded22017-03-03 08:12:36 -080080 reply_size = sizeof(rmsg);
Andrey Petrovb1aded22017-03-03 08:12:36 -080081
Sridhar Siricilla6836da22022-02-23 23:36:45 +053082 if (heci_send_receive(&msg, sizeof(msg), &rmsg, &reply_size, HECI_MKHI_ADDR)) {
Rizwan Qureshi957857d2021-08-30 16:43:57 +053083 printk(BIOS_ERR, "HECI: Failed to read file\n");
Andrey Petrovb1aded22017-03-03 08:12:36 -080084 return 0;
85 }
86
87 if (rmsg.data_size > *size) {
88 printk(BIOS_ERR, "reply is too large\n");
89 return 0;
90 }
91
92 memcpy(buff, rmsg.buffer, rmsg.data_size);
93 *size = rmsg.data_size;
94
95 return 1;
96}
97
Andrey Petrovc5f36852017-03-12 00:51:34 -080098static enum fuse_flash_state load_cached_fpf(struct region_device *rdev)
99{
100 enum fuse_flash_state state;
101 uint8_t buff;
102
103 state = FUSE_FLASH_UNKNOWN;
104
105 if (rdev_readat(rdev, &buff, 0, sizeof(buff)) >= 0) {
106 state = read8(&buff);
107 return state;
108 }
109
110 printk(BIOS_WARNING, "failed to load cached FPF value\n");
111
112 return state;
113}
114
115static
116int save_fpf_state(enum fuse_flash_state state, struct region_device *rdev)
117{
118 uint8_t buff;
119
Elyes Haouas9018dee2022-11-18 15:07:33 +0100120 write8(&buff, (uint8_t)state);
Andrey Petrovc5f36852017-03-12 00:51:34 -0800121 return rdev_writeat(rdev, &buff, 0, sizeof(buff));
122}
123
Andrey Petrovb1aded22017-03-03 08:12:36 -0800124static void fpf_blown(void *unused)
125{
Andrey Petrovc5f36852017-03-12 00:51:34 -0800126 uint8_t fuse;
127 struct region_device rdev;
Andrey Petrovb1aded22017-03-03 08:12:36 -0800128 size_t sz = sizeof(fuse);
Andrey Petrovc5f36852017-03-12 00:51:34 -0800129 bool rdev_valid = false;
Andrey Petrovb1aded22017-03-03 08:12:36 -0800130
Andrey Petrovc5f36852017-03-12 00:51:34 -0800131 if (fmap_locate_area_as_rdev_rw(FPF_STATUS_FMAP, &rdev) == 0) {
132 rdev_valid = true;
133 g_fuse_state = load_cached_fpf(&rdev);
134 if (g_fuse_state != FUSE_FLASH_UNKNOWN)
135 return;
Andrey Petrovb1aded22017-03-03 08:12:36 -0800136 }
Andrey Petrovc5f36852017-03-12 00:51:34 -0800137
138 if (!read_cse_file(FUSE_LOCK_FILE, &fuse, &sz, 0, READ_FILE_FLAG_HW))
139 return;
140
141 g_fuse_state = fuse == 1 ? FUSE_FLASH_FUSED : FUSE_FLASH_UNFUSED;
142
143 if (rdev_valid && (save_fpf_state(g_fuse_state, &rdev) < 0))
144 printk(BIOS_CRIT, "failed to save FPF state\n");
Andrey Petrovb1aded22017-03-03 08:12:36 -0800145}
146
Aaron Durbin7d14af82017-02-07 11:33:56 -0600147static uint32_t dump_status(int index, int reg_addr)
148{
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530149 uint32_t reg;
150
151 reg = me_read_config32(reg_addr);
Aaron Durbin7d14af82017-02-07 11:33:56 -0600152
153 printk(BIOS_DEBUG, "CSE FWSTS%d: 0x%08x\n", index, reg);
154
155 return reg;
156}
157
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800158static void dump_cse_state(void)
Aaron Durbin7d14af82017-02-07 11:33:56 -0600159{
Sean Rhodese71ea1e2022-07-19 11:20:05 +0100160 union cse_fwsts1 fwsts1;
Sean Rhodes03f68202022-07-19 13:50:09 +0100161 union cse_fwsts2 fwsts2;
162 union cse_fwsts3 fwsts3;
163 union cse_fwsts4 fwsts4;
164 union cse_fwsts5 fwsts5;
165 union cse_fwsts6 fwsts6;
Aaron Durbin7d14af82017-02-07 11:33:56 -0600166
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530167 if (!is_cse_enabled())
168 return;
169
Sean Rhodese71ea1e2022-07-19 11:20:05 +0100170 fwsts1.data = dump_status(1, PCI_ME_HFSTS1);
Sean Rhodes03f68202022-07-19 13:50:09 +0100171 fwsts2.data = dump_status(2, PCI_ME_HFSTS2);
172 fwsts3.data = dump_status(3, PCI_ME_HFSTS3);
173 fwsts4.data = dump_status(4, PCI_ME_HFSTS4);
174 fwsts5.data = dump_status(5, PCI_ME_HFSTS5);
175 fwsts6.data = dump_status(6, PCI_ME_HFSTS6);
Aaron Durbin7d14af82017-02-07 11:33:56 -0600176
Sean Rhodese71ea1e2022-07-19 11:20:05 +0100177 printk(BIOS_DEBUG, "CSE: Working State : %u\n",
178 fwsts1.fields.working_state);
179 printk(BIOS_DEBUG, "CSE: Manufacturing Mode : %s\n",
180 fwsts1.fields.mfg_mode ? "YES" : "NO");
181 printk(BIOS_DEBUG, "CSE: Operation State : %u\n",
182 fwsts1.fields.operation_state);
183 printk(BIOS_DEBUG, "CSE: FW Init Complete : %s\n",
184 fwsts1.fields.fw_init_complete ? "YES" : "NO");
185 printk(BIOS_DEBUG, "CSE: Error Code : %u\n",
186 fwsts1.fields.error_code);
187 printk(BIOS_DEBUG, "CSE: Operation Mode : %u\n",
188 fwsts1.fields.operation_mode);
Sean Rhodes03f68202022-07-19 13:50:09 +0100189 printk(BIOS_DEBUG, "CSE: IBB Verification Result: %s\n",
190 fwsts3.fields.ibb_verif_result ? "PASS" : "FAIL");
191 printk(BIOS_DEBUG, "CSE: IBB Verification Done : %s\n",
192 fwsts3.fields.ibb_verif_done ? "YES" : "NO");
193 printk(BIOS_DEBUG, "CSE: Actual IBB Size : %u\n",
194 fwsts3.fields.ibb_size);
195 printk(BIOS_DEBUG, "CSE: Verified Boot Valid : %s\n",
196 fwsts4.fields.txe_veri_boot_valid ? "PASS" : "FAIL");
197 printk(BIOS_DEBUG, "CSE: Verified Boot Test : %s\n",
198 fwsts4.fields.txe_veri_boot_test ? "YES" : "NO");
199 printk(BIOS_DEBUG, "CSE: FPF status : %s\n",
200 fwsts6.fields.fpf_commited ? "FUSED" : "UNFUSED");
201 printk(BIOS_DEBUG, "CSE: Error Status Code : %u\n",
202 fwsts5.fields.error_status_code);
Andrey Petrovb1aded22017-03-03 08:12:36 -0800203}
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800204
205#define PCR_PSFX_T0_SHDW_PCIEN 0x1C
206#define PCR_PSFX_T0_SHDW_PCIEN_FUNDIS (1 << 8)
207
Subrata Banikea47c6b2022-01-28 13:12:58 +0530208void soc_disable_heci1_using_pcr(void)
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800209{
210 pcr_or32(PID_PSF3, PSF3_BASE_ADDRESS + PCR_PSFX_T0_SHDW_PCIEN,
211 PCR_PSFX_T0_SHDW_PCIEN_FUNDIS);
212}
213
214void heci_cse_lockdown(void)
215{
216 dump_cse_state();
217
218 /*
219 * It is safe to disable HECI1 now since we won't be talking to the ME
220 * anymore.
221 */
Subrata Banik206b0bc2022-01-06 09:34:43 +0000222 if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
Subrata Banikea47c6b2022-01-28 13:12:58 +0530223 heci1_disable();
Furquan Shaikhd2c2f832018-11-07 10:24:31 -0800224}
225
Andrey Petrovb1aded22017-03-03 08:12:36 -0800226BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, fpf_blown, NULL);
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530227BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, print_me_fw_version, NULL);