xref: /aosp_15_r20/external/coreboot/src/southbridge/intel/bd82x6x/me_8.x.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
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 
11 #include <acpi/acpi.h>
12 #include <cf9_reset.h>
13 #include <device/mmio.h>
14 #include <device/device.h>
15 #include <device/pci.h>
16 #include <device/pci_ops.h>
17 #include <console/console.h>
18 #include <device/pci_ids.h>
19 #include <string.h>
20 #include <elog.h>
21 #include <option.h>
22 #include <southbridge/intel/common/me.h>
23 
24 #include "me.h"
25 #include "pch.h"
26 
print_cap(const char * name,int state)27 static inline void print_cap(const char *name, int state)
28 {
29 	printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
30 	       name, state ? " en" : "dis");
31 }
32 
me_print_fw_version(mbp_fw_version_name * vers_name)33 static void me_print_fw_version(mbp_fw_version_name *vers_name)
34 {
35 	if (!vers_name->major_version) {
36 		printk(BIOS_ERR, "ME: mbp missing version report\n");
37 		return;
38 	}
39 
40 	printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
41 	       vers_name->major_version, vers_name->minor_version,
42 	       vers_name->hotfix_version, vers_name->build_version);
43 }
44 
45 /* Determine the path that we should take based on ME status */
intel_me_path(struct device * dev)46 static me_bios_path intel_me_path(struct device *dev)
47 {
48 	me_bios_path path = ME_DISABLE_BIOS_PATH;
49 	union me_hfs hfs;
50 	union me_gmes gmes;
51 
52 	/* S3 wake skips all MKHI messages */
53 	if (acpi_is_wakeup_s3())
54 		return ME_S3WAKE_BIOS_PATH;
55 
56 	hfs.raw = pci_read_config32(dev, PCI_ME_HFS);
57 	gmes.raw = pci_read_config32(dev, PCI_ME_GMES);
58 
59 	/* Check and dump status */
60 	intel_me_status(&hfs, &gmes);
61 
62 	/* Check Current Working State */
63 	switch (hfs.working_state) {
64 	case ME_HFS_CWS_NORMAL:
65 		path = ME_NORMAL_BIOS_PATH;
66 		break;
67 	case ME_HFS_CWS_REC:
68 		path = ME_RECOVERY_BIOS_PATH;
69 		break;
70 	default:
71 		path = ME_DISABLE_BIOS_PATH;
72 		break;
73 	}
74 
75 	/* Check Current Operation Mode */
76 	switch (hfs.operation_mode) {
77 	case ME_HFS_MODE_NORMAL:
78 		break;
79 	case ME_HFS_MODE_DEBUG:
80 	case ME_HFS_MODE_DIS:
81 	case ME_HFS_MODE_OVER_JMPR:
82 	case ME_HFS_MODE_OVER_MEI:
83 	default:
84 		path = ME_DISABLE_BIOS_PATH;
85 		break;
86 	}
87 
88 	/* Check for any error code and valid firmware and MBP */
89 	if (hfs.error_code || hfs.fpt_bad)
90 		path = ME_ERROR_BIOS_PATH;
91 
92 	/* Check if the MBP is ready */
93 	if (!gmes.mbp_rdy) {
94 		printk(BIOS_CRIT, "%s: mbp is not ready!\n", __func__);
95 		path = ME_ERROR_BIOS_PATH;
96 	}
97 
98 	if (CONFIG(ELOG) && path != ME_NORMAL_BIOS_PATH) {
99 		struct elog_event_data_me_extended data = {
100 			.current_working_state = hfs.working_state,
101 			.operation_state       = hfs.operation_state,
102 			.operation_mode        = hfs.operation_mode,
103 			.error_code            = hfs.error_code,
104 			.progress_code         = gmes.progress_code,
105 			.current_pmevent       = gmes.current_pmevent,
106 			.current_state         = gmes.current_state,
107 		};
108 		elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
109 		elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
110 				   &data, sizeof(data));
111 	}
112 
113 	return path;
114 }
115 
116 static int intel_me_read_mbp(me_bios_payload *mbp_data);
117 
118 /* Get ME Firmware Capabilities */
mkhi_get_fwcaps(mefwcaps_sku * cap)119 static int mkhi_get_fwcaps(mefwcaps_sku *cap)
120 {
121 	u32 rule_id = 0;
122 	struct me_fwcaps cap_msg;
123 	struct mkhi_header mkhi = {
124 		.group_id       = MKHI_GROUP_ID_FWCAPS,
125 		.command        = MKHI_FWCAPS_GET_RULE,
126 	};
127 	struct mei_header mei = {
128 		.is_complete    = 1,
129 		.host_address   = MEI_HOST_ADDRESS,
130 		.client_address = MEI_ADDRESS_MKHI,
131 		.length         = sizeof(mkhi) + sizeof(rule_id),
132 	};
133 
134 	/* Send request and wait for response */
135 	if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap_msg, sizeof(cap_msg)) < 0) {
136 		printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
137 		return -1;
138 	}
139 	*cap = cap_msg.caps_sku;
140 	return 0;
141 }
142 
143 /* Get ME Firmware Capabilities */
me_print_fwcaps(mbp_fw_caps * caps_section)144 static void me_print_fwcaps(mbp_fw_caps *caps_section)
145 {
146 	mefwcaps_sku *cap = &caps_section->fw_capabilities;
147 	if (!caps_section->available) {
148 		printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
149 		if (mkhi_get_fwcaps(cap))
150 			return;
151 	}
152 
153 	print_cap("Full Network manageability", cap->full_net);
154 	print_cap("Regular Network manageability", cap->std_net);
155 	print_cap("Manageability", cap->manageability);
156 	print_cap("Small business technology", cap->small_business);
157 	print_cap("Level III manageability", cap->l3manageability);
158 	print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
159 	print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
160 	print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
161 	print_cap("ICC Over Clocking", cap->icc_over_clocking);
162 	print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
163 	print_cap("IPV6", cap->ipv6);
164 	print_cap("KVM Remote Control (KVM)", cap->kvm);
165 	print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
166 	print_cap("Virtual LAN (VLAN)", cap->vlan);
167 	print_cap("TLS", cap->tls);
168 	print_cap("Wireless LAN (WLAN)", cap->wlan);
169 }
170 
171 /* Check whether ME is present and do basic init */
intel_me_init(struct device * dev)172 static void intel_me_init(struct device *dev)
173 {
174 	me_bios_path path = intel_me_path(dev);
175 	me_bios_payload mbp_data;
176 	bool need_reset = false;
177 	union me_hfs hfs;
178 
179 	/* Do initial setup and determine the BIOS path */
180 	printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_get_bios_path_string(path));
181 
182 	u8 me_state = get_uint_option("me_state", 0);
183 	u8 me_state_prev = get_uint_option("me_state_prev", 0);
184 
185 	printk(BIOS_DEBUG, "ME: me_state=%u, me_state_prev=%u\n", me_state, me_state_prev);
186 
187 	switch (path) {
188 	case ME_S3WAKE_BIOS_PATH:
189 #if CONFIG(HIDE_MEI_ON_ERROR)
190 	case ME_ERROR_BIOS_PATH:
191 #endif
192 		intel_me_hide(dev);
193 		break;
194 
195 	case ME_NORMAL_BIOS_PATH:
196 		/* Validate the extend register */
197 		if (intel_me_extend_valid(dev) < 0)
198 			break; /* TODO: force recovery mode */
199 
200 		/* Prepare MEI MMIO interface */
201 		if (intel_mei_setup(dev) < 0)
202 			break;
203 
204 		if (intel_me_read_mbp(&mbp_data))
205 			break;
206 
207 		if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
208 			me_print_fw_version(&mbp_data.fw_version_name);
209 			me_print_fwcaps(&mbp_data.fw_caps_sku);
210 		}
211 
212 		/* Put ME in Software Temporary Disable Mode, if needed */
213 		if (me_state == CMOS_ME_STATE_DISABLED
214 				&& CMOS_ME_STATE(me_state_prev) == CMOS_ME_STATE_NORMAL) {
215 			printk(BIOS_INFO, "ME: disabling ME\n");
216 			if (enter_soft_temp_disable()) {
217 				enter_soft_temp_disable_wait();
218 				need_reset = true;
219 			} else {
220 				printk(BIOS_ERR, "ME: failed to enter Soft Temporary Disable mode\n");
221 			}
222 
223 			break;
224 		}
225 
226 		/*
227 		 * Leave the ME unlocked in this path.
228 		 * It will be locked via SMI command later.
229 		 */
230 		break;
231 
232 	case ME_DISABLE_BIOS_PATH:
233 		/* Bring ME out of Soft Temporary Disable mode, if needed */
234 		hfs.raw = pci_read_config32(dev, PCI_ME_HFS);
235 		if (hfs.operation_mode == ME_HFS_MODE_DIS
236 				&& me_state == CMOS_ME_STATE_NORMAL
237 				&& (CMOS_ME_STATE(me_state_prev) == CMOS_ME_STATE_DISABLED
238 					|| !CMOS_ME_CHANGED(me_state_prev))) {
239 			printk(BIOS_INFO, "ME: re-enabling ME\n");
240 
241 			exit_soft_temp_disable(dev);
242 			exit_soft_temp_disable_wait(dev);
243 
244 			/*
245 			 * ME starts loading firmware immediately after writing to H_GS,
246 			 * but Lenovo BIOS performs a reboot after bringing ME back to
247 			 * Normal mode. Assume that global reset is needed.
248 			 */
249 			need_reset = true;
250 		} else {
251 			intel_me_hide(dev);
252 		}
253 		break;
254 
255 #if !CONFIG(HIDE_MEI_ON_ERROR)
256 	case ME_ERROR_BIOS_PATH:
257 #endif
258 	case ME_RECOVERY_BIOS_PATH:
259 	case ME_FIRMWARE_UPDATE_BIOS_PATH:
260 		break;
261 	}
262 
263 	/* To avoid boot loops if ME fails to get back from disabled mode,
264 	   set the 'changed' bit here. */
265 	if (me_state != CMOS_ME_STATE(me_state_prev) || need_reset) {
266 		u8 new_state = me_state | CMOS_ME_STATE_CHANGED;
267 		set_uint_option("me_state_prev", new_state);
268 	}
269 
270 	if (need_reset) {
271 		set_global_reset(true);
272 		full_reset();
273 	}
274 }
275 
276 static struct device_operations device_ops = {
277 	.read_resources		= pci_dev_read_resources,
278 	.set_resources		= pci_dev_set_resources,
279 	.enable_resources	= pci_dev_enable_resources,
280 	.init			= intel_me_init,
281 	.ops_pci		= &pci_dev_ops_pci,
282 };
283 
284 static const struct pci_driver intel_me __pci_driver = {
285 	.ops	= &device_ops,
286 	.vendor	= PCI_VID_INTEL,
287 	.device	= 0x1e3a,
288 };
289 
290 /******************************************************************************
291  *									     */
me_to_host_words_pending(void)292 static u32 me_to_host_words_pending(void)
293 {
294 	struct mei_csr me;
295 	read_me_csr(&me);
296 	if (!me.ready)
297 		return 0;
298 	return (me.buffer_write_ptr - me.buffer_read_ptr) &
299 		(me.buffer_depth - 1);
300 }
301 
302 /*
303  * mbp seems to be following its own flow, let's retrieve it in a dedicated
304  * function.
305  */
intel_me_read_mbp(me_bios_payload * mbp_data)306 static int intel_me_read_mbp(me_bios_payload *mbp_data)
307 {
308 	mbp_header mbp_hdr;
309 	mbp_item_header	mbp_item_hdr;
310 	u32 me2host_pending;
311 	u32 mbp_item_id;
312 	struct mei_csr host;
313 
314 	me2host_pending = me_to_host_words_pending();
315 	if (!me2host_pending) {
316 		printk(BIOS_ERR, "ME: no mbp data!\n");
317 		return -1;
318 	}
319 
320 	/* we know for sure that at least the header is there */
321 	mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
322 
323 	if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
324 	    (me2host_pending < mbp_hdr.mbp_size)) {
325 		printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
326 		       " buffer contains %d words\n",
327 		       mbp_hdr.num_entries, mbp_hdr.mbp_size,
328 		       me2host_pending);
329 		return -1;
330 	}
331 
332 	me2host_pending--;
333 	memset(mbp_data, 0, sizeof(*mbp_data));
334 
335 	while (mbp_hdr.num_entries--) {
336 		u32 *copy_addr;
337 		u32 copy_size, buffer_room;
338 		void *p;
339 
340 		if (!me2host_pending) {
341 			printk(BIOS_ERR, "ME: no mbp data %d entries to go!\n",
342 			       mbp_hdr.num_entries + 1);
343 			return -1;
344 		}
345 
346 		mei_read_dword_ptr(&mbp_item_hdr, MEI_ME_CB_RW);
347 
348 		if (mbp_item_hdr.length > me2host_pending) {
349 			printk(BIOS_ERR, "ME: insufficient mbp data %d "
350 			       "entries to go!\n",
351 			       mbp_hdr.num_entries + 1);
352 			return -1;
353 		}
354 
355 		me2host_pending -= mbp_item_hdr.length;
356 
357 		mbp_item_id = (((u32)mbp_item_hdr.item_id) << 8) +
358 			mbp_item_hdr.app_id;
359 
360 		copy_size = mbp_item_hdr.length - 1;
361 
362 #define SET_UP_COPY(field) { copy_addr = (u32 *)&mbp_data->field;	     \
363 			buffer_room = sizeof(mbp_data->field) / sizeof(u32); \
364 			break;					             \
365 		}
366 
367 		p = &mbp_item_hdr;
368 		printk(BIOS_INFO, "ME: MBP item header %8.8x\n", *((u32*)p));
369 
370 		switch (mbp_item_id) {
371 		case 0x101:
372 			SET_UP_COPY(fw_version_name);
373 
374 		case 0x102:
375 			SET_UP_COPY(icc_profile);
376 
377 		case 0x103:
378 			SET_UP_COPY(at_state);
379 
380 		case 0x201:
381 			mbp_data->fw_caps_sku.available = 1;
382 			SET_UP_COPY(fw_caps_sku.fw_capabilities);
383 
384 		case 0x301:
385 			SET_UP_COPY(rom_bist_data);
386 
387 		case 0x401:
388 			SET_UP_COPY(platform_key);
389 
390 		case 0x501:
391 			mbp_data->fw_plat_type.available = 1;
392 			SET_UP_COPY(fw_plat_type.rule_data);
393 
394 		case 0x601:
395 			SET_UP_COPY(mfsintegrity);
396 
397 		default:
398 			printk(BIOS_ERR, "ME: unknown mbp item id 0x%x! Skipping\n",
399 			       mbp_item_id);
400 			while (copy_size--)
401 				read_cb();
402 			continue;
403 		}
404 
405 		if (buffer_room != copy_size) {
406 			printk(BIOS_ERR, "ME: buffer room %d != %d copy size"
407 			       " for item  0x%x!!!\n",
408 			       buffer_room, copy_size, mbp_item_id);
409 			return -1;
410 		}
411 		while (copy_size--)
412 			*copy_addr++ = read_cb();
413 	}
414 
415 	read_host_csr(&host);
416 	host.interrupt_generate = 1;
417 	write_host_csr(&host);
418 
419 	{
420 		int cntr = 0;
421 		while (host.interrupt_generate) {
422 			read_host_csr(&host);
423 			cntr++;
424 		}
425 		printk(BIOS_SPEW, "ME: mbp read OK after %d cycles\n", cntr);
426 	}
427 
428 	return 0;
429 }
430