blob: 7af969517dcefba8aeb562e5a39c507fe32cfba2 [file] [log] [blame]
Stefan Reinauer8e073822012-04-04 00:07:22 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauer8e073822012-04-04 00:07:22 +020015 */
16
17/*
18 * This is a ramstage driver for the Intel Management Engine found in the
19 * 6-series chipset. It handles the required boot-time messages over the
20 * MMIO-based Management Engine Interface to tell the ME that the BIOS is
21 * finished with POST. Additional messages are defined for debug but are
22 * not used unless the console loglevel is high enough.
23 */
24
25#include <arch/acpi.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020026#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020027#include <device/pci_ops.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020028#include <console/console.h>
29#include <device/pci_ids.h>
30#include <device/pci_def.h>
31#include <string.h>
32#include <delay.h>
Duncan Lauriec1c94352012-07-13 10:11:54 -070033#include <elog.h>
Patrick Georgi546953c2014-11-29 10:38:17 +010034#include <halt.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020035
Elyes HAOUASead574e2018-11-11 20:52:30 +010036#ifndef __SMM__
37#include <device/device.h>
38#include <device/pci.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020039#endif
40
41#include "me.h"
42#include "pch.h"
43
Julius Wernercd49cce2019-03-05 16:53:33 -080044#if CONFIG(CHROMEOS)
Stefan Reinauer8e073822012-04-04 00:07:22 +020045#include <vendorcode/google/chromeos/chromeos.h>
Stefan Reinauer49058c02012-06-11 14:13:09 -070046#include <vendorcode/google/chromeos/gnvs.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020047#endif
48
49#ifndef __SMM__
50/* Path that the BIOS should take based on ME state */
51static const char *me_bios_path_values[] = {
52 [ME_NORMAL_BIOS_PATH] = "Normal",
53 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
54 [ME_ERROR_BIOS_PATH] = "Error",
55 [ME_RECOVERY_BIOS_PATH] = "Recovery",
56 [ME_DISABLE_BIOS_PATH] = "Disable",
57 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
58};
59static int intel_me_read_mbp(me_bios_payload *mbp_data);
60#endif
61
62/* MMIO base address for MEI interface */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080063static u32 *mei_base_address;
Stefan Reinauer8e073822012-04-04 00:07:22 +020064
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +020065
Stefan Reinauer8e073822012-04-04 00:07:22 +020066static void mei_dump(void *ptr, int dword, int offset, const char *type)
67{
68 struct mei_csr *csr;
69
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +020070 if (!CONFIG(DEBUG_INTEL_ME))
71 return;
72
Stefan Reinauer8e073822012-04-04 00:07:22 +020073 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
74
75 switch (offset) {
76 case MEI_H_CSR:
77 case MEI_ME_CSR_HA:
78 csr = ptr;
79 if (!csr) {
80 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
81 break;
82 }
83 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
84 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
85 csr->buffer_read_ptr, csr->buffer_write_ptr,
86 csr->ready, csr->reset, csr->interrupt_generate,
87 csr->interrupt_status, csr->interrupt_enable);
88 break;
89 case MEI_ME_CB_RW:
90 case MEI_H_CB_WW:
91 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
92 break;
93 default:
94 printk(BIOS_SPEW, "0x%08x\n", offset);
95 break;
96 }
97}
Stefan Reinauer8e073822012-04-04 00:07:22 +020098
99/*
100 * ME/MEI access helpers using memcpy to avoid aliasing.
101 */
102
103static inline void mei_read_dword_ptr(void *ptr, int offset)
104{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800105 u32 dword = read32(mei_base_address + (offset/sizeof(u32)));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200106 memcpy(ptr, &dword, sizeof(dword));
107 mei_dump(ptr, dword, offset, "READ");
108}
109
110static inline void mei_write_dword_ptr(void *ptr, int offset)
111{
112 u32 dword = 0;
113 memcpy(&dword, ptr, sizeof(dword));
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800114 write32(mei_base_address + (offset/sizeof(u32)), dword);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200115 mei_dump(ptr, dword, offset, "WRITE");
116}
117
118#ifndef __SMM__
Elyes HAOUASdc035282018-09-18 13:28:49 +0200119static inline void pci_read_dword_ptr(struct device *dev, void *ptr, int offset)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200120{
121 u32 dword = pci_read_config32(dev, offset);
122 memcpy(ptr, &dword, sizeof(dword));
123 mei_dump(ptr, dword, offset, "PCI READ");
124}
125#endif
126
127static inline void read_host_csr(struct mei_csr *csr)
128{
129 mei_read_dword_ptr(csr, MEI_H_CSR);
130}
131
132static inline void write_host_csr(struct mei_csr *csr)
133{
134 mei_write_dword_ptr(csr, MEI_H_CSR);
135}
136
137static inline void read_me_csr(struct mei_csr *csr)
138{
139 mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
140}
141
142static inline void write_cb(u32 dword)
143{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800144 write32(mei_base_address + (MEI_H_CB_WW/sizeof(u32)), dword);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200145 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
146}
147
148static inline u32 read_cb(void)
149{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800150 u32 dword = read32(mei_base_address + (MEI_ME_CB_RW/sizeof(u32)));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200151 mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
152 return dword;
153}
154
155/* Wait for ME ready bit to be asserted */
156static int mei_wait_for_me_ready(void)
157{
158 struct mei_csr me;
Martin Rothff744bf2019-10-23 21:46:03 -0600159 unsigned int try = ME_RETRY;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200160
161 while (try--) {
162 read_me_csr(&me);
163 if (me.ready)
164 return 0;
165 udelay(ME_DELAY);
166 }
167
168 printk(BIOS_ERR, "ME: failed to become ready\n");
169 return -1;
170}
171
172static void mei_reset(void)
173{
174 struct mei_csr host;
175
176 if (mei_wait_for_me_ready() < 0)
177 return;
178
179 /* Reset host and ME circular buffers for next message */
180 read_host_csr(&host);
181 host.reset = 1;
182 host.interrupt_generate = 1;
183 write_host_csr(&host);
184
185 if (mei_wait_for_me_ready() < 0)
186 return;
187
188 /* Re-init and indicate host is ready */
189 read_host_csr(&host);
190 host.interrupt_generate = 1;
191 host.ready = 1;
192 host.reset = 0;
193 write_host_csr(&host);
194}
195
196static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi,
197 void *req_data)
198{
199 struct mei_csr host;
Martin Rothff744bf2019-10-23 21:46:03 -0600200 unsigned int ndata, n;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200201 u32 *data;
202
203 /* Number of dwords to write, ignoring MKHI */
204 ndata = mei->length >> 2;
205
206 /* Pad non-dword aligned request message length */
207 if (mei->length & 3)
208 ndata++;
209 if (!ndata) {
210 printk(BIOS_DEBUG, "ME: request does not include MKHI\n");
211 return -1;
212 }
213 ndata++; /* Add MEI header */
214
215 /*
216 * Make sure there is still room left in the circular buffer.
217 * Reset the buffer pointers if the requested message will not fit.
218 */
219 read_host_csr(&host);
220 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
221 printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
222 mei_reset();
223 read_host_csr(&host);
224 }
225
226 /*
227 * This implementation does not handle splitting large messages
228 * across multiple transactions. Ensure the requested length
229 * will fit in the available circular buffer depth.
230 */
231 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
232 printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
233 ndata + 2, host.buffer_depth);
234 return -1;
235 }
236
237 /* Write MEI header */
238 mei_write_dword_ptr(mei, MEI_H_CB_WW);
239 ndata--;
240
241 /* Write MKHI header */
242 mei_write_dword_ptr(mkhi, MEI_H_CB_WW);
243 ndata--;
244
245 /* Write message data */
246 data = req_data;
247 for (n = 0; n < ndata; ++n)
248 write_cb(*data++);
249
250 /* Generate interrupt to the ME */
251 read_host_csr(&host);
252 host.interrupt_generate = 1;
253 write_host_csr(&host);
254
255 /* Make sure ME is ready after sending request data */
256 return mei_wait_for_me_ready();
257}
258
259static int mei_recv_msg(struct mkhi_header *mkhi,
260 void *rsp_data, int rsp_bytes)
261{
262 struct mei_header mei_rsp;
263 struct mkhi_header mkhi_rsp;
264 struct mei_csr me, host;
Martin Rothff744bf2019-10-23 21:46:03 -0600265 unsigned int ndata, n/*, me_data_len*/;
266 unsigned int expected;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200267 u32 *data;
268
269 /* Total number of dwords to read from circular buffer */
270 expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2;
271 if (rsp_bytes & 3)
272 expected++;
273
274 /*
275 * The interrupt status bit does not appear to indicate that the
276 * message has actually been received. Instead we wait until the
277 * expected number of dwords are present in the circular buffer.
278 */
279 for (n = ME_RETRY; n; --n) {
280 read_me_csr(&me);
281 if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
282 break;
283 udelay(ME_DELAY);
284 }
285 if (!n) {
286 printk(BIOS_ERR, "ME: timeout waiting for data: expected "
287 "%u, available %u\n", expected,
288 me.buffer_write_ptr - me.buffer_read_ptr);
289 return -1;
290 }
291
292 /* Read and verify MEI response header from the ME */
293 mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
294 if (!mei_rsp.is_complete) {
295 printk(BIOS_ERR, "ME: response is not complete\n");
296 return -1;
297 }
298
299 /* Handle non-dword responses and expect at least MKHI header */
300 ndata = mei_rsp.length >> 2;
301 if (mei_rsp.length & 3)
302 ndata++;
303 if (ndata != (expected - 1)) {
304 printk(BIOS_ERR, "ME: response is missing data %d != %d\n",
305 ndata, (expected - 1));
306 return -1;
307 }
308
309 /* Read and verify MKHI response header from the ME */
310 mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW);
311 if (!mkhi_rsp.is_response ||
312 mkhi->group_id != mkhi_rsp.group_id ||
313 mkhi->command != mkhi_rsp.command) {
314 printk(BIOS_ERR, "ME: invalid response, group %u ?= %u,"
315 "command %u ?= %u, is_response %u\n", mkhi->group_id,
316 mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
317 mkhi_rsp.is_response);
318 return -1;
319 }
320 ndata--; /* MKHI header has been read */
321
322 /* Make sure caller passed a buffer with enough space */
323 if (ndata != (rsp_bytes >> 2)) {
324 printk(BIOS_ERR, "ME: not enough room in response buffer: "
325 "%u != %u\n", ndata, rsp_bytes >> 2);
326 return -1;
327 }
328
329 /* Read response data from the circular buffer */
330 data = rsp_data;
331 for (n = 0; n < ndata; ++n)
332 *data++ = read_cb();
333
334 /* Tell the ME that we have consumed the response */
335 read_host_csr(&host);
336 host.interrupt_status = 1;
337 host.interrupt_generate = 1;
338 write_host_csr(&host);
339
340 return mei_wait_for_me_ready();
341}
342
343static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi,
344 void *req_data, void *rsp_data, int rsp_bytes)
345{
346 if (mei_send_msg(mei, mkhi, req_data) < 0)
347 return -1;
348 if (mei_recv_msg(mkhi, rsp_data, rsp_bytes) < 0)
349 return -1;
350 return 0;
351}
352
Stefan Reinauer8e073822012-04-04 00:07:22 +0200353static inline void print_cap(const char *name, int state)
354{
355 printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
356 name, state ? " en" : "dis");
357}
358
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200359static void __unused me_print_fw_version(mbp_fw_version_name *vers_name)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200360{
361 if (!vers_name->major_version) {
362 printk(BIOS_ERR, "ME: mbp missing version report\n");
363 return;
364 }
365
366 printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
367 vers_name->major_version, vers_name->minor_version,
368 vers_name->hotfix_version, vers_name->build_version);
369}
370
371/* Get ME Firmware Capabilities */
372static int mkhi_get_fwcaps(mefwcaps_sku *cap)
373{
374 u32 rule_id = 0;
375 struct me_fwcaps cap_msg;
376 struct mkhi_header mkhi = {
377 .group_id = MKHI_GROUP_ID_FWCAPS,
378 .command = MKHI_FWCAPS_GET_RULE,
379 };
380 struct mei_header mei = {
381 .is_complete = 1,
382 .host_address = MEI_HOST_ADDRESS,
383 .client_address = MEI_ADDRESS_MKHI,
384 .length = sizeof(mkhi) + sizeof(rule_id),
385 };
386
387 /* Send request and wait for response */
Edward O'Callaghan152e5172014-07-13 00:28:05 +1000388 if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap_msg, sizeof(cap_msg)) < 0) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200389 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
390 return -1;
Edward O'Callaghan152e5172014-07-13 00:28:05 +1000391 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200392 *cap = cap_msg.caps_sku;
393 return 0;
394}
395
396/* Get ME Firmware Capabilities */
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200397static void __unused me_print_fwcaps(mbp_fw_caps *caps_section)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200398{
399 mefwcaps_sku *cap = &caps_section->fw_capabilities;
400 if (!caps_section->available) {
401 printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
402 if (mkhi_get_fwcaps(cap))
403 return;
404 }
405
406 print_cap("Full Network manageability", cap->full_net);
407 print_cap("Regular Network manageability", cap->std_net);
408 print_cap("Manageability", cap->manageability);
409 print_cap("Small business technology", cap->small_business);
410 print_cap("Level III manageability", cap->l3manageability);
411 print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
412 print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
413 print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
414 print_cap("ICC Over Clocking", cap->icc_over_clocking);
Edward O'Callaghan152e5172014-07-13 00:28:05 +1000415 print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200416 print_cap("IPV6", cap->ipv6);
417 print_cap("KVM Remote Control (KVM)", cap->kvm);
418 print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
419 print_cap("Virtual LAN (VLAN)", cap->vlan);
420 print_cap("TLS", cap->tls);
421 print_cap("Wireless LAN (WLAN)", cap->wlan);
422}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200423
Julius Wernercd49cce2019-03-05 16:53:33 -0800424#if CONFIG(CHROMEOS) && 0 /* DISABLED */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200425/* Tell ME to issue a global reset */
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700426static int mkhi_global_reset(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200427{
428 struct me_global_reset reset = {
429 .request_origin = GLOBAL_RESET_BIOS_POST,
430 .reset_type = CBM_RR_GLOBAL_RESET,
431 };
432 struct mkhi_header mkhi = {
433 .group_id = MKHI_GROUP_ID_CBM,
434 .command = MKHI_GLOBAL_RESET,
435 };
436 struct mei_header mei = {
437 .is_complete = 1,
438 .length = sizeof(mkhi) + sizeof(reset),
439 .host_address = MEI_HOST_ADDRESS,
440 .client_address = MEI_ADDRESS_MKHI,
441 };
442
443 /* Send request and wait for response */
444 printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__);
445 if (mei_sendrecv(&mei, &mkhi, &reset, NULL, 0) < 0) {
446 /* No response means reset will happen shortly... */
Patrick Georgi546953c2014-11-29 10:38:17 +0100447 halt();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200448 }
449
450 /* If the ME responded it rejected the reset request */
451 printk(BIOS_ERR, "ME: Global Reset failed\n");
452 return -1;
453}
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700454#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200455
456#ifdef __SMM__
457
Duncan Laurie708f7312012-07-10 15:15:41 -0700458/* Send END OF POST message to the ME */
459static int mkhi_end_of_post(void)
460{
461 struct mkhi_header mkhi = {
462 .group_id = MKHI_GROUP_ID_GEN,
463 .command = MKHI_END_OF_POST,
464 };
465 struct mei_header mei = {
466 .is_complete = 1,
467 .host_address = MEI_HOST_ADDRESS,
468 .client_address = MEI_ADDRESS_MKHI,
469 .length = sizeof(mkhi),
470 };
471
472 u32 eop_ack;
473
474 /* Send request and wait for response */
475 printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__);
476 if (mei_sendrecv(&mei, &mkhi, NULL, &eop_ack, sizeof(eop_ack)) < 0) {
477 printk(BIOS_ERR, "ME: END OF POST message failed\n");
478 return -1;
479 }
480
481 printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack);
482 return 0;
483}
484
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700485void intel_me8_finalize_smm(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200486{
487 struct me_hfs hfs;
488 u32 reg32;
489
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800490 mei_base_address = (void *)
491 (pci_read_config32(PCH_ME_DEV, PCI_BASE_ADDRESS_0) & ~0xf);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200492
493 /* S3 path will have hidden this device already */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800494 if (!mei_base_address || mei_base_address == (u32 *)0xfffffff0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200495 return;
496
497 /* Make sure ME is in a mode that expects EOP */
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300498 reg32 = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200499 memcpy(&hfs, &reg32, sizeof(u32));
500
501 /* Abort and leave device alone if not normal mode */
502 if (hfs.fpt_bad ||
503 hfs.working_state != ME_HFS_CWS_NORMAL ||
504 hfs.operation_mode != ME_HFS_MODE_NORMAL)
505 return;
506
507 /* Try to send EOP command so ME stops accepting other commands */
508 mkhi_end_of_post();
509
510 /* Make sure IO is disabled */
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300511 reg32 = pci_read_config32(PCH_ME_DEV, PCI_COMMAND);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200512 reg32 &= ~(PCI_COMMAND_MASTER |
513 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Kyösti Mälkkifd98c652013-07-26 08:50:53 +0300514 pci_write_config32(PCH_ME_DEV, PCI_COMMAND, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200515
516 /* Hide the PCI device */
517 RCBA32_OR(FD2, PCH_DISABLE_MEI1);
518}
519
520#else /* !__SMM__ */
521
522/* Determine the path that we should take based on ME status */
Elyes HAOUASdc035282018-09-18 13:28:49 +0200523static me_bios_path intel_me_path(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200524{
525 me_bios_path path = ME_DISABLE_BIOS_PATH;
526 struct me_hfs hfs;
527 struct me_gmes gmes;
528
Stefan Reinauer8e073822012-04-04 00:07:22 +0200529 /* S3 wake skips all MKHI messages */
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +0300530 if (acpi_is_wakeup_s3())
Stefan Reinauer8e073822012-04-04 00:07:22 +0200531 return ME_S3WAKE_BIOS_PATH;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200532
533 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
534 pci_read_dword_ptr(dev, &gmes, PCI_ME_GMES);
535
536 /* Check and dump status */
537 intel_me_status(&hfs, &gmes);
538
Stefan Reinauer8e073822012-04-04 00:07:22 +0200539 /* Check Current Working State */
540 switch (hfs.working_state) {
541 case ME_HFS_CWS_NORMAL:
542 path = ME_NORMAL_BIOS_PATH;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200543 break;
544 case ME_HFS_CWS_REC:
545 path = ME_RECOVERY_BIOS_PATH;
546 break;
547 default:
548 path = ME_DISABLE_BIOS_PATH;
549 break;
550 }
551
552 /* Check Current Operation Mode */
553 switch (hfs.operation_mode) {
554 case ME_HFS_MODE_NORMAL:
555 break;
556 case ME_HFS_MODE_DEBUG:
557 case ME_HFS_MODE_DIS:
558 case ME_HFS_MODE_OVER_JMPR:
559 case ME_HFS_MODE_OVER_MEI:
560 default:
561 path = ME_DISABLE_BIOS_PATH;
562 break;
563 }
564
Duncan Laurie5c88c6f2012-09-01 14:00:23 -0700565 /* Check for any error code and valid firmware and MBP */
566 if (hfs.error_code || hfs.fpt_bad)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200567 path = ME_ERROR_BIOS_PATH;
568
Duncan Laurie5c88c6f2012-09-01 14:00:23 -0700569 /* Check if the MBP is ready */
570 if (!gmes.mbp_rdy) {
571 printk(BIOS_CRIT, "%s: mbp is not ready!\n",
572 __FUNCTION__);
573 path = ME_ERROR_BIOS_PATH;
574 }
575
Kyösti Mälkkibe5317f2019-11-06 12:07:21 +0200576 if (CONFIG(ELOG) && path != ME_NORMAL_BIOS_PATH) {
Duncan Laurie5c88c6f2012-09-01 14:00:23 -0700577 struct elog_event_data_me_extended data = {
578 .current_working_state = hfs.working_state,
579 .operation_state = hfs.operation_state,
580 .operation_mode = hfs.operation_mode,
581 .error_code = hfs.error_code,
582 .progress_code = gmes.progress_code,
583 .current_pmevent = gmes.current_pmevent,
584 .current_state = gmes.current_state,
585 };
586 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
587 elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
588 &data, sizeof(data));
589 }
Duncan Laurie5c88c6f2012-09-01 14:00:23 -0700590
Stefan Reinauer8e073822012-04-04 00:07:22 +0200591 return path;
592}
593
594/* Prepare ME for MEI messages */
Elyes HAOUASdc035282018-09-18 13:28:49 +0200595static int intel_mei_setup(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200596{
597 struct resource *res;
598 struct mei_csr host;
599 u32 reg32;
600
601 /* Find the MMIO base for the ME interface */
602 res = find_resource(dev, PCI_BASE_ADDRESS_0);
603 if (!res || res->base == 0 || res->size == 0) {
604 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
605 return -1;
606 }
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800607 mei_base_address = (u32 *)(uintptr_t)res->base;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200608
609 /* Ensure Memory and Bus Master bits are set */
610 reg32 = pci_read_config32(dev, PCI_COMMAND);
611 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
612 pci_write_config32(dev, PCI_COMMAND, reg32);
613
614 /* Clean up status for next message */
615 read_host_csr(&host);
616 host.interrupt_generate = 1;
617 host.ready = 1;
618 host.reset = 0;
619 write_host_csr(&host);
620
621 return 0;
622}
623
624/* Read the Extend register hash of ME firmware */
Elyes HAOUASdc035282018-09-18 13:28:49 +0200625static int intel_me_extend_valid(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200626{
627 struct me_heres status;
Stefan Reinauer49058c02012-06-11 14:13:09 -0700628 u32 extend[8] = {0};
Stefan Reinauer8e073822012-04-04 00:07:22 +0200629 int i, count = 0;
630
631 pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
632 if (!status.extend_feature_present) {
633 printk(BIOS_ERR, "ME: Extend Feature not present\n");
634 return -1;
635 }
636
637 if (!status.extend_reg_valid) {
638 printk(BIOS_ERR, "ME: Extend Register not valid\n");
639 return -1;
640 }
641
642 switch (status.extend_reg_algorithm) {
643 case PCI_ME_EXT_SHA1:
644 count = 5;
645 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
646 break;
647 case PCI_ME_EXT_SHA256:
648 count = 8;
649 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
650 break;
651 default:
652 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
653 status.extend_reg_algorithm);
654 return -1;
655 }
656
Stefan Reinauer8e073822012-04-04 00:07:22 +0200657 for (i = 0; i < count; ++i) {
Stefan Reinauer49058c02012-06-11 14:13:09 -0700658 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
659 printk(BIOS_DEBUG, "%08x", extend[i]);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200660 }
661 printk(BIOS_DEBUG, "\n");
662
Julius Wernercd49cce2019-03-05 16:53:33 -0800663#if CONFIG(CHROMEOS)
Stefan Reinauer49058c02012-06-11 14:13:09 -0700664 /* Save hash in NVS for the OS to verify */
665 chromeos_set_me_hash(extend, count);
666#endif
667
Stefan Reinauer8e073822012-04-04 00:07:22 +0200668 return 0;
669}
670
671/* Hide the ME virtual PCI devices */
Elyes HAOUASdc035282018-09-18 13:28:49 +0200672static void intel_me_hide(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200673{
674 dev->enabled = 0;
675 pch_enable(dev);
676}
677
678/* Check whether ME is present and do basic init */
Elyes HAOUASdc035282018-09-18 13:28:49 +0200679static void intel_me_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200680{
681 me_bios_path path = intel_me_path(dev);
682 me_bios_payload mbp_data;
683
684 /* Do initial setup and determine the BIOS path */
685 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
686
687 switch (path) {
688 case ME_S3WAKE_BIOS_PATH:
689 intel_me_hide(dev);
690 break;
691
692 case ME_NORMAL_BIOS_PATH:
693 /* Validate the extend register */
694 if (intel_me_extend_valid(dev) < 0)
695 break; /* TODO: force recovery mode */
696
697 /* Prepare MEI MMIO interface */
698 if (intel_mei_setup(dev) < 0)
699 break;
700
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200701 if (intel_me_read_mbp(&mbp_data))
Stefan Reinauer8e073822012-04-04 00:07:22 +0200702 break;
703
Julius Wernercd49cce2019-03-05 16:53:33 -0800704#if CONFIG(CHROMEOS) && 0 /* DISABLED */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200705 /*
706 * Unlock ME in recovery mode.
707 */
Furquan Shaikh0325dc62016-07-25 13:02:36 -0700708 if (vboot_recovery_mode_enabled()) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200709 /* Unlock ME flash region */
710 mkhi_hmrfpo_enable();
711
712 /* Issue global reset */
713 mkhi_global_reset();
714 return;
715 }
716#endif
717
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200718 if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
719 me_print_fw_version(&mbp_data.fw_version_name);
720 me_print_fwcaps(&mbp_data.fw_caps_sku);
721 }
Duncan Laurie708f7312012-07-10 15:15:41 -0700722
723 /*
724 * Leave the ME unlocked in this path.
725 * It will be locked via SMI command later.
726 */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200727 break;
728
729 case ME_ERROR_BIOS_PATH:
730 case ME_RECOVERY_BIOS_PATH:
731 case ME_DISABLE_BIOS_PATH:
732 case ME_FIRMWARE_UPDATE_BIOS_PATH:
Stefan Reinauer8e073822012-04-04 00:07:22 +0200733 break;
734 }
735}
736
Stefan Reinauer8e073822012-04-04 00:07:22 +0200737static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530738 .set_subsystem = pci_dev_set_subsystem,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200739};
740
741static struct device_operations device_ops = {
742 .read_resources = pci_dev_read_resources,
743 .set_resources = pci_dev_set_resources,
744 .enable_resources = pci_dev_enable_resources,
745 .init = intel_me_init,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200746 .ops_pci = &pci_ops,
747};
748
749static const struct pci_driver intel_me __pci_driver = {
750 .ops = &device_ops,
751 .vendor = PCI_VENDOR_ID_INTEL,
752 .device = 0x1e3a,
753};
754
755/******************************************************************************
756 * */
757static u32 me_to_host_words_pending(void)
758{
759 struct mei_csr me;
760 read_me_csr(&me);
761 if (!me.ready)
762 return 0;
763 return (me.buffer_write_ptr - me.buffer_read_ptr) &
764 (me.buffer_depth - 1);
765}
766
767#if 0
768/* This function is not yet being used, keep it in for the future. */
769static u32 host_to_me_words_room(void)
770{
771 struct mei_csr csr;
772
773 read_me_csr(&csr);
774 if (!csr.ready)
775 return 0;
776
777 read_host_csr(&csr);
778 return (csr.buffer_read_ptr - csr.buffer_write_ptr - 1) &
779 (csr.buffer_depth - 1);
780}
781#endif
782/*
783 * mbp seems to be following its own flow, let's retrieve it in a dedicated
784 * function.
785 */
786static int intel_me_read_mbp(me_bios_payload *mbp_data)
787{
788 mbp_header mbp_hdr;
789 mbp_item_header mbp_item_hdr;
790 u32 me2host_pending;
791 u32 mbp_item_id;
792 struct mei_csr host;
793
794 me2host_pending = me_to_host_words_pending();
795 if (!me2host_pending) {
796 printk(BIOS_ERR, "ME: no mbp data!\n");
797 return -1;
798 }
799
800 /* we know for sure that at least the header is there */
801 mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
802
803 if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
804 (me2host_pending < mbp_hdr.mbp_size)) {
805 printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
806 " buffer contains %d words\n",
807 mbp_hdr.num_entries, mbp_hdr.mbp_size,
808 me2host_pending);
809 return -1;
810 }
811
812 me2host_pending--;
813 memset(mbp_data, 0, sizeof(*mbp_data));
814
815 while (mbp_hdr.num_entries--) {
Elyes HAOUAS448d9fb2018-05-22 12:51:27 +0200816 u32 *copy_addr;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200817 u32 copy_size, buffer_room;
818 void *p;
819
820 if (!me2host_pending) {
821 printk(BIOS_ERR, "ME: no mbp data %d entries to go!\n",
822 mbp_hdr.num_entries + 1);
823 return -1;
824 }
825
826 mei_read_dword_ptr(&mbp_item_hdr, MEI_ME_CB_RW);
827
828 if (mbp_item_hdr.length > me2host_pending) {
829 printk(BIOS_ERR, "ME: insufficient mbp data %d "
830 "entries to go!\n",
831 mbp_hdr.num_entries + 1);
832 return -1;
833 }
834
835 me2host_pending -= mbp_item_hdr.length;
836
837 mbp_item_id = (((u32)mbp_item_hdr.item_id) << 8) +
838 mbp_item_hdr.app_id;
839
840 copy_size = mbp_item_hdr.length - 1;
841
842#define SET_UP_COPY(field) { copy_addr = (u32 *)&mbp_data->field; \
843 buffer_room = sizeof(mbp_data->field) / sizeof(u32); \
844 break; \
845 }
846
847 p = &mbp_item_hdr;
848 printk(BIOS_INFO, "ME: MBP item header %8.8x\n", *((u32*)p));
849
Elyes HAOUASf9de5a42018-05-03 17:21:02 +0200850 switch (mbp_item_id) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200851 case 0x101:
852 SET_UP_COPY(fw_version_name);
853
854 case 0x102:
855 SET_UP_COPY(icc_profile);
856
857 case 0x103:
858 SET_UP_COPY(at_state);
859
860 case 0x201:
861 mbp_data->fw_caps_sku.available = 1;
862 SET_UP_COPY(fw_caps_sku.fw_capabilities);
863
864 case 0x301:
865 SET_UP_COPY(rom_bist_data);
866
867 case 0x401:
868 SET_UP_COPY(platform_key);
869
870 case 0x501:
871 mbp_data->fw_plat_type.available = 1;
872 SET_UP_COPY(fw_plat_type.rule_data);
873
874 case 0x601:
875 SET_UP_COPY(mfsintegrity);
876
877 default:
Vladimir Serbinenkoafc8d982014-06-11 18:52:55 +0000878 printk(BIOS_ERR, "ME: unknown mbp item id 0x%x! Skipping\n",
Stefan Reinauer8e073822012-04-04 00:07:22 +0200879 mbp_item_id);
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200880 while (copy_size--)
Vladimir Serbinenkoafc8d982014-06-11 18:52:55 +0000881 read_cb();
882 continue;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200883 }
884
885 if (buffer_room != copy_size) {
886 printk(BIOS_ERR, "ME: buffer room %d != %d copy size"
887 " for item 0x%x!!!\n",
888 buffer_room, copy_size, mbp_item_id);
889 return -1;
890 }
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200891 while (copy_size--)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200892 *copy_addr++ = read_cb();
893 }
894
895 read_host_csr(&host);
896 host.interrupt_generate = 1;
897 write_host_csr(&host);
898
899 {
900 int cntr = 0;
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200901 while (host.interrupt_generate) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200902 read_host_csr(&host);
903 cntr++;
904 }
905 printk(BIOS_SPEW, "ME: mbp read OK after %d cycles\n", cntr);
906 }
907
908 return 0;
909}
910
911#endif /* !__SMM__ */