xref: /aosp_15_r20/external/coreboot/src/southbridge/intel/bd82x6x/me_common.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <device/device.h>
5 #include <device/pci.h>
6 #include <device/pci_ops.h>
7 #include <console/console.h>
8 #include <device/pci_ids.h>
9 #include <string.h>
10 #include <delay.h>
11 #include <timer.h>
12 
13 #include "me.h"
14 #include "pch.h"
15 
16 #include <vendorcode/google/chromeos/chromeos.h>
17 
18 /* Path that the BIOS should take based on ME state */
19 static const char *const me_bios_path_values[] = {
20 	[ME_NORMAL_BIOS_PATH]		= "Normal",
21 	[ME_S3WAKE_BIOS_PATH]		= "S3 Wake",
22 	[ME_ERROR_BIOS_PATH]		= "Error",
23 	[ME_RECOVERY_BIOS_PATH]		= "Recovery",
24 	[ME_DISABLE_BIOS_PATH]		= "Disable",
25 	[ME_FIRMWARE_UPDATE_BIOS_PATH]	= "Firmware Update",
26 };
27 
me_get_bios_path_string(int path)28 const char *const me_get_bios_path_string(int path)
29 {
30 	return me_bios_path_values[path];
31 }
32 
33 /* MMIO base address for MEI interface */
34 static u32 *mei_base_address;
35 
mei_dump(void * ptr,int dword,int offset,const char * type)36 static void mei_dump(void *ptr, int dword, int offset, const char *type)
37 {
38 	struct mei_csr *csr;
39 
40 	if (!CONFIG(DEBUG_INTEL_ME))
41 		return;
42 
43 	printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
44 
45 	switch (offset) {
46 	case MEI_H_CSR:
47 	case MEI_ME_CSR_HA:
48 		csr = ptr;
49 		if (!csr) {
50 			printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
51 			break;
52 		}
53 		printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
54 		       "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
55 		       csr->buffer_read_ptr, csr->buffer_write_ptr,
56 		       csr->ready, csr->reset, csr->interrupt_generate,
57 		       csr->interrupt_status, csr->interrupt_enable);
58 		break;
59 	case MEI_ME_CB_RW:
60 	case MEI_H_CB_WW:
61 		printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
62 		break;
63 	default:
64 		printk(BIOS_SPEW, "0x%08x\n", offset);
65 		break;
66 	}
67 }
68 
69 /*
70  * ME/MEI access helpers using memcpy to avoid aliasing.
71  */
72 
mei_read_dword_ptr(void * ptr,int offset)73 void mei_read_dword_ptr(void *ptr, int offset)
74 {
75 	u32 dword = read32(mei_base_address + (offset / sizeof(u32)));
76 	memcpy(ptr, &dword, sizeof(dword));
77 	mei_dump(ptr, dword, offset, "READ");
78 }
79 
mei_write_dword_ptr(void * ptr,int offset)80 void mei_write_dword_ptr(void *ptr, int offset)
81 {
82 	u32 dword = 0;
83 	memcpy(&dword, ptr, sizeof(dword));
84 	write32(mei_base_address + (offset / sizeof(u32)), dword);
85 	mei_dump(ptr, dword, offset, "WRITE");
86 }
87 
read_host_csr(struct mei_csr * csr)88 void read_host_csr(struct mei_csr *csr)
89 {
90 	mei_read_dword_ptr(csr, MEI_H_CSR);
91 }
92 
write_host_csr(struct mei_csr * csr)93 void write_host_csr(struct mei_csr *csr)
94 {
95 	mei_write_dword_ptr(csr, MEI_H_CSR);
96 }
97 
read_me_csr(struct mei_csr * csr)98 void read_me_csr(struct mei_csr *csr)
99 {
100 	mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
101 }
102 
write_cb(u32 dword)103 void write_cb(u32 dword)
104 {
105 	write32(mei_base_address + (MEI_H_CB_WW / sizeof(u32)), dword);
106 	mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
107 }
108 
read_cb(void)109 u32 read_cb(void)
110 {
111 	u32 dword = read32(mei_base_address + (MEI_ME_CB_RW / sizeof(u32)));
112 	mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
113 	return dword;
114 }
115 
116 /* Wait for ME ready bit to be asserted */
mei_wait_for_me_ready(void)117 static int mei_wait_for_me_ready(void)
118 {
119 	struct mei_csr me;
120 	unsigned int try = ME_RETRY;
121 
122 	while (try--) {
123 		read_me_csr(&me);
124 		if (me.ready)
125 			return 0;
126 		udelay(ME_DELAY);
127 	}
128 
129 	printk(BIOS_ERR, "ME: failed to become ready\n");
130 	return -1;
131 }
132 
mei_reset(void)133 static void mei_reset(void)
134 {
135 	struct mei_csr host;
136 
137 	if (mei_wait_for_me_ready() < 0)
138 		return;
139 
140 	/* Reset host and ME circular buffers for next message */
141 	read_host_csr(&host);
142 	host.reset = 1;
143 	host.interrupt_generate = 1;
144 	write_host_csr(&host);
145 
146 	if (mei_wait_for_me_ready() < 0)
147 		return;
148 
149 	/* Re-init and indicate host is ready */
150 	read_host_csr(&host);
151 	host.interrupt_generate = 1;
152 	host.ready = 1;
153 	host.reset = 0;
154 	write_host_csr(&host);
155 }
156 
mei_send_msg(struct mei_header * mei,struct mkhi_header * mkhi,void * req_data)157 static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, void *req_data)
158 {
159 	struct mei_csr host;
160 	unsigned int ndata, n;
161 	u32 *data;
162 
163 	/* Number of dwords to write, ignoring MKHI */
164 	ndata = mei->length >> 2;
165 
166 	/* Pad non-dword aligned request message length */
167 	if (mei->length & 3)
168 		ndata++;
169 
170 	if (!ndata) {
171 		printk(BIOS_DEBUG, "ME: request does not include MKHI\n");
172 		return -1;
173 	}
174 	ndata++; /* Add MEI header */
175 
176 	/*
177 	 * Make sure there is still room left in the circular buffer.
178 	 * Reset the buffer pointers if the requested message will not fit.
179 	 */
180 	read_host_csr(&host);
181 	if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
182 		printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
183 		mei_reset();
184 		read_host_csr(&host);
185 	}
186 
187 	/*
188 	 * This implementation does not handle splitting large messages
189 	 * across multiple transactions.  Ensure the requested length
190 	 * will fit in the available circular buffer depth.
191 	 */
192 	if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
193 		printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
194 		       ndata + 2, host.buffer_depth);
195 		return -1;
196 	}
197 
198 	/* Write MEI header */
199 	mei_write_dword_ptr(mei, MEI_H_CB_WW);
200 	ndata--;
201 
202 	/* Write MKHI header */
203 	mei_write_dword_ptr(mkhi, MEI_H_CB_WW);
204 	ndata--;
205 
206 	/* Write message data */
207 	data = req_data;
208 	for (n = 0; n < ndata; ++n)
209 		write_cb(*data++);
210 
211 	/* Generate interrupt to the ME */
212 	read_host_csr(&host);
213 	host.interrupt_generate = 1;
214 	write_host_csr(&host);
215 
216 	/* Make sure ME is ready after sending request data */
217 	return mei_wait_for_me_ready();
218 }
219 
mei_recv_msg(struct mkhi_header * mkhi,void * rsp_data,int rsp_bytes)220 static int mei_recv_msg(struct mkhi_header *mkhi, void *rsp_data, int rsp_bytes)
221 {
222 	struct mei_header mei_rsp;
223 	struct mkhi_header mkhi_rsp;
224 	struct mei_csr me, host;
225 	unsigned int ndata, n;
226 	unsigned int expected;
227 	u32 *data;
228 
229 	/* Total number of dwords to read from circular buffer */
230 	expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2;
231 	if (rsp_bytes & 3)
232 		expected++;
233 
234 	/*
235 	 * The interrupt status bit does not appear to indicate that the
236 	 * message has actually been received.  Instead we wait until the
237 	 * expected number of dwords are present in the circular buffer.
238 	 */
239 	for (n = ME_RETRY; n; --n) {
240 		read_me_csr(&me);
241 		if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
242 			break;
243 		udelay(ME_DELAY);
244 	}
245 
246 	if (!n) {
247 		printk(BIOS_ERR, "ME: timeout waiting for data: expected %u, available %u\n",
248 		       expected, me.buffer_write_ptr - me.buffer_read_ptr);
249 		return -1;
250 	}
251 
252 	/* Read and verify MEI response header from the ME */
253 	mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
254 	if (!mei_rsp.is_complete) {
255 		printk(BIOS_ERR, "ME: response is not complete\n");
256 		return -1;
257 	}
258 
259 	/* Handle non-dword responses and expect at least MKHI header */
260 	ndata = mei_rsp.length >> 2;
261 	if (mei_rsp.length & 3)
262 		ndata++;
263 
264 	if (ndata != (expected - 1)) {
265 		printk(BIOS_ERR, "ME: response is missing data %d != %d\n",
266 		       ndata, (expected - 1));
267 		return -1;
268 	}
269 
270 	/* Read and verify MKHI response header from the ME */
271 	mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW);
272 	if (!mkhi_rsp.is_response ||
273 	    mkhi->group_id != mkhi_rsp.group_id ||
274 	    mkhi->command != mkhi_rsp.command) {
275 		printk(BIOS_ERR, "ME: invalid response, group %u ?= %u, "
276 		       "command %u ?= %u, is_response %u\n", mkhi->group_id,
277 		       mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
278 		       mkhi_rsp.is_response);
279 		return -1;
280 	}
281 	ndata--; /* MKHI header has been read */
282 
283 	/* Make sure caller passed a buffer with enough space */
284 	if (ndata != (rsp_bytes >> 2)) {
285 		printk(BIOS_ERR, "ME: not enough room in response buffer: %u != %u\n",
286 		       ndata, rsp_bytes >> 2);
287 		return -1;
288 	}
289 
290 	/* Read response data from the circular buffer */
291 	data = rsp_data;
292 	for (n = 0; n < ndata; ++n)
293 		*data++ = read_cb();
294 
295 	/* Tell the ME that we have consumed the response */
296 	read_host_csr(&host);
297 	host.interrupt_status = 1;
298 	host.interrupt_generate = 1;
299 	write_host_csr(&host);
300 
301 	return mei_wait_for_me_ready();
302 }
303 
mei_sendrecv(struct mei_header * mei,struct mkhi_header * mkhi,void * req_data,void * rsp_data,int rsp_bytes)304 int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi,
305 		 void *req_data, void *rsp_data, int rsp_bytes)
306 {
307 	if (mei_send_msg(mei, mkhi, req_data) < 0)
308 		return -1;
309 	if (mei_recv_msg(mkhi, rsp_data, rsp_bytes) < 0)
310 		return -1;
311 	return 0;
312 }
313 
314 #ifdef __SIMPLE_DEVICE__
315 
update_mei_base_address(void)316 void update_mei_base_address(void)
317 {
318 	uint32_t reg32 = pci_read_config32(PCH_ME_DEV, PCI_BASE_ADDRESS_0) & ~0xf;
319 	mei_base_address = (u32 *)(uintptr_t)reg32;
320 }
321 
is_mei_base_address_valid(void)322 bool is_mei_base_address_valid(void)
323 {
324 	return mei_base_address && mei_base_address != (u32 *)0xfffffff0;
325 }
326 
327 #else
328 
329 /* Prepare ME for MEI messages */
intel_mei_setup(struct device * dev)330 int intel_mei_setup(struct device *dev)
331 {
332 	struct resource *res;
333 	struct mei_csr host;
334 
335 	/* Find the MMIO base for the ME interface */
336 	res = probe_resource(dev, PCI_BASE_ADDRESS_0);
337 	if (!res || res->base == 0 || res->size == 0) {
338 		printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
339 		return -1;
340 	}
341 	mei_base_address = (u32 *)(uintptr_t)res->base;
342 
343 	/* Ensure Memory and Bus Master bits are set */
344 	pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
345 
346 	/* Clean up status for next message */
347 	read_host_csr(&host);
348 	host.interrupt_generate = 1;
349 	host.ready = 1;
350 	host.reset = 0;
351 	write_host_csr(&host);
352 
353 	return 0;
354 }
355 
356 /* Read the Extend register hash of ME firmware */
intel_me_extend_valid(struct device * dev)357 int intel_me_extend_valid(struct device *dev)
358 {
359 	union me_heres status;
360 	u32 extend[8] = {0};
361 	int i, count = 0;
362 
363 	status.raw = pci_read_config32(dev, PCI_ME_HERES);
364 	if (!status.extend_feature_present) {
365 		printk(BIOS_ERR, "ME: Extend Feature not present\n");
366 		return -1;
367 	}
368 
369 	if (!status.extend_reg_valid) {
370 		printk(BIOS_ERR, "ME: Extend Register not valid\n");
371 		return -1;
372 	}
373 
374 	switch (status.extend_reg_algorithm) {
375 	case PCI_ME_EXT_SHA1:
376 		count = 5;
377 		printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
378 		break;
379 	case PCI_ME_EXT_SHA256:
380 		count = 8;
381 		printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
382 		break;
383 	default:
384 		printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
385 		       status.extend_reg_algorithm);
386 		return -1;
387 	}
388 
389 	for (i = 0; i < count; ++i) {
390 		extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
391 		printk(BIOS_DEBUG, "%08x", extend[i]);
392 	}
393 	printk(BIOS_DEBUG, "\n");
394 
395 	/* Save hash in NVS for the OS to verify */
396 	if (CONFIG(CHROMEOS_NVS))
397 		chromeos_set_me_hash(extend, count);
398 
399 	return 0;
400 }
401 
402 /* Hide the ME virtual PCI devices */
intel_me_hide(struct device * dev)403 void intel_me_hide(struct device *dev)
404 {
405 	dev->enabled = 0;
406 	pch_enable(dev);
407 }
408 
enter_soft_temp_disable(void)409 bool enter_soft_temp_disable(void)
410 {
411 	/* The binary sequence for the disable command was found by PT in some vendor BIOS */
412 	struct me_disable message = {
413 		.rule_id = MKHI_DISABLE_RULE_ID,
414 		.data = 0x01,
415 	};
416 	struct mkhi_header mkhi = {
417 		.group_id	= MKHI_GROUP_ID_FWCAPS,
418 		.command	= MKHI_FWCAPS_SET_RULE,
419 	};
420 	struct mei_header mei = {
421 		.is_complete	= 1,
422 		.length		= sizeof(mkhi) + sizeof(message),
423 		.host_address	= MEI_HOST_ADDRESS,
424 		.client_address	= MEI_ADDRESS_MKHI,
425 	};
426 	u32 resp;
427 
428 	if (mei_sendrecv(&mei, &mkhi, &message, &resp, sizeof(resp)) < 0
429 	    || resp != MKHI_DISABLE_RULE_ID) {
430 		printk(BIOS_WARNING, "ME: disable command failed\n");
431 		return false;
432 	}
433 
434 	return true;
435 }
436 
enter_soft_temp_disable_wait(void)437 void enter_soft_temp_disable_wait(void)
438 {
439 	/*
440 	 * TODO: Find smarter way to determine when we're ready to reboot.
441 	 *
442 	 * There has to be some bit in some register, or something, that indicates that ME has
443 	 * finished doing its thing and we're ready to reboot.
444 	 *
445 	 * It was not found yet, though, and waiting for a response after the disable command is
446 	 * not enough. If we reboot too early, ME will not be disabled on next boot. For now,
447 	 * let's just wait for 1 second here.
448 	 */
449 	mdelay(1000);
450 }
451 
exit_soft_temp_disable(struct device * dev)452 void exit_soft_temp_disable(struct device *dev)
453 {
454 	/* To bring ME out of Soft Temporary Disable Mode, host writes 0x20000000 to H_GS */
455 	pci_write_config32(dev, PCI_ME_H_GS, 0x2 << 28);
456 }
457 
exit_soft_temp_disable_wait(struct device * dev)458 void exit_soft_temp_disable_wait(struct device *dev)
459 {
460 	union me_hfs hfs;
461 	struct stopwatch sw;
462 
463 	stopwatch_init_msecs_expire(&sw, ME_ENABLE_TIMEOUT);
464 
465 	/**
466 	 * Wait for fw_init_complete. Check every 50 ms, give up after 20 sec.
467 	 * This is what vendor BIOS does. Usually it takes 1.5 seconds or so.
468 	 */
469 	do {
470 		mdelay(50);
471 		hfs.raw = pci_read_config32(dev, PCI_ME_HFS);
472 		if (hfs.fw_init_complete)
473 			break;
474 	} while (!stopwatch_expired(&sw));
475 
476 	if (!hfs.fw_init_complete)
477 		printk(BIOS_ERR, "ME: giving up on waiting for fw_init_complete\n");
478 	else
479 		printk(BIOS_NOTICE, "ME: took %lldms to complete initialization\n",
480 		       stopwatch_duration_msecs(&sw));
481 }
482 
483 #endif
484