blob: 8c7b7c80b7d00f7ecbbeeac8681449692fb1b516 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin76c37002012-10-30 09:03:43 -05002
3/*
4 * This is a ramstage driver for the Intel Management Engine found in the
5 * 6-series chipset. It handles the required boot-time messages over the
6 * MMIO-based Management Engine Interface to tell the ME that the BIOS is
7 * finished with POST. Additional messages are defined for debug but are
8 * not used unless the console loglevel is high enough.
9 */
10
Furquan Shaikh76cedd22020-05-02 10:24:23 -070011#include <acpi/acpi.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020012#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020013#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050014#include <console/console.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070015#include <device/device.h>
16#include <device/pci.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050017#include <device/pci_ids.h>
18#include <device/pci_def.h>
19#include <string.h>
20#include <delay.h>
21#include <elog.h>
Elyes HAOUAS400f9ca2019-06-23 07:01:22 +020022#include <stdlib.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050023
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030024#include "chip.h"
Aaron Durbin76c37002012-10-30 09:03:43 -050025#include "me.h"
26#include "pch.h"
27
Aaron Durbin76c37002012-10-30 09:03:43 -050028#include <vendorcode/google/chromeos/chromeos.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050029
Aaron Durbin76c37002012-10-30 09:03:43 -050030/* Path that the BIOS should take based on ME state */
Angel Ponsf01884e2020-06-21 12:48:48 +020031static const char *const me_bios_path_values[] __unused = {
Aaron Durbin76c37002012-10-30 09:03:43 -050032 [ME_NORMAL_BIOS_PATH] = "Normal",
33 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
34 [ME_ERROR_BIOS_PATH] = "Error",
35 [ME_RECOVERY_BIOS_PATH] = "Recovery",
36 [ME_DISABLE_BIOS_PATH] = "Disable",
37 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
38};
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +010039static int intel_me_read_mbp(me_bios_payload *mbp_data, struct device *dev);
Aaron Durbin76c37002012-10-30 09:03:43 -050040
41/* MMIO base address for MEI interface */
Angel Ponsa3492d72021-02-23 14:12:25 +010042static u8 *mei_base_address;
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +010043#ifdef __SIMPLE_DEVICE__
44void intel_me_mbp_clear(pci_devfn_t dev);
45#else
46void intel_me_mbp_clear(struct device *dev);
47#endif
Aaron Durbin76c37002012-10-30 09:03:43 -050048
Aaron Durbin76c37002012-10-30 09:03:43 -050049static void mei_dump(void *ptr, int dword, int offset, const char *type)
50{
51 struct mei_csr *csr;
52
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +020053 if (!CONFIG(DEBUG_INTEL_ME))
54 return;
55
Aaron Durbin76c37002012-10-30 09:03:43 -050056 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
57
58 switch (offset) {
59 case MEI_H_CSR:
60 case MEI_ME_CSR_HA:
61 csr = ptr;
62 if (!csr) {
63 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
64 break;
65 }
66 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
67 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
68 csr->buffer_read_ptr, csr->buffer_write_ptr,
69 csr->ready, csr->reset, csr->interrupt_generate,
70 csr->interrupt_status, csr->interrupt_enable);
71 break;
72 case MEI_ME_CB_RW:
73 case MEI_H_CB_WW:
74 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
75 break;
76 default:
77 printk(BIOS_SPEW, "0x%08x\n", offset);
78 break;
79 }
80}
Aaron Durbin76c37002012-10-30 09:03:43 -050081
82/*
83 * ME/MEI access helpers using memcpy to avoid aliasing.
84 */
85
86static inline void mei_read_dword_ptr(void *ptr, int offset)
87{
Angel Ponsa3492d72021-02-23 14:12:25 +010088 u32 dword = read32(mei_base_address + offset);
Aaron Durbin76c37002012-10-30 09:03:43 -050089 memcpy(ptr, &dword, sizeof(dword));
90 mei_dump(ptr, dword, offset, "READ");
91}
92
93static inline void mei_write_dword_ptr(void *ptr, int offset)
94{
95 u32 dword = 0;
96 memcpy(&dword, ptr, sizeof(dword));
Angel Ponsa3492d72021-02-23 14:12:25 +010097 write32(mei_base_address + offset, dword);
Aaron Durbin76c37002012-10-30 09:03:43 -050098 mei_dump(ptr, dword, offset, "WRITE");
99}
100
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100101#ifdef __SIMPLE_DEVICE__
102static inline void pci_read_dword_ptr(pci_devfn_t dev, void *ptr, int offset)
103#else
104static inline void pci_read_dword_ptr(struct device *dev, void *ptr, int offset)
105#endif
Aaron Durbin76c37002012-10-30 09:03:43 -0500106{
107 u32 dword = pci_read_config32(dev, offset);
108 memcpy(ptr, &dword, sizeof(dword));
109 mei_dump(ptr, dword, offset, "PCI READ");
110}
Aaron Durbin76c37002012-10-30 09:03:43 -0500111
112static inline void read_host_csr(struct mei_csr *csr)
113{
114 mei_read_dword_ptr(csr, MEI_H_CSR);
115}
116
117static inline void write_host_csr(struct mei_csr *csr)
118{
119 mei_write_dword_ptr(csr, MEI_H_CSR);
120}
121
122static inline void read_me_csr(struct mei_csr *csr)
123{
124 mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
125}
126
127static inline void write_cb(u32 dword)
128{
Angel Ponsa3492d72021-02-23 14:12:25 +0100129 write32(mei_base_address + MEI_H_CB_WW, dword);
Aaron Durbin76c37002012-10-30 09:03:43 -0500130 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
131}
132
133static inline u32 read_cb(void)
134{
Angel Ponsa3492d72021-02-23 14:12:25 +0100135 u32 dword = read32(mei_base_address + MEI_ME_CB_RW);
Aaron Durbin76c37002012-10-30 09:03:43 -0500136 mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
137 return dword;
138}
139
140/* Wait for ME ready bit to be asserted */
141static int mei_wait_for_me_ready(void)
142{
143 struct mei_csr me;
Martin Rothff744bf2019-10-23 21:46:03 -0600144 unsigned int try = ME_RETRY;
Aaron Durbin76c37002012-10-30 09:03:43 -0500145
146 while (try--) {
147 read_me_csr(&me);
148 if (me.ready)
149 return 0;
150 udelay(ME_DELAY);
151 }
152
153 printk(BIOS_ERR, "ME: failed to become ready\n");
154 return -1;
155}
156
157static void mei_reset(void)
158{
159 struct mei_csr host;
160
161 if (mei_wait_for_me_ready() < 0)
162 return;
163
164 /* Reset host and ME circular buffers for next message */
165 read_host_csr(&host);
166 host.reset = 1;
167 host.interrupt_generate = 1;
168 write_host_csr(&host);
169
170 if (mei_wait_for_me_ready() < 0)
171 return;
172
173 /* Re-init and indicate host is ready */
174 read_host_csr(&host);
175 host.interrupt_generate = 1;
176 host.ready = 1;
177 host.reset = 0;
178 write_host_csr(&host);
179}
180
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700181static int mei_send_packet(struct mei_header *mei, void *req_data)
Aaron Durbin76c37002012-10-30 09:03:43 -0500182{
183 struct mei_csr host;
Martin Rothff744bf2019-10-23 21:46:03 -0600184 unsigned int ndata, n;
Aaron Durbin76c37002012-10-30 09:03:43 -0500185 u32 *data;
186
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700187 /* Number of dwords to write */
Aaron Durbin76c37002012-10-30 09:03:43 -0500188 ndata = mei->length >> 2;
189
190 /* Pad non-dword aligned request message length */
191 if (mei->length & 3)
192 ndata++;
193 if (!ndata) {
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700194 printk(BIOS_DEBUG, "ME: request has no data\n");
Aaron Durbin76c37002012-10-30 09:03:43 -0500195 return -1;
196 }
197 ndata++; /* Add MEI header */
198
199 /*
200 * Make sure there is still room left in the circular buffer.
201 * Reset the buffer pointers if the requested message will not fit.
202 */
203 read_host_csr(&host);
204 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
205 printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
206 mei_reset();
207 read_host_csr(&host);
208 }
209
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700210 /* Ensure the requested length will fit in the circular buffer. */
Aaron Durbin76c37002012-10-30 09:03:43 -0500211 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
212 printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
213 ndata + 2, host.buffer_depth);
214 return -1;
215 }
216
217 /* Write MEI header */
218 mei_write_dword_ptr(mei, MEI_H_CB_WW);
219 ndata--;
220
Aaron Durbin76c37002012-10-30 09:03:43 -0500221 /* Write message data */
222 data = req_data;
223 for (n = 0; n < ndata; ++n)
224 write_cb(*data++);
225
226 /* Generate interrupt to the ME */
227 read_host_csr(&host);
228 host.interrupt_generate = 1;
229 write_host_csr(&host);
230
231 /* Make sure ME is ready after sending request data */
232 return mei_wait_for_me_ready();
233}
234
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700235static int mei_send_data(u8 me_address, u8 host_address,
236 void *req_data, int req_bytes)
237{
238 struct mei_header header = {
239 .client_address = me_address,
240 .host_address = host_address,
241 };
242 struct mei_csr host;
243 int current = 0;
244 u8 *req_ptr = req_data;
245
246 while (!header.is_complete) {
247 int remain = req_bytes - current;
248 int buf_len;
249
250 read_host_csr(&host);
251 buf_len = host.buffer_depth - host.buffer_write_ptr;
252
253 if (buf_len > remain) {
254 /* Send all remaining data as final message */
255 header.length = req_bytes - current;
256 header.is_complete = 1;
257 } else {
258 /* Send as much data as the buffer can hold */
259 header.length = buf_len;
260 }
261
262 mei_send_packet(&header, req_ptr);
263
264 req_ptr += header.length;
265 current += header.length;
266 }
267
268 return 0;
269}
270
271static int mei_send_header(u8 me_address, u8 host_address,
272 void *header, int header_len, int complete)
273{
274 struct mei_header mei = {
275 .client_address = me_address,
276 .host_address = host_address,
277 .length = header_len,
278 .is_complete = complete,
279 };
280 return mei_send_packet(&mei, header);
281}
282
283static int mei_recv_msg(void *header, int header_bytes,
Aaron Durbin76c37002012-10-30 09:03:43 -0500284 void *rsp_data, int rsp_bytes)
285{
286 struct mei_header mei_rsp;
Aaron Durbin76c37002012-10-30 09:03:43 -0500287 struct mei_csr me, host;
Martin Rothff744bf2019-10-23 21:46:03 -0600288 unsigned int ndata, n;
289 unsigned int expected;
Aaron Durbin76c37002012-10-30 09:03:43 -0500290 u32 *data;
291
292 /* Total number of dwords to read from circular buffer */
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700293 expected = (rsp_bytes + sizeof(mei_rsp) + header_bytes) >> 2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500294 if (rsp_bytes & 3)
295 expected++;
296
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700297 if (mei_wait_for_me_ready() < 0)
298 return -1;
299
Aaron Durbin76c37002012-10-30 09:03:43 -0500300 /*
301 * The interrupt status bit does not appear to indicate that the
302 * message has actually been received. Instead we wait until the
303 * expected number of dwords are present in the circular buffer.
304 */
305 for (n = ME_RETRY; n; --n) {
306 read_me_csr(&me);
307 if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
308 break;
309 udelay(ME_DELAY);
310 }
311 if (!n) {
312 printk(BIOS_ERR, "ME: timeout waiting for data: expected "
313 "%u, available %u\n", expected,
314 me.buffer_write_ptr - me.buffer_read_ptr);
315 return -1;
316 }
317
318 /* Read and verify MEI response header from the ME */
319 mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
320 if (!mei_rsp.is_complete) {
321 printk(BIOS_ERR, "ME: response is not complete\n");
322 return -1;
323 }
324
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700325 /* Handle non-dword responses and expect at least the header */
Aaron Durbin76c37002012-10-30 09:03:43 -0500326 ndata = mei_rsp.length >> 2;
327 if (mei_rsp.length & 3)
328 ndata++;
329 if (ndata != (expected - 1)) {
330 printk(BIOS_ERR, "ME: response is missing data %d != %d\n",
331 ndata, (expected - 1));
332 return -1;
333 }
334
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700335 /* Read response header from the ME */
336 data = header;
337 for (n = 0; n < (header_bytes >> 2); ++n)
338 *data++ = read_cb();
339 ndata -= header_bytes >> 2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500340
341 /* Make sure caller passed a buffer with enough space */
342 if (ndata != (rsp_bytes >> 2)) {
343 printk(BIOS_ERR, "ME: not enough room in response buffer: "
344 "%u != %u\n", ndata, rsp_bytes >> 2);
345 return -1;
346 }
347
348 /* Read response data from the circular buffer */
349 data = rsp_data;
350 for (n = 0; n < ndata; ++n)
351 *data++ = read_cb();
352
353 /* Tell the ME that we have consumed the response */
354 read_host_csr(&host);
355 host.interrupt_status = 1;
356 host.interrupt_generate = 1;
357 write_host_csr(&host);
358
359 return mei_wait_for_me_ready();
360}
361
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700362static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi,
363 void *req_data, int req_bytes,
364 void *rsp_data, int rsp_bytes)
Aaron Durbin76c37002012-10-30 09:03:43 -0500365{
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700366 struct mkhi_header mkhi_rsp;
367
368 /* Send header */
369 if (mei_send_header(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS,
370 mkhi, sizeof(*mkhi), req_bytes ? 0 : 1) < 0)
Aaron Durbin76c37002012-10-30 09:03:43 -0500371 return -1;
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700372
373 /* Send data if available */
374 if (req_bytes && mei_send_data(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS,
375 req_data, req_bytes) < 0)
Aaron Durbin76c37002012-10-30 09:03:43 -0500376 return -1;
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700377
378 /* Return now if no response expected */
379 if (!rsp_bytes)
380 return 0;
381
382 /* Read header and data */
383 if (mei_recv_msg(&mkhi_rsp, sizeof(mkhi_rsp),
384 rsp_data, rsp_bytes) < 0)
385 return -1;
386
387 if (!mkhi_rsp.is_response ||
388 mkhi->group_id != mkhi_rsp.group_id ||
389 mkhi->command != mkhi_rsp.command) {
390 printk(BIOS_ERR, "ME: invalid response, group %u ?= %u,"
391 "command %u ?= %u, is_response %u\n", mkhi->group_id,
392 mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
393 mkhi_rsp.is_response);
394 return -1;
395 }
396
Aaron Durbin76c37002012-10-30 09:03:43 -0500397 return 0;
398}
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700399
Duncan Laurie3d299c42013-07-19 08:48:05 -0700400/*
401 * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
402 * state machine on the BIOS end doesn't match the ME's state machine.
403 */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100404#ifdef __SIMPLE_DEVICE__
405static void intel_me_mbp_give_up(pci_devfn_t dev)
406#else
407static void intel_me_mbp_give_up(struct device *dev)
408#endif
Duncan Laurie3d299c42013-07-19 08:48:05 -0700409{
410 struct mei_csr csr;
411
412 pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP);
413
414 read_host_csr(&csr);
415 csr.reset = 1;
416 csr.interrupt_generate = 1;
417 write_host_csr(&csr);
418}
419
420/*
421 * mbp clear routine. This will wait for the ME to indicate that
422 * the MBP has been read and cleared.
423 */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100424#ifdef __SIMPLE_DEVICE__
425void intel_me_mbp_clear(pci_devfn_t dev)
426#else
427void intel_me_mbp_clear(struct device *dev)
428#endif
Duncan Laurie3d299c42013-07-19 08:48:05 -0700429{
430 int count;
431 struct me_hfs2 hfs2;
432
433 /* Wait for the mbp_cleared indicator */
434 for (count = ME_RETRY; count > 0; --count) {
435 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
436 if (hfs2.mbp_cleared)
437 break;
438 udelay(ME_DELAY);
439 }
440
441 if (count == 0) {
442 printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n");
443 intel_me_mbp_give_up(dev);
444 } else {
445 printk(BIOS_INFO, "ME: MBP cleared\n");
446 }
447}
448
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200449static void __unused me_print_fw_version(mbp_fw_version_name *vers_name)
Aaron Durbin76c37002012-10-30 09:03:43 -0500450{
Aaron Durbinbe985242012-12-12 12:40:33 -0600451 if (!vers_name) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500452 printk(BIOS_ERR, "ME: mbp missing version report\n");
453 return;
454 }
455
456 printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
457 vers_name->major_version, vers_name->minor_version,
458 vers_name->hotfix_version, vers_name->build_version);
459}
460
Edward O'Callaghan7bf4f482014-06-17 15:12:09 +1000461static inline void print_cap(const char *name, int state)
462{
463 printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
464 name, state ? " en" : "dis");
465}
466
Aaron Durbin76c37002012-10-30 09:03:43 -0500467/* Get ME Firmware Capabilities */
Aaron Durbinbe985242012-12-12 12:40:33 -0600468static int mkhi_get_fwcaps(mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500469{
470 u32 rule_id = 0;
471 struct me_fwcaps cap_msg;
472 struct mkhi_header mkhi = {
473 .group_id = MKHI_GROUP_ID_FWCAPS,
474 .command = MKHI_FWCAPS_GET_RULE,
475 };
Aaron Durbin76c37002012-10-30 09:03:43 -0500476
477 /* Send request and wait for response */
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700478 if (mei_sendrecv_mkhi(&mkhi, &rule_id, sizeof(u32),
479 &cap_msg, sizeof(cap_msg)) < 0) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500480 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
481 return -1;
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200482 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500483 *cap = cap_msg.caps_sku;
484 return 0;
485}
486
487/* Get ME Firmware Capabilities */
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200488static void __unused me_print_fwcaps(mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500489{
Aaron Durbinbe985242012-12-12 12:40:33 -0600490 mbp_mefwcaps local_caps;
491 if (!cap) {
492 cap = &local_caps;
Aaron Durbin76c37002012-10-30 09:03:43 -0500493 printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
494 if (mkhi_get_fwcaps(cap))
495 return;
496 }
497
498 print_cap("Full Network manageability", cap->full_net);
499 print_cap("Regular Network manageability", cap->std_net);
500 print_cap("Manageability", cap->manageability);
Aaron Durbin76c37002012-10-30 09:03:43 -0500501 print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
502 print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
503 print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
504 print_cap("ICC Over Clocking", cap->icc_over_clocking);
Edward O'Callaghan7bf4f482014-06-17 15:12:09 +1000505 print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
Aaron Durbin76c37002012-10-30 09:03:43 -0500506 print_cap("IPV6", cap->ipv6);
507 print_cap("KVM Remote Control (KVM)", cap->kvm);
508 print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
509 print_cap("Virtual LAN (VLAN)", cap->vlan);
510 print_cap("TLS", cap->tls);
511 print_cap("Wireless LAN (WLAN)", cap->wlan);
512}
Aaron Durbin76c37002012-10-30 09:03:43 -0500513
Aaron Durbin76c37002012-10-30 09:03:43 -0500514/* Send END OF POST message to the ME */
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200515static int __unused mkhi_end_of_post(void)
Aaron Durbin76c37002012-10-30 09:03:43 -0500516{
517 struct mkhi_header mkhi = {
518 .group_id = MKHI_GROUP_ID_GEN,
519 .command = MKHI_END_OF_POST,
520 };
Aaron Durbin76c37002012-10-30 09:03:43 -0500521 u32 eop_ack;
522
523 /* Send request and wait for response */
Angel Pons08e8cab2020-06-18 15:20:37 +0200524 printk(BIOS_NOTICE, "ME: %s\n", __func__);
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700525 if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &eop_ack, sizeof(eop_ack)) < 0) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500526 printk(BIOS_ERR, "ME: END OF POST message failed\n");
527 return -1;
528 }
529
530 printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack);
531 return 0;
532}
533
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200534#ifdef __SIMPLE_DEVICE__
535
Duncan Laurieaf980622013-07-18 23:02:18 -0700536void intel_me_finalize_smm(void)
537{
538 struct me_hfs hfs;
539 u32 reg32;
540
Angel Ponsa3492d72021-02-23 14:12:25 +0100541 reg32 = pci_read_config32(PCH_ME_DEV, PCI_BASE_ADDRESS_0);
542 mei_base_address = (u8 *)(uintptr_t)(reg32 & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
Duncan Laurieaf980622013-07-18 23:02:18 -0700543
544 /* S3 path will have hidden this device already */
Angel Ponsa3492d72021-02-23 14:12:25 +0100545 if (!mei_base_address || mei_base_address == (u8 *)0xfffffff0)
Duncan Laurieaf980622013-07-18 23:02:18 -0700546 return;
547
Duncan Laurie3d299c42013-07-19 08:48:05 -0700548 /* Wait for ME MBP Cleared indicator */
549 intel_me_mbp_clear(PCH_ME_DEV);
Duncan Laurie3d299c42013-07-19 08:48:05 -0700550
Duncan Laurieaf980622013-07-18 23:02:18 -0700551 /* Make sure ME is in a mode that expects EOP */
552 reg32 = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
553 memcpy(&hfs, &reg32, sizeof(u32));
554
555 /* Abort and leave device alone if not normal mode */
556 if (hfs.fpt_bad ||
557 hfs.working_state != ME_HFS_CWS_NORMAL ||
558 hfs.operation_mode != ME_HFS_MODE_NORMAL)
559 return;
560
561 /* Try to send EOP command so ME stops accepting other commands */
562 mkhi_end_of_post();
563
564 /* Make sure IO is disabled */
Angel Ponsbf9bc502020-06-08 00:12:43 +0200565 pci_and_config16(PCH_ME_DEV, PCI_COMMAND,
566 ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
Duncan Laurieaf980622013-07-18 23:02:18 -0700567
568 /* Hide the PCI device */
569 RCBA32_OR(FD2, PCH_DISABLE_MEI1);
570}
571
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200572#else /* !__SIMPLE_DEVICE__ */
Duncan Laurieaf980622013-07-18 23:02:18 -0700573
Edward O'Callaghan97ccefd2015-01-07 15:53:00 +1100574static inline int mei_sendrecv_icc(struct icc_header *icc,
575 void *req_data, int req_bytes,
576 void *rsp_data, int rsp_bytes)
577{
578 struct icc_header icc_rsp;
579
580 /* Send header */
581 if (mei_send_header(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
582 icc, sizeof(*icc), req_bytes ? 0 : 1) < 0)
583 return -1;
584
585 /* Send data if available */
586 if (req_bytes && mei_send_data(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
587 req_data, req_bytes) < 0)
588 return -1;
589
590 /* Read header and data, if needed */
591 if (rsp_bytes && mei_recv_msg(&icc_rsp, sizeof(icc_rsp),
592 rsp_data, rsp_bytes) < 0)
593 return -1;
594
595 return 0;
596}
597
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700598static int me_icc_set_clock_enables(u32 mask)
599{
600 struct icc_clock_enables_msg clk = {
601 .clock_enables = 0, /* Turn off specified clocks */
602 .clock_mask = mask,
603 .no_response = 1, /* Do not expect response */
604 };
605 struct icc_header icc = {
606 .api_version = ICC_API_VERSION_LYNXPOINT,
607 .icc_command = ICC_SET_CLOCK_ENABLES,
608 .length = sizeof(clk),
609 };
610
611 /* Send request and wait for response */
612 if (mei_sendrecv_icc(&icc, &clk, sizeof(clk), NULL, 0) < 0) {
613 printk(BIOS_ERR, "ME: ICC SET CLOCK ENABLES message failed\n");
614 return -1;
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700615 }
616
Elyes HAOUAS54f94242018-10-25 10:57:39 +0200617 printk(BIOS_INFO, "ME: ICC SET CLOCK ENABLES 0x%08x\n", mask);
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700618 return 0;
619}
620
Aaron Durbin76c37002012-10-30 09:03:43 -0500621/* Determine the path that we should take based on ME status */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100622static me_bios_path intel_me_path(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500623{
624 me_bios_path path = ME_DISABLE_BIOS_PATH;
625 struct me_hfs hfs;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500626 struct me_hfs2 hfs2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500627
Aaron Durbin76c37002012-10-30 09:03:43 -0500628 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500629 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500630
631 /* Check and dump status */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500632 intel_me_status(&hfs, &hfs2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500633
634 /* Check Current Working State */
635 switch (hfs.working_state) {
636 case ME_HFS_CWS_NORMAL:
637 path = ME_NORMAL_BIOS_PATH;
638 break;
639 case ME_HFS_CWS_REC:
640 path = ME_RECOVERY_BIOS_PATH;
641 break;
642 default:
643 path = ME_DISABLE_BIOS_PATH;
644 break;
645 }
646
647 /* Check Current Operation Mode */
648 switch (hfs.operation_mode) {
649 case ME_HFS_MODE_NORMAL:
650 break;
651 case ME_HFS_MODE_DEBUG:
652 case ME_HFS_MODE_DIS:
653 case ME_HFS_MODE_OVER_JMPR:
654 case ME_HFS_MODE_OVER_MEI:
655 default:
656 path = ME_DISABLE_BIOS_PATH;
657 break;
658 }
659
660 /* Check for any error code and valid firmware and MBP */
661 if (hfs.error_code || hfs.fpt_bad)
662 path = ME_ERROR_BIOS_PATH;
663
664 /* Check if the MBP is ready */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500665 if (!hfs2.mbp_rdy) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500666 printk(BIOS_CRIT, "%s: mbp is not ready!\n",
Angel Pons08e8cab2020-06-18 15:20:37 +0200667 __func__);
Aaron Durbin76c37002012-10-30 09:03:43 -0500668 path = ME_ERROR_BIOS_PATH;
669 }
670
Kyösti Mälkkibe5317f2019-11-06 12:07:21 +0200671 if (CONFIG(ELOG) && path != ME_NORMAL_BIOS_PATH) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500672 struct elog_event_data_me_extended data = {
673 .current_working_state = hfs.working_state,
674 .operation_state = hfs.operation_state,
675 .operation_mode = hfs.operation_mode,
676 .error_code = hfs.error_code,
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500677 .progress_code = hfs2.progress_code,
678 .current_pmevent = hfs2.current_pmevent,
679 .current_state = hfs2.current_state,
Aaron Durbin76c37002012-10-30 09:03:43 -0500680 };
681 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
682 elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
683 &data, sizeof(data));
684 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500685
686 return path;
687}
688
689/* Prepare ME for MEI messages */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100690static int intel_mei_setup(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500691{
692 struct resource *res;
693 struct mei_csr host;
Aaron Durbin76c37002012-10-30 09:03:43 -0500694
695 /* Find the MMIO base for the ME interface */
696 res = find_resource(dev, PCI_BASE_ADDRESS_0);
697 if (!res || res->base == 0 || res->size == 0) {
698 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
699 return -1;
700 }
Angel Ponsd32b5142021-02-23 14:23:49 +0100701 mei_base_address = res2mmio(res, 0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500702
703 /* Ensure Memory and Bus Master bits are set */
Angel Ponsd5d4fbc2020-05-31 01:03:59 +0200704 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Aaron Durbin76c37002012-10-30 09:03:43 -0500705
706 /* Clean up status for next message */
707 read_host_csr(&host);
708 host.interrupt_generate = 1;
709 host.ready = 1;
710 host.reset = 0;
711 write_host_csr(&host);
712
713 return 0;
714}
715
716/* Read the Extend register hash of ME firmware */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100717static int intel_me_extend_valid(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500718{
719 struct me_heres status;
720 u32 extend[8] = {0};
721 int i, count = 0;
722
723 pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
724 if (!status.extend_feature_present) {
725 printk(BIOS_ERR, "ME: Extend Feature not present\n");
726 return -1;
727 }
728
729 if (!status.extend_reg_valid) {
730 printk(BIOS_ERR, "ME: Extend Register not valid\n");
731 return -1;
732 }
733
734 switch (status.extend_reg_algorithm) {
735 case PCI_ME_EXT_SHA1:
736 count = 5;
737 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
738 break;
739 case PCI_ME_EXT_SHA256:
740 count = 8;
741 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
742 break;
743 default:
744 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
745 status.extend_reg_algorithm);
746 return -1;
747 }
748
749 for (i = 0; i < count; ++i) {
750 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
751 printk(BIOS_DEBUG, "%08x", extend[i]);
752 }
753 printk(BIOS_DEBUG, "\n");
754
Aaron Durbin76c37002012-10-30 09:03:43 -0500755 /* Save hash in NVS for the OS to verify */
Kyösti Mälkki26e0f4c2020-12-19 19:10:45 +0200756 if (CONFIG(CHROMEOS))
757 chromeos_set_me_hash(extend, count);
Aaron Durbin76c37002012-10-30 09:03:43 -0500758
759 return 0;
760}
761
Aaron Durbin76c37002012-10-30 09:03:43 -0500762/* Check whether ME is present and do basic init */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100763static void intel_me_init(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500764{
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700765 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500766 me_bios_path path = intel_me_path(dev);
767 me_bios_payload mbp_data;
768
769 /* Do initial setup and determine the BIOS path */
770 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
771
Duncan Laurie8056dc62013-07-22 08:47:43 -0700772 if (path == ME_NORMAL_BIOS_PATH) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500773 /* Validate the extend register */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500774 intel_me_extend_valid(dev);
775 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500776
Aaron Durbinbe985242012-12-12 12:40:33 -0600777 memset(&mbp_data, 0, sizeof(mbp_data));
778
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500779 /*
780 * According to the ME9 BWG, BIOS is required to fetch MBP data in
781 * all boot flows except S3 Resume.
782 */
Aaron Durbin76c37002012-10-30 09:03:43 -0500783
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500784 /* Prepare MEI MMIO interface */
785 if (intel_mei_setup(dev) < 0)
786 return;
Aaron Durbin76c37002012-10-30 09:03:43 -0500787
Duncan Laurie144f7b22013-05-01 11:27:58 -0700788 if (intel_me_read_mbp(&mbp_data, dev))
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500789 return;
Aaron Durbin76c37002012-10-30 09:03:43 -0500790
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200791 if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
792 me_print_fw_version(mbp_data.fw_version_name);
Duncan Laurie144f7b22013-05-01 11:27:58 -0700793
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200794 if (CONFIG(DEBUG_INTEL_ME))
795 me_print_fwcaps(mbp_data.fw_capabilities);
796
797 if (mbp_data.plat_time) {
798 printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n",
799 mbp_data.plat_time->wake_event_mrst_time_ms);
800 printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n",
801 mbp_data.plat_time->mrst_pltrst_time_ms);
802 printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n",
803 mbp_data.plat_time->pltrst_cpurst_time_ms);
804 }
Duncan Laurie144f7b22013-05-01 11:27:58 -0700805 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500806
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700807 /* Set clock enables according to devicetree */
808 if (config && config->icc_clock_disable)
809 me_icc_set_clock_enables(config->icc_clock_disable);
810
Duncan Laurieaf980622013-07-18 23:02:18 -0700811 /*
812 * Leave the ME unlocked. It will be locked via SMI command later.
813 */
Aaron Durbin76c37002012-10-30 09:03:43 -0500814}
815
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100816static void intel_me_enable(struct device *dev)
Duncan Laurie8056dc62013-07-22 08:47:43 -0700817{
Duncan Laurie8056dc62013-07-22 08:47:43 -0700818 /* Avoid talking to the device in S3 path */
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +0300819 if (acpi_is_wakeup_s3()) {
Duncan Laurie8056dc62013-07-22 08:47:43 -0700820 dev->enabled = 0;
821 pch_disable_devfn(dev);
822 }
Duncan Laurie8056dc62013-07-22 08:47:43 -0700823}
824
Aaron Durbin76c37002012-10-30 09:03:43 -0500825static struct device_operations device_ops = {
826 .read_resources = pci_dev_read_resources,
827 .set_resources = pci_dev_set_resources,
828 .enable_resources = pci_dev_enable_resources,
Duncan Laurie8056dc62013-07-22 08:47:43 -0700829 .enable = intel_me_enable,
Aaron Durbin76c37002012-10-30 09:03:43 -0500830 .init = intel_me_init,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200831 .ops_pci = &pci_dev_ops_pci,
Aaron Durbin76c37002012-10-30 09:03:43 -0500832};
833
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800834static const unsigned short pci_device_ids[] = {
Felix Singer4ea08f92020-11-20 12:56:44 +0000835 PCI_DEVICE_ID_INTEL_LPT_H_MEI,
836 PCI_DEVICE_ID_INTEL_LPT_LP_MEI,
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800837 0
838};
839
Aaron Durbin76c37002012-10-30 09:03:43 -0500840static const struct pci_driver intel_me __pci_driver = {
Angel Ponsb4b4e322020-06-21 12:47:13 +0200841 .ops = &device_ops,
842 .vendor = PCI_VENDOR_ID_INTEL,
843 .devices = pci_device_ids,
Aaron Durbin76c37002012-10-30 09:03:43 -0500844};
845
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200846#endif /* !__SIMPLE_DEVICE__ */
847
Aaron Durbin76c37002012-10-30 09:03:43 -0500848/******************************************************************************
849 * */
850static u32 me_to_host_words_pending(void)
851{
852 struct mei_csr me;
853 read_me_csr(&me);
854 if (!me.ready)
855 return 0;
856 return (me.buffer_write_ptr - me.buffer_read_ptr) &
857 (me.buffer_depth - 1);
858}
859
Aaron Durbinbe985242012-12-12 12:40:33 -0600860struct mbp_payload {
861 mbp_header header;
862 u32 data[0];
863};
864
Aaron Durbin76c37002012-10-30 09:03:43 -0500865/*
866 * mbp seems to be following its own flow, let's retrieve it in a dedicated
867 * function.
868 */
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200869static int __unused intel_me_read_mbp(me_bios_payload *mbp_data, struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500870{
871 mbp_header mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500872 u32 me2host_pending;
Aaron Durbin76c37002012-10-30 09:03:43 -0500873 struct mei_csr host;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500874 struct me_hfs2 hfs2;
Aaron Durbinbe985242012-12-12 12:40:33 -0600875 struct mbp_payload *mbp;
876 int i;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500877
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200878#ifdef __SIMPLE_DEVICE__
879 pci_read_dword_ptr(PCI_BDF(dev), &hfs2, PCI_ME_HFS2);
880#else
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500881 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200882#endif
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500883
884 if (!hfs2.mbp_rdy) {
885 printk(BIOS_ERR, "ME: MBP not ready\n");
886 goto mbp_failure;
887 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500888
889 me2host_pending = me_to_host_words_pending();
890 if (!me2host_pending) {
891 printk(BIOS_ERR, "ME: no mbp data!\n");
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500892 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500893 }
894
895 /* we know for sure that at least the header is there */
896 mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
897
898 if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
899 (me2host_pending < mbp_hdr.mbp_size)) {
900 printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
901 " buffer contains %d words\n",
902 mbp_hdr.num_entries, mbp_hdr.mbp_size,
903 me2host_pending);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500904 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500905 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600906 mbp = malloc(mbp_hdr.mbp_size * sizeof(u32));
907 if (!mbp)
908 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500909
Aaron Durbinbe985242012-12-12 12:40:33 -0600910 mbp->header = mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500911 me2host_pending--;
Aaron Durbin76c37002012-10-30 09:03:43 -0500912
Aaron Durbinbe985242012-12-12 12:40:33 -0600913 i = 0;
914 while (i != me2host_pending) {
915 mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW);
916 i++;
Aaron Durbin76c37002012-10-30 09:03:43 -0500917 }
918
Aaron Durbinbe985242012-12-12 12:40:33 -0600919 /* Signal to the ME that the host has finished reading the MBP. */
Aaron Durbin76c37002012-10-30 09:03:43 -0500920 read_host_csr(&host);
921 host.interrupt_generate = 1;
922 write_host_csr(&host);
923
Aaron Durbinbe985242012-12-12 12:40:33 -0600924 /* Dump out the MBP contents. */
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200925 if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
926 printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n",
927 mbp->header.num_entries, mbp->header.mbp_size);
928 if (CONFIG(DEBUG_INTEL_ME)) {
929 for (i = 0; i < mbp->header.mbp_size - 1; i++) {
930 printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]);
931 }
932 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600933 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600934
935 #define ASSIGN_FIELD_PTR(field_,val_) \
936 { \
937 mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \
938 break; \
939 }
940 /* Setup the pointers in the me_bios_payload structure. */
941 for (i = 0; i < mbp->header.mbp_size - 1;) {
942 mbp_item_header *item = (void *)&mbp->data[i];
943
Elyes HAOUASf9de5a42018-05-03 17:21:02 +0200944 switch (MBP_MAKE_IDENT(item->app_id, item->item_id)) {
Aaron Durbinbe985242012-12-12 12:40:33 -0600945 case MBP_IDENT(KERNEL, FW_VER):
946 ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]);
947
948 case MBP_IDENT(ICC, PROFILE):
949 ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]);
950
951 case MBP_IDENT(INTEL_AT, STATE):
952 ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]);
953
954 case MBP_IDENT(KERNEL, FW_CAP):
955 ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]);
956
957 case MBP_IDENT(KERNEL, ROM_BIST):
958 ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]);
959
960 case MBP_IDENT(KERNEL, PLAT_KEY):
961 ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]);
962
963 case MBP_IDENT(KERNEL, FW_TYPE):
964 ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]);
965
966 case MBP_IDENT(KERNEL, MFS_FAILURE):
967 ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]);
968
Duncan Laurie144f7b22013-05-01 11:27:58 -0700969 case MBP_IDENT(KERNEL, PLAT_TIME):
970 ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]);
971
972 case MBP_IDENT(NFC, SUPPORT_DATA):
973 ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]);
974
Aaron Durbinbe985242012-12-12 12:40:33 -0600975 default:
Duncan Laurie0b3cd362013-08-08 15:40:01 -0700976 printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ "
977 "dw offset 0x%x\n", mbp->data[i], i);
Aaron Durbinbe985242012-12-12 12:40:33 -0600978 break;
979 }
980 i += item->length;
981 }
982 #undef ASSIGN_FIELD_PTR
983
Aaron Durbin76c37002012-10-30 09:03:43 -0500984 return 0;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500985
986mbp_failure:
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200987#ifdef __SIMPLE_DEVICE__
988 intel_me_mbp_give_up(PCI_BDF(dev));
989#else
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500990 intel_me_mbp_give_up(dev);
Kyösti Mälkki21d6a272019-11-05 18:50:38 +0200991#endif
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500992 return -1;
Aaron Durbin76c37002012-10-30 09:03:43 -0500993}