blob: 3b7f3428bc12e2c9365ba15e4c562ce065f455f2 [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.
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>
34#include <device/pci_ids.h>
35#include <device/pci_def.h>
36#include <string.h>
37#include <delay.h>
Duncan Lauriec1c94352012-07-13 10:11:54 -070038#include <elog.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020039
40#ifdef __SMM__
41# include <arch/romcc_io.h>
42# include <northbridge/intel/sandybridge/pcie_config.c>
43#else
44# include <device/device.h>
45# include <device/pci.h>
46#endif
47
48#include "me.h"
49#include "pch.h"
50
51#if CONFIG_CHROMEOS
52#include <vendorcode/google/chromeos/gnvs.h>
53#endif
54
55#ifndef __SMM__
56/* Path that the BIOS should take based on ME state */
57static const char *me_bios_path_values[] = {
58 [ME_NORMAL_BIOS_PATH] = "Normal",
59 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
60 [ME_ERROR_BIOS_PATH] = "Error",
61 [ME_RECOVERY_BIOS_PATH] = "Recovery",
62 [ME_DISABLE_BIOS_PATH] = "Disable",
63 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
64};
65#endif
66
67/* MMIO base address for MEI interface */
68static u32 mei_base_address;
69
70#if CONFIG_DEBUG_INTEL_ME
71static void mei_dump(void *ptr, int dword, int offset, const char *type)
72{
73 struct mei_csr *csr;
74
75 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
76
77 switch (offset) {
78 case MEI_H_CSR:
79 case MEI_ME_CSR_HA:
80 csr = ptr;
81 if (!csr) {
82 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
83 break;
84 }
85 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
86 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
87 csr->buffer_read_ptr, csr->buffer_write_ptr,
88 csr->ready, csr->reset, csr->interrupt_generate,
89 csr->interrupt_status, csr->interrupt_enable);
90 break;
91 case MEI_ME_CB_RW:
92 case MEI_H_CB_WW:
93 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
94 break;
95 default:
96 printk(BIOS_SPEW, "0x%08x\n", offset);
97 break;
98 }
99}
100#else
101# define mei_dump(ptr,dword,offset,type) do {} while (0)
102#endif
103
104/*
105 * ME/MEI access helpers using memcpy to avoid aliasing.
106 */
107
108static inline void mei_read_dword_ptr(void *ptr, int offset)
109{
110 u32 dword = read32(mei_base_address + offset);
111 memcpy(ptr, &dword, sizeof(dword));
112 mei_dump(ptr, dword, offset, "READ");
113}
114
115static inline void mei_write_dword_ptr(void *ptr, int offset)
116{
117 u32 dword = 0;
118 memcpy(&dword, ptr, sizeof(dword));
119 write32(mei_base_address + offset, dword);
120 mei_dump(ptr, dword, offset, "WRITE");
121}
122
123#ifndef __SMM__
124static inline void pci_read_dword_ptr(device_t dev, void *ptr, int offset)
125{
126 u32 dword = pci_read_config32(dev, offset);
127 memcpy(ptr, &dword, sizeof(dword));
128 mei_dump(ptr, dword, offset, "PCI READ");
129}
130#endif
131
132static inline void read_host_csr(struct mei_csr *csr)
133{
134 mei_read_dword_ptr(csr, MEI_H_CSR);
135}
136
137static inline void write_host_csr(struct mei_csr *csr)
138{
139 mei_write_dword_ptr(csr, MEI_H_CSR);
140}
141
142static inline void read_me_csr(struct mei_csr *csr)
143{
144 mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
145}
146
147static inline void write_cb(u32 dword)
148{
149 write32(mei_base_address + MEI_H_CB_WW, dword);
150 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
151}
152
153static inline u32 read_cb(void)
154{
155 u32 dword = read32(mei_base_address + MEI_ME_CB_RW);
156 mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
157 return dword;
158}
159
160/* Wait for ME ready bit to be asserted */
161static int mei_wait_for_me_ready(void)
162{
163 struct mei_csr me;
164 unsigned try = ME_RETRY;
165
166 while (try--) {
167 read_me_csr(&me);
168 if (me.ready)
169 return 0;
170 udelay(ME_DELAY);
171 }
172
173 printk(BIOS_ERR, "ME: failed to become ready\n");
174 return -1;
175}
176
177static void mei_reset(void)
178{
179 struct mei_csr host;
180
181 if (mei_wait_for_me_ready() < 0)
182 return;
183
184 /* Reset host and ME circular buffers for next message */
185 read_host_csr(&host);
186 host.reset = 1;
187 host.interrupt_generate = 1;
188 write_host_csr(&host);
189
190 if (mei_wait_for_me_ready() < 0)
191 return;
192
193 /* Re-init and indicate host is ready */
194 read_host_csr(&host);
195 host.interrupt_generate = 1;
196 host.ready = 1;
197 host.reset = 0;
198 write_host_csr(&host);
199}
200
201static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi,
202 void *req_data)
203{
204 struct mei_csr host;
205 unsigned ndata, n;
206 u32 *data;
207
208 /* Number of dwords to write, ignoring MKHI */
209 ndata = mei->length >> 2;
210
211 /* Pad non-dword aligned request message length */
212 if (mei->length & 3)
213 ndata++;
214 if (!ndata) {
215 printk(BIOS_DEBUG, "ME: request does not include MKHI\n");
216 return -1;
217 }
218 ndata++; /* Add MEI header */
219
220 /*
221 * Make sure there is still room left in the circular buffer.
222 * Reset the buffer pointers if the requested message will not fit.
223 */
224 read_host_csr(&host);
225 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
226 printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
227 mei_reset();
228 read_host_csr(&host);
229 }
230
231 /*
232 * This implementation does not handle splitting large messages
233 * across multiple transactions. Ensure the requested length
234 * will fit in the available circular buffer depth.
235 */
236 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
237 printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
238 ndata + 2, host.buffer_depth);
239 return -1;
240 }
241
242 /* Write MEI header */
243 mei_write_dword_ptr(mei, MEI_H_CB_WW);
244 ndata--;
245
246 /* Write MKHI header */
247 mei_write_dword_ptr(mkhi, MEI_H_CB_WW);
248 ndata--;
249
250 /* Write message data */
251 data = req_data;
252 for (n = 0; n < ndata; ++n)
253 write_cb(*data++);
254
255 /* Generate interrupt to the ME */
256 read_host_csr(&host);
257 host.interrupt_generate = 1;
258 write_host_csr(&host);
259
260 /* Make sure ME is ready after sending request data */
261 return mei_wait_for_me_ready();
262}
263
264static int mei_recv_msg(struct mei_header *mei, struct mkhi_header *mkhi,
265 void *rsp_data, int rsp_bytes)
266{
267 struct mei_header mei_rsp;
268 struct mkhi_header mkhi_rsp;
269 struct mei_csr me, host;
270 unsigned ndata, n;
271 unsigned expected;
272 u32 *data;
273
274 /* Total number of dwords to read from circular buffer */
275 expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2;
276 if (rsp_bytes & 3)
277 expected++;
278
279 /*
280 * The interrupt status bit does not appear to indicate that the
281 * message has actually been received. Instead we wait until the
282 * expected number of dwords are present in the circular buffer.
283 */
284 for (n = ME_RETRY; n; --n) {
285 read_me_csr(&me);
286 if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
287 break;
288 udelay(ME_DELAY);
289 }
290 if (!n) {
291 printk(BIOS_ERR, "ME: timeout waiting for data: expected "
292 "%u, available %u\n", expected,
293 me.buffer_write_ptr - me.buffer_read_ptr);
294 return -1;
295 }
296
297 /* Read and verify MEI response header from the ME */
298 mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
299 if (!mei_rsp.is_complete) {
300 printk(BIOS_ERR, "ME: response is not complete\n");
301 return -1;
302 }
303
304 /* Handle non-dword responses and expect at least MKHI header */
305 ndata = mei_rsp.length >> 2;
306 if (mei_rsp.length & 3)
307 ndata++;
308 if (ndata != (expected - 1)) {
309 printk(BIOS_ERR, "ME: response is missing data\n");
310 return -1;
311 }
312
313 /* Read and verify MKHI response header from the ME */
314 mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW);
315 if (!mkhi_rsp.is_response ||
316 mkhi->group_id != mkhi_rsp.group_id ||
317 mkhi->command != mkhi_rsp.command) {
318 printk(BIOS_ERR, "ME: invalid response, group %u ?= %u, "
319 "command %u ?= %u, is_response %u\n", mkhi->group_id,
320 mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
321 mkhi_rsp.is_response);
322 return -1;
323 }
324 ndata--; /* MKHI header has been read */
325
326 /* Make sure caller passed a buffer with enough space */
327 if (ndata != (rsp_bytes >> 2)) {
328 printk(BIOS_ERR, "ME: not enough room in response buffer: "
329 "%u != %u\n", ndata, rsp_bytes >> 2);
330 return -1;
331 }
332
333 /* Read response data from the circular buffer */
334 data = rsp_data;
335 for (n = 0; n < ndata; ++n)
336 *data++ = read_cb();
337
338 /* Tell the ME that we have consumed the response */
339 read_host_csr(&host);
340 host.interrupt_status = 1;
341 host.interrupt_generate = 1;
342 write_host_csr(&host);
343
344 return mei_wait_for_me_ready();
345}
346
347static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi,
348 void *req_data, void *rsp_data, int rsp_bytes)
349{
350 if (mei_send_msg(mei, mkhi, req_data) < 0)
351 return -1;
352 if (mei_recv_msg(mei, mkhi, rsp_data, rsp_bytes) < 0)
353 return -1;
354 return 0;
355}
356
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700357#ifdef __SMM__
Stefan Reinauer8e073822012-04-04 00:07:22 +0200358/* Send END OF POST message to the ME */
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700359static int mkhi_end_of_post(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200360{
361 struct mkhi_header mkhi = {
362 .group_id = MKHI_GROUP_ID_GEN,
363 .command = MKHI_END_OF_POST,
364 };
365 struct mei_header mei = {
366 .is_complete = 1,
367 .host_address = MEI_HOST_ADDRESS,
368 .client_address = MEI_ADDRESS_MKHI,
369 .length = sizeof(mkhi),
370 };
371
372 /* Send request and wait for response */
373 if (mei_sendrecv(&mei, &mkhi, NULL, NULL, 0) < 0) {
374 printk(BIOS_ERR, "ME: END OF POST message failed\n");
375 return -1;
376 }
377
378 printk(BIOS_INFO, "ME: END OF POST message successful\n");
379 return 0;
380}
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700381#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200382
383#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) && !defined(__SMM__)
384/* Get ME firmware version */
385static int mkhi_get_fw_version(void)
386{
387 struct me_fw_version version;
388 struct mkhi_header mkhi = {
389 .group_id = MKHI_GROUP_ID_GEN,
390 .command = MKHI_GET_FW_VERSION,
391 };
392 struct mei_header mei = {
393 .is_complete = 1,
394 .host_address = MEI_HOST_ADDRESS,
395 .client_address = MEI_ADDRESS_MKHI,
396 .length = sizeof(mkhi),
397 };
398
399 /* Send request and wait for response */
400 if (mei_sendrecv(&mei, &mkhi, NULL, &version, sizeof(version)) < 0) {
401 printk(BIOS_ERR, "ME: GET FW VERSION message failed\n");
402 return -1;
403 }
404
405 printk(BIOS_INFO, "ME: Firmware Version %u.%u.%u.%u (code) "
406 "%u.%u.%u.%u (recovery)\n",
407 version.code_major, version.code_minor,
408 version.code_build_number, version.code_hot_fix,
409 version.recovery_major, version.recovery_minor,
410 version.recovery_build_number, version.recovery_hot_fix);
411
412 return 0;
413}
414
415static inline void print_cap(const char *name, int state)
416{
417 printk(BIOS_DEBUG, "ME Capability: %-30s : %sabled\n",
418 name, state ? "en" : "dis");
419}
420
421/* Get ME Firmware Capabilities */
422static int mkhi_get_fwcaps(void)
423{
424 u32 rule_id = 0;
425 struct me_fwcaps cap;
426 struct mkhi_header mkhi = {
427 .group_id = MKHI_GROUP_ID_FWCAPS,
428 .command = MKHI_FWCAPS_GET_RULE,
429 };
430 struct mei_header mei = {
431 .is_complete = 1,
432 .host_address = MEI_HOST_ADDRESS,
433 .client_address = MEI_ADDRESS_MKHI,
434 .length = sizeof(mkhi) + sizeof(rule_id),
435 };
436
437 /* Send request and wait for response */
438 if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap, sizeof(cap)) < 0) {
439 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
440 return -1;
441 }
442
443 print_cap("Full Network manageability", cap.caps_sku.full_net);
444 print_cap("Regular Network manageability", cap.caps_sku.std_net);
445 print_cap("Manageability", cap.caps_sku.manageability);
446 print_cap("Small business technology", cap.caps_sku.small_business);
447 print_cap("Level III manageability", cap.caps_sku.l3manageability);
448 print_cap("IntelR Anti-Theft (AT)", cap.caps_sku.intel_at);
449 print_cap("IntelR Capability Licensing Service (CLS)",
450 cap.caps_sku.intel_cls);
451 print_cap("IntelR Power Sharing Technology (MPC)",
452 cap.caps_sku.intel_mpc);
453 print_cap("ICC Over Clocking", cap.caps_sku.icc_over_clocking);
454 print_cap("Protected Audio Video Path (PAVP)", cap.caps_sku.pavp);
455 print_cap("IPV6", cap.caps_sku.ipv6);
456 print_cap("KVM Remote Control (KVM)", cap.caps_sku.kvm);
457 print_cap("Outbreak Containment Heuristic (OCH)", cap.caps_sku.och);
458 print_cap("Virtual LAN (VLAN)", cap.caps_sku.vlan);
459 print_cap("TLS", cap.caps_sku.tls);
460 print_cap("Wireless LAN (WLAN)", cap.caps_sku.wlan);
461
462 return 0;
463}
464#endif
465
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700466#if CONFIG_CHROMEOS && 0 /* DISABLED */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200467/* Tell ME to issue a global reset */
468int mkhi_global_reset(void)
469{
470 struct me_global_reset reset = {
471 .request_origin = GLOBAL_RESET_BIOS_POST,
472 .reset_type = CBM_RR_GLOBAL_RESET,
473 };
474 struct mkhi_header mkhi = {
475 .group_id = MKHI_GROUP_ID_CBM,
476 .command = MKHI_GLOBAL_RESET,
477 };
478 struct mei_header mei = {
479 .is_complete = 1,
480 .length = sizeof(mkhi) + sizeof(reset),
481 .host_address = MEI_HOST_ADDRESS,
482 .client_address = MEI_ADDRESS_MKHI,
483 };
484
485 printk(BIOS_NOTICE, "ME: Requesting global reset\n");
486
487 /* Send request and wait for response */
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}
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700497#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200498
499#ifdef __SMM__
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700500static void intel_me7_finalize_smm(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200501{
502 struct me_hfs hfs;
503 u32 reg32;
504
505 mei_base_address =
506 pcie_read_config32(PCH_ME_DEV, PCI_BASE_ADDRESS_0) & ~0xf;
507
508 /* S3 path will have hidden this device already */
509 if (!mei_base_address || mei_base_address == 0xfffffff0)
510 return;
511
512 /* Make sure ME is in a mode that expects EOP */
513 reg32 = pcie_read_config32(PCH_ME_DEV, PCI_ME_HFS);
514 memcpy(&hfs, &reg32, sizeof(u32));
515
516 /* Abort and leave device alone if not normal mode */
517 if (hfs.fpt_bad ||
518 hfs.working_state != ME_HFS_CWS_NORMAL ||
519 hfs.operation_mode != ME_HFS_MODE_NORMAL)
520 return;
521
522 /* Try to send EOP command so ME stops accepting other commands */
523 mkhi_end_of_post();
524
525 /* Make sure IO is disabled */
526 reg32 = pcie_read_config32(PCH_ME_DEV, PCI_COMMAND);
527 reg32 &= ~(PCI_COMMAND_MASTER |
528 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
529 pcie_write_config32(PCH_ME_DEV, PCI_COMMAND, reg32);
530
531 /* Hide the PCI device */
532 RCBA32_OR(FD2, PCH_DISABLE_MEI1);
533}
534
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700535void intel_me_finalize_smm(void)
536{
Stefan Reinauer9842ad82012-06-13 16:31:50 -0700537 u32 did = pcie_read_config32(PCH_ME_DEV, PCI_VENDOR_ID);
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700538 switch (did) {
Duncan Laurie708f7312012-07-10 15:15:41 -0700539 case 0x1c3a8086:
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700540 intel_me7_finalize_smm();
541 break;
Duncan Laurie708f7312012-07-10 15:15:41 -0700542 case 0x1e3a8086:
Stefan Reinauer998f3a22012-06-11 15:15:46 -0700543 intel_me8_finalize_smm();
544 break;
545 default:
546 printk(BIOS_ERR, "No finalize handler for ME %08x.\n", did);
547 }
548}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200549#else /* !__SMM__ */
550
551/* Determine the path that we should take based on ME status */
552static me_bios_path intel_me_path(device_t dev)
553{
554 me_bios_path path = ME_DISABLE_BIOS_PATH;
555 struct me_hfs hfs;
556 struct me_gmes gmes;
557
558#if CONFIG_HAVE_ACPI_RESUME
559 /* S3 wake skips all MKHI messages */
560 if (acpi_slp_type == 3) {
561 return ME_S3WAKE_BIOS_PATH;
562 }
563#endif
564
565 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
566 pci_read_dword_ptr(dev, &gmes, PCI_ME_GMES);
567
568 /* Check and dump status */
569 intel_me_status(&hfs, &gmes);
570
571 /* Check for valid firmware */
572 if (hfs.fpt_bad)
573 return ME_ERROR_BIOS_PATH;
574
575 /* Check Current Working State */
576 switch (hfs.working_state) {
577 case ME_HFS_CWS_NORMAL:
578 path = ME_NORMAL_BIOS_PATH;
579 break;
580 case ME_HFS_CWS_REC:
581 path = ME_RECOVERY_BIOS_PATH;
582 break;
583 default:
584 path = ME_DISABLE_BIOS_PATH;
585 break;
586 }
587
588 /* Check Current Operation Mode */
589 switch (hfs.operation_mode) {
590 case ME_HFS_MODE_NORMAL:
591 break;
592 case ME_HFS_MODE_DEBUG:
593 case ME_HFS_MODE_DIS:
594 case ME_HFS_MODE_OVER_JMPR:
595 case ME_HFS_MODE_OVER_MEI:
596 default:
597 path = ME_DISABLE_BIOS_PATH;
598 break;
599 }
600
601 /* Check for any error code */
602 if (hfs.error_code)
603 path = ME_ERROR_BIOS_PATH;
604
605 return path;
606}
607
608/* Prepare ME for MEI messages */
609static int intel_mei_setup(device_t dev)
610{
611 struct resource *res;
612 struct mei_csr host;
613 u32 reg32;
614
615 /* Find the MMIO base for the ME interface */
616 res = find_resource(dev, PCI_BASE_ADDRESS_0);
617 if (!res || res->base == 0 || res->size == 0) {
618 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
619 return -1;
620 }
621 mei_base_address = res->base;
622
623 /* Ensure Memory and Bus Master bits are set */
624 reg32 = pci_read_config32(dev, PCI_COMMAND);
625 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
626 pci_write_config32(dev, PCI_COMMAND, reg32);
627
628 /* Clean up status for next message */
629 read_host_csr(&host);
630 host.interrupt_generate = 1;
631 host.ready = 1;
632 host.reset = 0;
633 write_host_csr(&host);
634
635 return 0;
636}
637
638/* Read the Extend register hash of ME firmware */
639static int intel_me_extend_valid(device_t dev)
640{
641 struct me_heres status;
Stefan Reinauer49058c02012-06-11 14:13:09 -0700642 u32 extend[8] = {0};
Stefan Reinauer8e073822012-04-04 00:07:22 +0200643 int i, count = 0;
644
645 pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
646 if (!status.extend_feature_present) {
647 printk(BIOS_ERR, "ME: Extend Feature not present\n");
648 return -1;
649 }
650
651 if (!status.extend_reg_valid) {
652 printk(BIOS_ERR, "ME: Extend Register not valid\n");
653 return -1;
654 }
655
656 switch (status.extend_reg_algorithm) {
657 case PCI_ME_EXT_SHA1:
658 count = 5;
659 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
660 break;
661 case PCI_ME_EXT_SHA256:
662 count = 8;
663 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
664 break;
665 default:
666 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
667 status.extend_reg_algorithm);
668 return -1;
669 }
670
671 for (i = 0; i < count; ++i) {
672 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
673 printk(BIOS_DEBUG, "%08x", extend[i]);
674 }
675 printk(BIOS_DEBUG, "\n");
676
677#if CONFIG_CHROMEOS
678 /* Save hash in NVS for the OS to verify */
679 chromeos_set_me_hash(extend, count);
680#endif
681
682 return 0;
683}
684
685/* Hide the ME virtual PCI devices */
686static void intel_me_hide(device_t dev)
687{
688 dev->enabled = 0;
689 pch_enable(dev);
690}
691
692/* Check whether ME is present and do basic init */
693static void intel_me_init(device_t dev)
694{
695 me_bios_path path = intel_me_path(dev);
696
697 /* Do initial setup and determine the BIOS path */
698 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
699
700 switch (path) {
701 case ME_S3WAKE_BIOS_PATH:
702 intel_me_hide(dev);
703 break;
704
705 case ME_NORMAL_BIOS_PATH:
706 /* Validate the extend register */
707 if (intel_me_extend_valid(dev) < 0)
708 break; /* TODO: force recovery mode */
709
710 /* Prepare MEI MMIO interface */
711 if (intel_mei_setup(dev) < 0)
712 break;
713
714#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
715 /* Print ME firmware version */
716 mkhi_get_fw_version();
717 /* Print ME firmware capabilities */
718 mkhi_get_fwcaps();
719#endif
720
721 /*
722 * Leave the ME unlocked in this path.
723 * It will be locked via SMI command later.
724 */
725 break;
726
727 case ME_ERROR_BIOS_PATH:
728 case ME_RECOVERY_BIOS_PATH:
729 case ME_DISABLE_BIOS_PATH:
730 case ME_FIRMWARE_UPDATE_BIOS_PATH:
Duncan Lauriec1c94352012-07-13 10:11:54 -0700731#if CONFIG_ELOG
732 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
733#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200734 break;
735 }
736}
737
738static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
739{
740 if (!vendor || !device) {
741 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
742 pci_read_config32(dev, PCI_VENDOR_ID));
743 } else {
744 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
745 ((device & 0xffff) << 16) | (vendor & 0xffff));
746 }
747}
748
749static struct pci_operations pci_ops = {
750 .set_subsystem = set_subsystem,
751};
752
753static struct device_operations device_ops = {
754 .read_resources = pci_dev_read_resources,
755 .set_resources = pci_dev_set_resources,
756 .enable_resources = pci_dev_enable_resources,
757 .init = intel_me_init,
758 .scan_bus = scan_static_bus,
759 .ops_pci = &pci_ops,
760};
761
762static const struct pci_driver intel_me __pci_driver = {
763 .ops = &device_ops,
764 .vendor = PCI_VENDOR_ID_INTEL,
765 .device = 0x1c3a,
766};
767
768#endif /* !__SMM__ */