mb/system76/cml-u/dt: Make use of chipset devicetree
[coreboot.git] / src / soc / intel / apollolake / cse.c
blobe82b468436a5748db5e0645687d064381fbb6ff5
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <bootstate.h>
5 #include <commonlib/region.h>
6 #include <console/console.h>
7 #include <fmap.h>
8 #include <intelblocks/cse.h>
9 #include <intelblocks/p2sb.h>
10 #include <intelblocks/pcr.h>
11 #include <soc/cse.h>
12 #include <soc/heci.h>
13 #include <soc/iomap.h>
14 #include <soc/pcr_ids.h>
15 #include <soc/pci_devs.h>
16 #include <device/pci_ops.h>
17 #include <stdint.h>
19 #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)
26 #define MCA_MAX_FILE_PATH_SIZE 64
28 #define FUSE_LOCK_FILE "/fpf/intel/SocCfgLock"
30 /* Status values are made in such a way erase is not needed */
31 static enum fuse_flash_state {
32 FUSE_FLASH_FUSED = 0xfc,
33 FUSE_FLASH_UNFUSED = 0xfe,
34 FUSE_FLASH_UNKNOWN = 0xff,
35 } g_fuse_state;
37 #define FPF_STATUS_FMAP "FPF_STATUS"
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.
45 static int read_cse_file(const char *path, void *buff, size_t *size,
46 size_t offset, uint32_t flags)
48 size_t reply_size;
50 struct mca_command {
51 struct mkhi_hdr hdr;
52 char file_name[MCA_MAX_FILE_PATH_SIZE];
53 uint32_t offset;
54 uint32_t data_size;
55 uint8_t flags;
56 } __packed msg;
58 struct mca_response {
59 struct mkhi_hdr hdr;
60 uint32_t data_size;
61 uint8_t buffer[128];
62 } __packed rmsg;
64 if (sizeof(rmsg.buffer) < *size) {
65 printk(BIOS_ERR, "internal buffer is too small\n");
66 return 0;
69 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;
73 strncpy(msg.file_name, path, sizeof(msg.file_name));
74 msg.hdr.group_id = MKHI_GROUP_ID_MCA;
75 msg.hdr.command = READ_FILE;
76 msg.flags = flags;
77 msg.data_size = *size;
78 msg.offset = offset;
80 reply_size = sizeof(rmsg);
82 if (heci_send_receive(&msg, sizeof(msg), &rmsg, &reply_size, HECI_MKHI_ADDR)) {
83 printk(BIOS_ERR, "HECI: Failed to read file\n");
84 return 0;
87 if (rmsg.data_size > *size) {
88 printk(BIOS_ERR, "reply is too large\n");
89 return 0;
92 memcpy(buff, rmsg.buffer, rmsg.data_size);
93 *size = rmsg.data_size;
95 return 1;
98 static enum fuse_flash_state load_cached_fpf(struct region_device *rdev)
100 enum fuse_flash_state state;
101 uint8_t buff;
103 state = FUSE_FLASH_UNKNOWN;
105 if (rdev_readat(rdev, &buff, 0, sizeof(buff)) >= 0) {
106 state = read8(&buff);
107 return state;
110 printk(BIOS_WARNING, "failed to load cached FPF value\n");
112 return state;
115 static
116 int save_fpf_state(enum fuse_flash_state state, struct region_device *rdev)
118 uint8_t buff;
120 write8(&buff, (uint8_t)state);
121 return rdev_writeat(rdev, &buff, 0, sizeof(buff));
124 static void fpf_blown(void *unused)
126 uint8_t fuse;
127 struct region_device rdev;
128 size_t sz = sizeof(fuse);
129 bool rdev_valid = false;
131 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;
138 if (!read_cse_file(FUSE_LOCK_FILE, &fuse, &sz, 0, READ_FILE_FLAG_HW))
139 return;
141 g_fuse_state = fuse == 1 ? FUSE_FLASH_FUSED : FUSE_FLASH_UNFUSED;
143 if (rdev_valid && (save_fpf_state(g_fuse_state, &rdev) < 0))
144 printk(BIOS_CRIT, "failed to save FPF state\n");
147 static uint32_t dump_status(int index, int reg_addr)
149 uint32_t reg;
151 reg = me_read_config32(reg_addr);
153 printk(BIOS_DEBUG, "CSE FWSTS%d: 0x%08x\n", index, reg);
155 return reg;
158 static void dump_cse_state(void)
160 union cse_fwsts1 fwsts1;
161 union cse_fwsts3 fwsts3;
162 union cse_fwsts4 fwsts4;
163 union cse_fwsts5 fwsts5;
164 union cse_fwsts6 fwsts6;
166 if (!is_cse_enabled())
167 return;
169 fwsts1.data = dump_status(1, PCI_ME_HFSTS1);
170 dump_status(2, PCI_ME_HFSTS2);
171 fwsts3.data = dump_status(3, PCI_ME_HFSTS3);
172 fwsts4.data = dump_status(4, PCI_ME_HFSTS4);
173 fwsts5.data = dump_status(5, PCI_ME_HFSTS5);
174 fwsts6.data = dump_status(6, PCI_ME_HFSTS6);
176 printk(BIOS_DEBUG, "CSE: Working State : %u\n",
177 fwsts1.fields.working_state);
178 printk(BIOS_DEBUG, "CSE: Manufacturing Mode : %s\n",
179 fwsts1.fields.mfg_mode ? "YES" : "NO");
180 printk(BIOS_DEBUG, "CSE: Operation State : %u\n",
181 fwsts1.fields.operation_state);
182 printk(BIOS_DEBUG, "CSE: FW Init Complete : %s\n",
183 fwsts1.fields.fw_init_complete ? "YES" : "NO");
184 printk(BIOS_DEBUG, "CSE: Error Code : %u\n",
185 fwsts1.fields.error_code);
186 printk(BIOS_DEBUG, "CSE: Operation Mode : %u\n",
187 fwsts1.fields.operation_mode);
188 printk(BIOS_DEBUG, "CSE: IBB Verification Result: %s\n",
189 fwsts3.fields.ibb_verif_result ? "PASS" : "FAIL");
190 printk(BIOS_DEBUG, "CSE: IBB Verification Done : %s\n",
191 fwsts3.fields.ibb_verif_done ? "YES" : "NO");
192 printk(BIOS_DEBUG, "CSE: Actual IBB Size : %u\n",
193 fwsts3.fields.ibb_size);
194 printk(BIOS_DEBUG, "CSE: Verified Boot Valid : %s\n",
195 fwsts4.fields.txe_veri_boot_valid ? "PASS" : "FAIL");
196 printk(BIOS_DEBUG, "CSE: Verified Boot Test : %s\n",
197 fwsts4.fields.txe_veri_boot_test ? "YES" : "NO");
198 printk(BIOS_DEBUG, "CSE: FPF status : %s\n",
199 fwsts6.fields.fpf_commited ? "FUSED" : "UNFUSED");
200 printk(BIOS_DEBUG, "CSE: Error Status Code : %u\n",
201 fwsts5.fields.error_status_code);
204 #define PCR_PSFX_T0_SHDW_PCIEN 0x1C
205 #define PCR_PSFX_T0_SHDW_PCIEN_FUNDIS (1 << 8)
207 void soc_disable_heci1_using_pcr(void)
209 pcr_or32(PID_PSF3, PSF3_BASE_ADDRESS + PCR_PSFX_T0_SHDW_PCIEN,
210 PCR_PSFX_T0_SHDW_PCIEN_FUNDIS);
213 void heci_cse_lockdown(void)
215 dump_cse_state();
218 * It is safe to disable HECI1 now since we won't be talking to the ME
219 * anymore.
221 if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
222 heci1_disable();
225 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, fpf_blown, NULL);
226 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, print_me_fw_version, NULL);