blob: eebc451bfe718af83c0e90b63c9dc93ee3b8e22c [file] [log] [blame]
Aaron Durbin76c37002012-10-30 09:03:43 -05001/*
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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22/*
23 * This is a ramstage driver for the Intel Management Engine found in the
24 * 6-series chipset. It handles the required boot-time messages over the
25 * MMIO-based Management Engine Interface to tell the ME that the BIOS is
26 * finished with POST. Additional messages are defined for debug but are
27 * not used unless the console loglevel is high enough.
28 */
29
30#include <arch/acpi.h>
31#include <arch/hlt.h>
32#include <arch/io.h>
33#include <console/console.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070034#include <device/device.h>
35#include <device/pci.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050036#include <device/pci_ids.h>
37#include <device/pci_def.h>
38#include <string.h>
39#include <delay.h>
40#include <elog.h>
41
Aaron Durbin76c37002012-10-30 09:03:43 -050042#include "me.h"
43#include "pch.h"
44
45#if CONFIG_CHROMEOS
46#include <vendorcode/google/chromeos/chromeos.h>
47#include <vendorcode/google/chromeos/gnvs.h>
48#endif
49
Duncan Laurieaf980622013-07-18 23:02:18 -070050#ifndef __SMM__
Aaron Durbin76c37002012-10-30 09:03:43 -050051/* Path that the BIOS should take based on ME state */
52static const char *me_bios_path_values[] = {
53 [ME_NORMAL_BIOS_PATH] = "Normal",
54 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
55 [ME_ERROR_BIOS_PATH] = "Error",
56 [ME_RECOVERY_BIOS_PATH] = "Recovery",
57 [ME_DISABLE_BIOS_PATH] = "Disable",
58 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
59};
Aaron Durbin9aa031e2012-11-02 09:16:46 -050060static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev);
Duncan Laurieaf980622013-07-18 23:02:18 -070061#endif
Aaron Durbin76c37002012-10-30 09:03:43 -050062
63/* MMIO base address for MEI interface */
64static u32 mei_base_address;
Duncan Laurie3d299c42013-07-19 08:48:05 -070065void intel_me_mbp_clear(device_t dev);
Aaron Durbin76c37002012-10-30 09:03:43 -050066
67#if CONFIG_DEBUG_INTEL_ME
68static void mei_dump(void *ptr, int dword, int offset, const char *type)
69{
70 struct mei_csr *csr;
71
72 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
73
74 switch (offset) {
75 case MEI_H_CSR:
76 case MEI_ME_CSR_HA:
77 csr = ptr;
78 if (!csr) {
79 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
80 break;
81 }
82 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
83 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
84 csr->buffer_read_ptr, csr->buffer_write_ptr,
85 csr->ready, csr->reset, csr->interrupt_generate,
86 csr->interrupt_status, csr->interrupt_enable);
87 break;
88 case MEI_ME_CB_RW:
89 case MEI_H_CB_WW:
90 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
91 break;
92 default:
93 printk(BIOS_SPEW, "0x%08x\n", offset);
94 break;
95 }
96}
97#else
98# define mei_dump(ptr,dword,offset,type) do {} while (0)
99#endif
100
101/*
102 * ME/MEI access helpers using memcpy to avoid aliasing.
103 */
104
105static inline void mei_read_dword_ptr(void *ptr, int offset)
106{
107 u32 dword = read32(mei_base_address + offset);
108 memcpy(ptr, &dword, sizeof(dword));
109 mei_dump(ptr, dword, offset, "READ");
110}
111
112static inline void mei_write_dword_ptr(void *ptr, int offset)
113{
114 u32 dword = 0;
115 memcpy(&dword, ptr, sizeof(dword));
116 write32(mei_base_address + offset, dword);
117 mei_dump(ptr, dword, offset, "WRITE");
118}
119
Aaron Durbin76c37002012-10-30 09:03:43 -0500120static inline void pci_read_dword_ptr(device_t dev, void *ptr, int offset)
121{
122 u32 dword = pci_read_config32(dev, offset);
123 memcpy(ptr, &dword, sizeof(dword));
124 mei_dump(ptr, dword, offset, "PCI READ");
125}
Aaron Durbin76c37002012-10-30 09:03:43 -0500126
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{
144 write32(mei_base_address + MEI_H_CB_WW, dword);
145 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
146}
147
148static inline u32 read_cb(void)
149{
150 u32 dword = read32(mei_base_address + MEI_ME_CB_RW);
151 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;
159 unsigned try = ME_RETRY;
160
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;
200 unsigned ndata, n;
201 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;
265 unsigned ndata, n/*, me_data_len*/;
266 unsigned expected;
267 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
Duncan Laurie3d299c42013-07-19 08:48:05 -0700353/*
354 * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
355 * state machine on the BIOS end doesn't match the ME's state machine.
356 */
357static void intel_me_mbp_give_up(device_t dev)
358{
359 struct mei_csr csr;
360
361 pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP);
362
363 read_host_csr(&csr);
364 csr.reset = 1;
365 csr.interrupt_generate = 1;
366 write_host_csr(&csr);
367}
368
369/*
370 * mbp clear routine. This will wait for the ME to indicate that
371 * the MBP has been read and cleared.
372 */
373void intel_me_mbp_clear(device_t dev)
374{
375 int count;
376 struct me_hfs2 hfs2;
377
378 /* Wait for the mbp_cleared indicator */
379 for (count = ME_RETRY; count > 0; --count) {
380 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
381 if (hfs2.mbp_cleared)
382 break;
383 udelay(ME_DELAY);
384 }
385
386 if (count == 0) {
387 printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n");
388 intel_me_mbp_give_up(dev);
389 } else {
390 printk(BIOS_INFO, "ME: MBP cleared\n");
391 }
392}
393
Duncan Laurieaf980622013-07-18 23:02:18 -0700394#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) && !defined(__SMM__)
Aaron Durbin76c37002012-10-30 09:03:43 -0500395static inline void print_cap(const char *name, int state)
396{
397 printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
398 name, state ? " en" : "dis");
399}
400
401static void me_print_fw_version(mbp_fw_version_name *vers_name)
402{
Aaron Durbinbe985242012-12-12 12:40:33 -0600403 if (!vers_name) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500404 printk(BIOS_ERR, "ME: mbp missing version report\n");
405 return;
406 }
407
408 printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
409 vers_name->major_version, vers_name->minor_version,
410 vers_name->hotfix_version, vers_name->build_version);
411}
412
413/* Get ME Firmware Capabilities */
Aaron Durbinbe985242012-12-12 12:40:33 -0600414static int mkhi_get_fwcaps(mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500415{
416 u32 rule_id = 0;
417 struct me_fwcaps cap_msg;
418 struct mkhi_header mkhi = {
419 .group_id = MKHI_GROUP_ID_FWCAPS,
420 .command = MKHI_FWCAPS_GET_RULE,
421 };
422 struct mei_header mei = {
423 .is_complete = 1,
424 .host_address = MEI_HOST_ADDRESS,
425 .client_address = MEI_ADDRESS_MKHI,
426 .length = sizeof(mkhi) + sizeof(rule_id),
427 };
428
429 /* Send request and wait for response */
430 if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap_msg, sizeof(cap_msg))
431 < 0) {
432 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
433 return -1;
434 }
435 *cap = cap_msg.caps_sku;
436 return 0;
437}
438
439/* Get ME Firmware Capabilities */
Aaron Durbinbe985242012-12-12 12:40:33 -0600440static void me_print_fwcaps(mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500441{
Aaron Durbinbe985242012-12-12 12:40:33 -0600442 mbp_mefwcaps local_caps;
443 if (!cap) {
444 cap = &local_caps;
Aaron Durbin76c37002012-10-30 09:03:43 -0500445 printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
446 if (mkhi_get_fwcaps(cap))
447 return;
448 }
449
450 print_cap("Full Network manageability", cap->full_net);
451 print_cap("Regular Network manageability", cap->std_net);
452 print_cap("Manageability", cap->manageability);
Aaron Durbin76c37002012-10-30 09:03:43 -0500453 print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
454 print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
455 print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
456 print_cap("ICC Over Clocking", cap->icc_over_clocking);
457 print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
458 print_cap("IPV6", cap->ipv6);
459 print_cap("KVM Remote Control (KVM)", cap->kvm);
460 print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
461 print_cap("Virtual LAN (VLAN)", cap->vlan);
462 print_cap("TLS", cap->tls);
463 print_cap("Wireless LAN (WLAN)", cap->wlan);
464}
465#endif
466
467#if CONFIG_CHROMEOS && 0 /* DISABLED */
468/* Tell ME to issue a global reset */
469static int mkhi_global_reset(void)
470{
471 struct me_global_reset reset = {
472 .request_origin = GLOBAL_RESET_BIOS_POST,
473 .reset_type = CBM_RR_GLOBAL_RESET,
474 };
475 struct mkhi_header mkhi = {
476 .group_id = MKHI_GROUP_ID_CBM,
477 .command = MKHI_GLOBAL_RESET,
478 };
479 struct mei_header mei = {
480 .is_complete = 1,
481 .length = sizeof(mkhi) + sizeof(reset),
482 .host_address = MEI_HOST_ADDRESS,
483 .client_address = MEI_ADDRESS_MKHI,
484 };
485
486 /* Send request and wait for response */
487 printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__);
488 if (mei_sendrecv(&mei, &mkhi, &reset, NULL, 0) < 0) {
489 /* No response means reset will happen shortly... */
490 hlt();
491 }
492
493 /* If the ME responded it rejected the reset request */
494 printk(BIOS_ERR, "ME: Global Reset failed\n");
495 return -1;
496}
497#endif
498
Duncan Laurieaf980622013-07-18 23:02:18 -0700499#ifdef __SMM__
500
Aaron Durbin76c37002012-10-30 09:03:43 -0500501/* Send END OF POST message to the ME */
502static int mkhi_end_of_post(void)
503{
504 struct mkhi_header mkhi = {
505 .group_id = MKHI_GROUP_ID_GEN,
506 .command = MKHI_END_OF_POST,
507 };
508 struct mei_header mei = {
509 .is_complete = 1,
510 .host_address = MEI_HOST_ADDRESS,
511 .client_address = MEI_ADDRESS_MKHI,
512 .length = sizeof(mkhi),
513 };
514
515 u32 eop_ack;
516
517 /* Send request and wait for response */
518 printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__);
519 if (mei_sendrecv(&mei, &mkhi, NULL, &eop_ack, sizeof(eop_ack)) < 0) {
520 printk(BIOS_ERR, "ME: END OF POST message failed\n");
521 return -1;
522 }
523
524 printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack);
525 return 0;
526}
527
Duncan Laurieaf980622013-07-18 23:02:18 -0700528void intel_me_finalize_smm(void)
529{
530 struct me_hfs hfs;
531 u32 reg32;
532
533 mei_base_address =
534 pci_read_config32(PCH_ME_DEV, PCI_BASE_ADDRESS_0) & ~0xf;
535
536 /* S3 path will have hidden this device already */
537 if (!mei_base_address || mei_base_address == 0xfffffff0)
538 return;
539
Duncan Laurie3d299c42013-07-19 08:48:05 -0700540#if CONFIG_ME_MBP_CLEAR_LATE
541 /* Wait for ME MBP Cleared indicator */
542 intel_me_mbp_clear(PCH_ME_DEV);
543#endif
544
Duncan Laurieaf980622013-07-18 23:02:18 -0700545 /* Make sure ME is in a mode that expects EOP */
546 reg32 = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
547 memcpy(&hfs, &reg32, sizeof(u32));
548
549 /* Abort and leave device alone if not normal mode */
550 if (hfs.fpt_bad ||
551 hfs.working_state != ME_HFS_CWS_NORMAL ||
552 hfs.operation_mode != ME_HFS_MODE_NORMAL)
553 return;
554
555 /* Try to send EOP command so ME stops accepting other commands */
556 mkhi_end_of_post();
557
558 /* Make sure IO is disabled */
559 reg32 = pci_read_config32(PCH_ME_DEV, PCI_COMMAND);
560 reg32 &= ~(PCI_COMMAND_MASTER |
561 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
562 pci_write_config32(PCH_ME_DEV, PCI_COMMAND, reg32);
563
564 /* Hide the PCI device */
565 RCBA32_OR(FD2, PCH_DISABLE_MEI1);
566}
567
568#else /* !__SMM__ */
569
Aaron Durbin76c37002012-10-30 09:03:43 -0500570/* Determine the path that we should take based on ME status */
571static me_bios_path intel_me_path(device_t dev)
572{
573 me_bios_path path = ME_DISABLE_BIOS_PATH;
574 struct me_hfs hfs;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500575 struct me_hfs2 hfs2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500576
Aaron Durbin76c37002012-10-30 09:03:43 -0500577 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500578 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500579
580 /* Check and dump status */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500581 intel_me_status(&hfs, &hfs2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500582
583 /* Check Current Working State */
584 switch (hfs.working_state) {
585 case ME_HFS_CWS_NORMAL:
586 path = ME_NORMAL_BIOS_PATH;
587 break;
588 case ME_HFS_CWS_REC:
589 path = ME_RECOVERY_BIOS_PATH;
590 break;
591 default:
592 path = ME_DISABLE_BIOS_PATH;
593 break;
594 }
595
596 /* Check Current Operation Mode */
597 switch (hfs.operation_mode) {
598 case ME_HFS_MODE_NORMAL:
599 break;
600 case ME_HFS_MODE_DEBUG:
601 case ME_HFS_MODE_DIS:
602 case ME_HFS_MODE_OVER_JMPR:
603 case ME_HFS_MODE_OVER_MEI:
604 default:
605 path = ME_DISABLE_BIOS_PATH;
606 break;
607 }
608
609 /* Check for any error code and valid firmware and MBP */
610 if (hfs.error_code || hfs.fpt_bad)
611 path = ME_ERROR_BIOS_PATH;
612
613 /* Check if the MBP is ready */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500614 if (!hfs2.mbp_rdy) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500615 printk(BIOS_CRIT, "%s: mbp is not ready!\n",
616 __FUNCTION__);
617 path = ME_ERROR_BIOS_PATH;
618 }
619
620#if CONFIG_ELOG
621 if (path != ME_NORMAL_BIOS_PATH) {
622 struct elog_event_data_me_extended data = {
623 .current_working_state = hfs.working_state,
624 .operation_state = hfs.operation_state,
625 .operation_mode = hfs.operation_mode,
626 .error_code = hfs.error_code,
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500627 .progress_code = hfs2.progress_code,
628 .current_pmevent = hfs2.current_pmevent,
629 .current_state = hfs2.current_state,
Aaron Durbin76c37002012-10-30 09:03:43 -0500630 };
631 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
632 elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
633 &data, sizeof(data));
634 }
635#endif
636
637 return path;
638}
639
640/* Prepare ME for MEI messages */
641static int intel_mei_setup(device_t dev)
642{
643 struct resource *res;
644 struct mei_csr host;
645 u32 reg32;
646
647 /* Find the MMIO base for the ME interface */
648 res = find_resource(dev, PCI_BASE_ADDRESS_0);
649 if (!res || res->base == 0 || res->size == 0) {
650 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
651 return -1;
652 }
653 mei_base_address = res->base;
654
655 /* Ensure Memory and Bus Master bits are set */
656 reg32 = pci_read_config32(dev, PCI_COMMAND);
657 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
658 pci_write_config32(dev, PCI_COMMAND, reg32);
659
660 /* Clean up status for next message */
661 read_host_csr(&host);
662 host.interrupt_generate = 1;
663 host.ready = 1;
664 host.reset = 0;
665 write_host_csr(&host);
666
667 return 0;
668}
669
670/* Read the Extend register hash of ME firmware */
671static int intel_me_extend_valid(device_t dev)
672{
673 struct me_heres status;
674 u32 extend[8] = {0};
675 int i, count = 0;
676
677 pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
678 if (!status.extend_feature_present) {
679 printk(BIOS_ERR, "ME: Extend Feature not present\n");
680 return -1;
681 }
682
683 if (!status.extend_reg_valid) {
684 printk(BIOS_ERR, "ME: Extend Register not valid\n");
685 return -1;
686 }
687
688 switch (status.extend_reg_algorithm) {
689 case PCI_ME_EXT_SHA1:
690 count = 5;
691 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
692 break;
693 case PCI_ME_EXT_SHA256:
694 count = 8;
695 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
696 break;
697 default:
698 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
699 status.extend_reg_algorithm);
700 return -1;
701 }
702
703 for (i = 0; i < count; ++i) {
704 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
705 printk(BIOS_DEBUG, "%08x", extend[i]);
706 }
707 printk(BIOS_DEBUG, "\n");
708
709#if CONFIG_CHROMEOS
710 /* Save hash in NVS for the OS to verify */
711 chromeos_set_me_hash(extend, count);
712#endif
713
714 return 0;
715}
716
Aaron Durbin76c37002012-10-30 09:03:43 -0500717/* Check whether ME is present and do basic init */
718static void intel_me_init(device_t dev)
719{
720 me_bios_path path = intel_me_path(dev);
721 me_bios_payload mbp_data;
722
723 /* Do initial setup and determine the BIOS path */
724 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
725
Duncan Laurie8056dc62013-07-22 08:47:43 -0700726 if (path == ME_NORMAL_BIOS_PATH) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500727 /* Validate the extend register */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500728 /* FIXME: force recovery mode on failure. */
729 intel_me_extend_valid(dev);
730 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500731
Aaron Durbinbe985242012-12-12 12:40:33 -0600732 memset(&mbp_data, 0, sizeof(mbp_data));
733
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500734 /*
735 * According to the ME9 BWG, BIOS is required to fetch MBP data in
736 * all boot flows except S3 Resume.
737 */
Aaron Durbin76c37002012-10-30 09:03:43 -0500738
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500739 /* Prepare MEI MMIO interface */
740 if (intel_mei_setup(dev) < 0)
741 return;
Aaron Durbin76c37002012-10-30 09:03:43 -0500742
Duncan Laurie144f7b22013-05-01 11:27:58 -0700743 if (intel_me_read_mbp(&mbp_data, dev))
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500744 return;
Aaron Durbin76c37002012-10-30 09:03:43 -0500745
746#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
Aaron Durbinbe985242012-12-12 12:40:33 -0600747 me_print_fw_version(mbp_data.fw_version_name);
748 me_print_fwcaps(mbp_data.fw_capabilities);
Duncan Laurie144f7b22013-05-01 11:27:58 -0700749
750 if (mbp_data.plat_time) {
751 printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n",
752 mbp_data.plat_time->wake_event_mrst_time_ms);
753 printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n",
754 mbp_data.plat_time->mrst_pltrst_time_ms);
755 printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n",
756 mbp_data.plat_time->pltrst_cpurst_time_ms);
757 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500758#endif
759
Duncan Laurieaf980622013-07-18 23:02:18 -0700760 /*
761 * Leave the ME unlocked. It will be locked via SMI command later.
762 */
Aaron Durbin76c37002012-10-30 09:03:43 -0500763}
764
765static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
766{
767 if (!vendor || !device) {
768 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
769 pci_read_config32(dev, PCI_VENDOR_ID));
770 } else {
771 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
772 ((device & 0xffff) << 16) | (vendor & 0xffff));
773 }
774}
775
776static struct pci_operations pci_ops = {
777 .set_subsystem = set_subsystem,
778};
779
Duncan Laurie8056dc62013-07-22 08:47:43 -0700780static void intel_me_enable(device_t dev)
781{
782#if CONFIG_HAVE_ACPI_RESUME
783 /* Avoid talking to the device in S3 path */
784 if (acpi_slp_type == 3) {
785 dev->enabled = 0;
786 pch_disable_devfn(dev);
787 }
788#endif
789}
790
Aaron Durbin76c37002012-10-30 09:03:43 -0500791static struct device_operations device_ops = {
792 .read_resources = pci_dev_read_resources,
793 .set_resources = pci_dev_set_resources,
794 .enable_resources = pci_dev_enable_resources,
Duncan Laurie8056dc62013-07-22 08:47:43 -0700795 .enable = intel_me_enable,
Aaron Durbin76c37002012-10-30 09:03:43 -0500796 .init = intel_me_init,
Aaron Durbin76c37002012-10-30 09:03:43 -0500797 .ops_pci = &pci_ops,
798};
799
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800800static const unsigned short pci_device_ids[] = {
801 0x8c3a, /* Mobile */
802 0x9c3a, /* Low Power */
803 0
804};
805
Aaron Durbin76c37002012-10-30 09:03:43 -0500806static const struct pci_driver intel_me __pci_driver = {
807 .ops = &device_ops,
808 .vendor = PCI_VENDOR_ID_INTEL,
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800809 .devices= pci_device_ids,
Aaron Durbin76c37002012-10-30 09:03:43 -0500810};
811
812/******************************************************************************
813 * */
814static u32 me_to_host_words_pending(void)
815{
816 struct mei_csr me;
817 read_me_csr(&me);
818 if (!me.ready)
819 return 0;
820 return (me.buffer_write_ptr - me.buffer_read_ptr) &
821 (me.buffer_depth - 1);
822}
823
824#if 0
825/* This function is not yet being used, keep it in for the future. */
826static u32 host_to_me_words_room(void)
827{
828 struct mei_csr csr;
829
830 read_me_csr(&csr);
831 if (!csr.ready)
832 return 0;
833
834 read_host_csr(&csr);
835 return (csr.buffer_read_ptr - csr.buffer_write_ptr - 1) &
836 (csr.buffer_depth - 1);
837}
838#endif
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500839
Aaron Durbinbe985242012-12-12 12:40:33 -0600840struct mbp_payload {
841 mbp_header header;
842 u32 data[0];
843};
844
Aaron Durbin76c37002012-10-30 09:03:43 -0500845/*
846 * mbp seems to be following its own flow, let's retrieve it in a dedicated
847 * function.
848 */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500849static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500850{
851 mbp_header mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500852 u32 me2host_pending;
Aaron Durbin76c37002012-10-30 09:03:43 -0500853 struct mei_csr host;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500854 struct me_hfs2 hfs2;
Aaron Durbinbe985242012-12-12 12:40:33 -0600855 struct mbp_payload *mbp;
856 int i;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500857
858 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
859
860 if (!hfs2.mbp_rdy) {
861 printk(BIOS_ERR, "ME: MBP not ready\n");
862 goto mbp_failure;
863 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500864
865 me2host_pending = me_to_host_words_pending();
866 if (!me2host_pending) {
867 printk(BIOS_ERR, "ME: no mbp data!\n");
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500868 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500869 }
870
871 /* we know for sure that at least the header is there */
872 mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
873
874 if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
875 (me2host_pending < mbp_hdr.mbp_size)) {
876 printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
877 " buffer contains %d words\n",
878 mbp_hdr.num_entries, mbp_hdr.mbp_size,
879 me2host_pending);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500880 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500881 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600882 mbp = malloc(mbp_hdr.mbp_size * sizeof(u32));
883 if (!mbp)
884 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500885
Aaron Durbinbe985242012-12-12 12:40:33 -0600886 mbp->header = mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500887 me2host_pending--;
Aaron Durbin76c37002012-10-30 09:03:43 -0500888
Aaron Durbinbe985242012-12-12 12:40:33 -0600889 i = 0;
890 while (i != me2host_pending) {
891 mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW);
892 i++;
Aaron Durbin76c37002012-10-30 09:03:43 -0500893 }
894
Aaron Durbinbe985242012-12-12 12:40:33 -0600895 /* Signal to the ME that the host has finished reading the MBP. */
Aaron Durbin76c37002012-10-30 09:03:43 -0500896 read_host_csr(&host);
897 host.interrupt_generate = 1;
898 write_host_csr(&host);
899
Duncan Laurie3d299c42013-07-19 08:48:05 -0700900#if !CONFIG_ME_MBP_CLEAR_LATE
Aaron Durbinbe985242012-12-12 12:40:33 -0600901 /* Wait for the mbp_cleared indicator. */
Duncan Laurie3d299c42013-07-19 08:48:05 -0700902 intel_me_mbp_clear(dev);
903#endif
Aaron Durbin76c37002012-10-30 09:03:43 -0500904
Aaron Durbinbe985242012-12-12 12:40:33 -0600905 /* Dump out the MBP contents. */
906#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
907 printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n",
908 mbp->header.num_entries, mbp->header.mbp_size);
909 for (i = 0; i < mbp->header.mbp_size - 1; i++) {
910 printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]);
911 }
912#endif
913
914 #define ASSIGN_FIELD_PTR(field_,val_) \
915 { \
916 mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \
917 break; \
918 }
919 /* Setup the pointers in the me_bios_payload structure. */
920 for (i = 0; i < mbp->header.mbp_size - 1;) {
921 mbp_item_header *item = (void *)&mbp->data[i];
922
923 switch(MBP_MAKE_IDENT(item->app_id, item->item_id)) {
924 case MBP_IDENT(KERNEL, FW_VER):
925 ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]);
926
927 case MBP_IDENT(ICC, PROFILE):
928 ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]);
929
930 case MBP_IDENT(INTEL_AT, STATE):
931 ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]);
932
933 case MBP_IDENT(KERNEL, FW_CAP):
934 ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]);
935
936 case MBP_IDENT(KERNEL, ROM_BIST):
937 ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]);
938
939 case MBP_IDENT(KERNEL, PLAT_KEY):
940 ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]);
941
942 case MBP_IDENT(KERNEL, FW_TYPE):
943 ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]);
944
945 case MBP_IDENT(KERNEL, MFS_FAILURE):
946 ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]);
947
Duncan Laurie144f7b22013-05-01 11:27:58 -0700948 case MBP_IDENT(KERNEL, PLAT_TIME):
949 ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]);
950
951 case MBP_IDENT(NFC, SUPPORT_DATA):
952 ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]);
953
Aaron Durbinbe985242012-12-12 12:40:33 -0600954 default:
955 printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ dw offset 0x%x\n",
956 mbp->data[i], i);
957 break;
958 }
959 i += item->length;
960 }
961 #undef ASSIGN_FIELD_PTR
962
Aaron Durbin76c37002012-10-30 09:03:43 -0500963 return 0;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500964
965mbp_failure:
966 intel_me_mbp_give_up(dev);
967 return -1;
Aaron Durbin76c37002012-10-30 09:03:43 -0500968}
Duncan Laurieaf980622013-07-18 23:02:18 -0700969
970#endif /* !__SMM__ */