[coreboot] New patch to review for coreboot: 3050fca lynxpoint: Management Engine Updates

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Sat Mar 9 01:26:02 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2620

-gerrit

commit 3050fcafa5cc5b13e80c5f9a81c83824c8223b62
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Fri Nov 2 09:16:46 2012 -0500

    lynxpoint: Management Engine Updates
    
    The ME9 requirements have added some registers and changed some
    of the MBP state machine. Implement the changes found so far in
    the ME9 BWG. There were a couple of reigster renames, but the
    majority of th churn in the me.h header file is just introducing
    the data structures in the same order as the ME9 BWG.
    
    Change-Id: I51b0bb6620eff4979674ea99992ddab65a8abc18
    Signed-Off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/southbridge/intel/lynxpoint/early_me.c  |  18 +-
 src/southbridge/intel/lynxpoint/me.h        | 262 +++++++++++++++++++---------
 src/southbridge/intel/lynxpoint/me_9.x.c    | 167 ++++++++++--------
 src/southbridge/intel/lynxpoint/me_status.c | 167 +++++++++---------
 4 files changed, 369 insertions(+), 245 deletions(-)

diff --git a/src/southbridge/intel/lynxpoint/early_me.c b/src/southbridge/intel/lynxpoint/early_me.c
index 3e3c08d..e41b801 100644
--- a/src/southbridge/intel/lynxpoint/early_me.c
+++ b/src/southbridge/intel/lynxpoint/early_me.c
@@ -56,12 +56,12 @@ static inline void pci_write_dword_ptr(void *ptr, int offset)
 void intel_early_me_status(void)
 {
 	struct me_hfs hfs;
-	struct me_gmes gmes;
+	struct me_hfs2 hfs2;
 
 	pci_read_dword_ptr(&hfs, PCI_ME_HFS);
-	pci_read_dword_ptr(&gmes, PCI_ME_GMES);
+	pci_read_dword_ptr(&hfs2, PCI_ME_HFS2);
 
-	intel_me_status(&hfs, &gmes);
+	intel_me_status(&hfs, &hfs2);
 }
 
 int intel_early_me_init(void)
@@ -73,6 +73,7 @@ int intel_early_me_init(void)
 	printk(BIOS_INFO, "Intel ME early init\n");
 
 	/* Wait for ME UMA SIZE VALID bit to be set */
+	/* FIXME: ME9 BGW indicates a 5 sec poll timeout. */
 	for (count = ME_RETRY; count > 0; --count) {
 		pci_read_dword_ptr(&uma, PCI_ME_UMA);
 		if (uma.valid)
@@ -144,6 +145,13 @@ int intel_early_me_init_done(u8 status)
 
 	pci_write_dword_ptr(&did, PCI_ME_H_GS);
 
+	/*
+	 * The ME firmware does not respond with an ACK when NOMEM or ERROR
+	 * are sent.
+	 */
+	if (status == ME_INIT_STATUS_NOMEM || status == ME_INIT_STATUS_ERROR)
+		return 0;
+
 	/* Must wait for ME acknowledgement */
 	for (count = ME_RETRY; count > 0; --count) {
 		pci_read_dword_ptr(&hfs, PCI_ME_HFS);
@@ -192,7 +200,9 @@ int intel_early_me_init_done(u8 status)
 	/* Perform the requested reset */
 	if (reset) {
 		outb(reset, 0xcf9);
-		hlt();
+		while (1) {
+			hlt();
+		}
 	}
 	return -1;
 }
diff --git a/src/southbridge/intel/lynxpoint/me.h b/src/southbridge/intel/lynxpoint/me.h
index aaeb24d..57c4f24 100644
--- a/src/southbridge/intel/lynxpoint/me.h
+++ b/src/southbridge/intel/lynxpoint/me.h
@@ -97,40 +97,111 @@ struct me_uma {
 #define  ME_INIT_STATUS_SUCCESS	0
 #define  ME_INIT_STATUS_NOMEM	1
 #define  ME_INIT_STATUS_ERROR	2
+#define  ME_INIT_STATUS_SUCCESS_OTHER 3 /* SEE ME9 BWG */
 
 struct me_did {
 	u32 uma_base: 16;
-	u32 reserved: 8;
+	u32 reserved: 7;
+	u32 rapid_start: 1;
 	u32 status: 4;
 	u32 init_done: 4;
 } __attribute__ ((packed));
 
-#define PCI_ME_GMES		0x48
-#define  ME_GMES_PHASE_ROM	0
-#define  ME_GMES_PHASE_BUP	1
-#define  ME_GMES_PHASE_UKERNEL	2
-#define  ME_GMES_PHASE_POLICY	3
-#define  ME_GMES_PHASE_MODULE	4
-#define  ME_GMES_PHASE_UNKNOWN	5
-#define  ME_GMES_PHASE_HOST	6
-
-struct me_gmes {
-	u32 bist_in_prog : 1;
-	u32 icc_prog_sts : 2;
-	u32 invoke_mebx : 1;
-	u32 cpu_replaced_sts : 1;
-	u32 mbp_rdy : 1;
-	u32 mfs_failure : 1;
-	u32 warm_rst_req_for_df : 1;
-	u32 cpu_replaced_valid : 1;
-	u32 reserved_1 : 2;
-	u32 fw_upd_ipu : 1;
-	u32 reserved_2 : 4;
+/*
+ * Apparently the GMES register is renamed to HFS2 (or HFSTS2 according
+ * to ME9 BWG). Sadly the PCH EDS and the ME BWG do not match on nomenclature.
+ */
+#define PCI_ME_HFS2		0x48
+/* Infrastructure Progress Values */
+#define  ME_HFS2_PHASE_ROM		0
+#define  ME_HFS2_PHASE_BUP		1
+#define  ME_HFS2_PHASE_UKERNEL		2
+#define  ME_HFS2_PHASE_POLICY		3
+#define  ME_HFS2_PHASE_MODULE_LOAD	4
+#define  ME_HFS2_PHASE_UNKNOWN		5
+#define  ME_HFS2_PHASE_HOST_COMM	6
+/* Current State - Based on Infra Progress values. */
+/*       ROM State */
+#define  ME_HFS2_STATE_ROM_BEGIN 0
+#define  ME_HFS2_STATE_ROM_DISABLE 6
+/*       BUP State */
+#define  ME_HFS2_STATE_BUP_INIT 0
+#define  ME_HFS2_STATE_BUP_DIS_HOST_WAKE 1
+#define  ME_HFS2_STATE_BUP_FLOW_DET 4
+#define  ME_HFS2_STATE_BUP_VSCC_ERR 8
+#define  ME_HFS2_STATE_BUP_CHECK_STRAP 0xa
+#define  ME_HFS2_STATE_BUP_PWR_OK_TIMEOUT 0xb
+#define  ME_HFS2_STATE_BUP_MANUF_OVRD_STRAP 0xd
+#define  ME_HFS2_STATE_BUP_M3 0x11
+#define  ME_HFS2_STATE_BUP_M0 0x12
+#define  ME_HFS2_STATE_BUP_FLOW_DET_ERR 0x13
+#define  ME_HFS2_STATE_BUP_M3_CLK_ERR 0x15
+#define  ME_HFS2_STATE_BUP_M3_KERN_LOAD 0x18
+#define  ME_HFS2_STATE_BUP_T32_MISSING 0x1c
+#define  ME_HFS2_STATE_BUP_WAIT_DID 0x1f
+#define  ME_HFS2_STATE_BUP_WAIT_DID_FAIL 0x20
+#define  ME_HFS2_STATE_BUP_DID_NO_FAIL 0x21
+#define  ME_HFS2_STATE_BUP_ENABLE_UMA 0x22
+#define  ME_HFS2_STATE_BUP_ENABLE_UMA_ERR 0x23
+#define  ME_HFS2_STATE_BUP_SEND_DID_ACK 0x24
+#define  ME_HFS2_STATE_BUP_SEND_DID_ACK_ERR 0x25
+#define  ME_HFS2_STATE_BUP_M0_CLK 0x26
+#define  ME_HFS2_STATE_BUP_M0_CLK_ERR 0x27
+#define  ME_HFS2_STATE_BUP_TEMP_DIS 0x28
+#define  ME_HFS2_STATE_BUP_M0_KERN_LOAD 0x32
+/*       Policy Module State */
+#define  ME_HFS2_STATE_POLICY_ENTRY 0
+#define  ME_HFS2_STATE_POLICY_RCVD_S3 3
+#define  ME_HFS2_STATE_POLICY_RCVD_S4 4
+#define  ME_HFS2_STATE_POLICY_RCVD_S5 5
+#define  ME_HFS2_STATE_POLICY_RCVD_UPD 6
+#define  ME_HFS2_STATE_POLICY_RCVD_PCR 7
+#define  ME_HFS2_STATE_POLICY_RCVD_NPCR 8
+#define  ME_HFS2_STATE_POLICY_RCVD_HOST_WAKE 9
+#define  ME_HFS2_STATE_POLICY_RCVD_AC_DC 0xa
+#define  ME_HFS2_STATE_POLICY_RCVD_DID 0xb
+#define  ME_HFS2_STATE_POLICY_VSCC_NOT_FOUND 0xc
+#define  ME_HFS2_STATE_POLICY_VSCC_INVALID 0xd
+#define  ME_HFS2_STATE_POLICY_FPB_ERR 0xe
+#define  ME_HFS2_STATE_POLICY_DESCRIPTOR_ERR 0xf
+#define  ME_HFS2_STATE_POLICY_VSCC_NO_MATCH 0x10
+/* Current PM Event Values */
+#define  ME_HFS2_PMEVENT_CLEAN_MOFF_MX_WAKE 0
+#define  ME_HFS2_PMEVENT_MOFF_MX_WAKE_ERROR 1
+#define  ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET 2
+#define  ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET_ERROR 3
+#define  ME_HFS2_PMEVENT_CLEAN_ME_RESET 4
+#define  ME_HFS2_PMEVENT_ME_RESET_EXCEPTION 5
+#define  ME_HFS2_PMEVENT_PSEUDO_ME_RESET 6
+#define  ME_HFS2_PMEVENT_S0MO_SXM3 7
+#define  ME_HFS2_PMEVENT_SXM3_S0M0 8
+#define  ME_HFS2_PMEVENT_NON_PWR_CYCLE_RESET 9
+#define  ME_HFS2_PMEVENT_PWR_CYCLE_RESET_M3 0xa
+#define  ME_HFS2_PMEVENT_PWR_CYCLE_RESET_MOFF 0xb
+#define  ME_HFS2_PMEVENT_SXMX_SXMOFF 0xc
+
+struct me_hfs2 {
+	u32 bist_in_progress: 1;
+	u32 reserved1: 2;
+	u32 invoke_mebx: 1;
+	u32 cpu_replaced_sts: 1;
+	u32 mbp_rdy: 1;
+	u32 mfs_failure: 1;
+	u32 warm_reset_request: 1;
+	u32 cpu_replaced_valid: 1;
+	u32 reserved2: 4;
+	u32 mbp_cleared: 1;
+	u32 reserved3: 2;
 	u32 current_state: 8;
 	u32 current_pmevent: 4;
 	u32 progress_code: 4;
 } __attribute__ ((packed));
 
+#define PCI_ME_H_GS2		0x70
+#define   PCI_ME_MBP_GIVE_UP	0x01
+
+#define PCI_ME_H_GS3		0x74
+
 #define PCI_ME_HERES		0xbc
 #define  PCI_ME_EXT_SHA1	0x00
 #define  PCI_ME_EXT_SHA256	0x02
@@ -241,7 +312,7 @@ typedef enum {
 } me_bios_path;
 
 /* Defined in me_status.c for both romstage and ramstage */
-void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes);
+void intel_me_status(struct me_hfs *hfs, struct me_hfs2 *hfs2);
 
 #ifdef __PRE_RAM__
 void intel_early_me_status(void);
@@ -254,6 +325,47 @@ int intel_early_me_init_done(u8 status);
 void intel_me_finalize_smm(void);
 void intel_me8_finalize_smm(void);
 #endif
+
+/*
+ * ME to BIOS Payload Datastructures and definitions. The ordering of the
+ * structures follows the ordering in the ME9 BWG.
+ */
+
+#define MBP_APPID_KERNEL 1
+#define MBP_APPID_INTEL_AT 3
+#define MBP_APPID_HWA 4
+#define MBP_APPID_ICC 5
+/* Kernel items: */
+#define MBP_KERNEL_FW_VER_ITEM 1
+#define MBP_KERNEL_FW_CAP_ITEM 2
+#define MBP_KERNEL_ROM_BIST_ITEM 3
+#define MBP_KERNEL_PLAT_KEY_ITEM 4
+#define MBP_KERNEL_FW_TYPE_ITEM 5
+#define MBP_KERNEL_MFS_FAILURE_ITEM 6
+/* Intel AT items: */
+#define MBP_INTEL_AT_STATE_ITEM 1
+/* ICC Items: */
+#define MBP_ICC_PROFILE_ITEM 1
+/* HWA Items: */
+#define MBP_HWA_REQUEST_ITEM 1
+
+#define MBP_MAKE_IDENT(appid, item) ((appid << 8) | item)
+#define MBP_IDENT(appid, item) \
+	MBP_MAKE_IDENT(MBP_APPID_##appid, MBP_##appid##_##item##_ITEM)
+
+typedef  struct {
+	u32  mbp_size	 : 8;
+	u32  num_entries : 8;
+	u32  rsvd      	 : 16;
+} __attribute__ ((packed)) mbp_header;
+
+typedef struct {
+	u32  app_id  : 8;
+	u32  item_id : 8;
+	u32  length  : 8;
+	u32  rsvd    : 8;
+}  __attribute__ ((packed)) mbp_item_header;
+
 typedef struct {
 	u32       major_version  : 16;
 	u32       minor_version  : 16;
@@ -262,19 +374,10 @@ typedef struct {
 } __attribute__ ((packed)) mbp_fw_version_name;
 
 typedef struct {
-	u8        num_icc_profiles;
-	u8        icc_profile_soft_strap;
-	u8        icc_profile_index;
-	u8        reserved;
-	u32       register_lock_mask[3];
-} __attribute__ ((packed)) mbp_icc_profile;
-
-typedef struct {
 	u32  full_net		: 1;
 	u32  std_net		: 1;
 	u32  manageability	: 1;
-	u32  small_business	: 1;
-	u32  l3manageability	: 1;
+	u32  reserved_2		: 2;
 	u32  intel_at		: 1;
 	u32  intel_cls		: 1;
 	u32  reserved		: 3;
@@ -293,33 +396,6 @@ typedef struct {
 } __attribute__ ((packed)) mefwcaps_sku;
 
 typedef struct {
-	u16  lock_state		     : 1;
-	u16  authenticate_module     : 1;
-	u16  s3authentication  	     : 1;
-	u16  flash_wear_out          : 1;
-	u16  flash_variable_security : 1;
-	u16  wwan3gpresent	     : 1;
-	u16  wwan3goob		     : 1;
-	u16  reserved		     : 9;
-} __attribute__ ((packed)) tdt_state_flag;
-
-typedef struct {
-	u8           state;
-	u8           last_theft_trigger;
-	tdt_state_flag  flags;
-}  __attribute__ ((packed)) tdt_state_info;
-
-typedef struct {
-	u32  platform_target_usage_type	 : 4;
-	u32  platform_target_market_type : 2;
-	u32  super_sku			 : 1;
-	u32  reserved			 : 1;
-	u32  intel_me_fw_image_type	 : 4;
-	u32  platform_brand		 : 4;
-	u32  reserved_1			 : 16;
-}  __attribute__ ((packed)) platform_type_rule_data;
-
-typedef struct {
 	mefwcaps_sku fw_capabilities;
 	u8      available;
 } mbp_fw_caps;
@@ -335,33 +411,57 @@ typedef struct {
 } mbp_platform_key;
 
 typedef struct {
-	platform_type_rule_data rule_data;
-	u8	          available;
+	u32 mobile:		1;
+	u32 desktop:		1;
+	u32 server:		1;
+	u32 workstation:	1;
+	u32 corporate:		1;
+	u32 consumer:		1;
+	u32 regular_super_sku:	1;
+	u32 rsvd:		1;
+	u32 image_type:		4;
+	u32 brand:		4;
+	u32 rsvd1:		16;
+}  __attribute__ ((packed)) mbp_me_firmware_type;
+
+typedef struct {
+	mbp_me_firmware_type rule_data;
+	u8                   available;
 } mbp_plat_type;
 
 typedef struct {
-	mbp_fw_version_name fw_version_name;
-	mbp_fw_caps	    fw_caps_sku;
-	mbp_rom_bist_data   rom_bist_data;
-	mbp_platform_key    platform_key;
-	mbp_plat_type	    fw_plat_type;
-	mbp_icc_profile	    icc_profile;
-	tdt_state_info	    at_state;
-	u32		    mfsintegrity;
-} me_bios_payload;
+	u8        num_icc_profiles;
+	u8        icc_profile_soft_strap;
+	u8        icc_profile_index;
+	u8        reserved;
+	u32       register_lock_mask[3];
+} __attribute__ ((packed)) mbp_icc_profile;
 
-typedef  struct {
-	u32  mbp_size	 : 8;
-	u32  num_entries : 8;
-	u32  rsvd      	 : 16;
-} __attribute__ ((packed)) mbp_header;
+typedef struct {
+	u16  lock_state		     : 1;
+	u16  authenticate_module     : 1;
+	u16  s3authentication  	     : 1;
+	u16  flash_wear_out          : 1;
+	u16  flash_variable_security : 1;
+	u16  reserved		     : 11;
+} __attribute__ ((packed)) tdt_state_flag;
 
 typedef struct {
-	u32  app_id  : 8;
-	u32  item_id : 8;
-	u32  length  : 8;
-	u32  rsvd    : 8;
-}  __attribute__ ((packed)) mbp_item_header;
+	u8           state;
+	u8           last_theft_trigger;
+	tdt_state_flag  flags;
+}  __attribute__ ((packed)) tdt_state_info;
+
+typedef struct {
+	mbp_fw_version_name  fw_version_name;
+	mbp_fw_caps	     fw_caps_sku;
+	mbp_rom_bist_data    rom_bist_data;
+	mbp_platform_key     platform_key;
+	mbp_plat_type        fw_plat_type;
+	mbp_icc_profile	     icc_profile;
+	tdt_state_info	     at_state;
+	u32		     mfsintegrity;
+} me_bios_payload;
 
 struct me_fwcaps {
 	u32 id;
diff --git a/src/southbridge/intel/lynxpoint/me_9.x.c b/src/southbridge/intel/lynxpoint/me_9.x.c
index e9e5cec..12f7ab7 100644
--- a/src/southbridge/intel/lynxpoint/me_9.x.c
+++ b/src/southbridge/intel/lynxpoint/me_9.x.c
@@ -62,7 +62,7 @@ static const char *me_bios_path_values[] = {
 	[ME_DISABLE_BIOS_PATH]		= "Disable",
 	[ME_FIRMWARE_UPDATE_BIOS_PATH]	= "Firmware Update",
 };
-static int intel_me_read_mbp(me_bios_payload *mbp_data);
+static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev);
 #endif
 
 /* MMIO base address for MEI interface */
@@ -414,8 +414,6 @@ static void me_print_fwcaps(mbp_fw_caps *caps_section)
 	print_cap("Full Network manageability", cap->full_net);
 	print_cap("Regular Network manageability", cap->std_net);
 	print_cap("Manageability", cap->manageability);
-	print_cap("Small business technology", cap->small_business);
-	print_cap("Level III manageability", cap->l3manageability);
 	print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
 	print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
 	print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
@@ -533,7 +531,7 @@ static me_bios_path intel_me_path(device_t dev)
 {
 	me_bios_path path = ME_DISABLE_BIOS_PATH;
 	struct me_hfs hfs;
-	struct me_gmes gmes;
+	struct me_hfs2 hfs2;
 
 #if CONFIG_HAVE_ACPI_RESUME
 	/* S3 wake skips all MKHI messages */
@@ -543,10 +541,10 @@ static me_bios_path intel_me_path(device_t dev)
 #endif
 
 	pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
-	pci_read_dword_ptr(dev, &gmes, PCI_ME_GMES);
+	pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
 
 	/* Check and dump status */
-	intel_me_status(&hfs, &gmes);
+	intel_me_status(&hfs, &hfs2);
 
 	/* Check Current Working State */
 	switch (hfs.working_state) {
@@ -579,7 +577,7 @@ static me_bios_path intel_me_path(device_t dev)
 		path = ME_ERROR_BIOS_PATH;
 
 	/* Check if the MBP is ready */
-	if (!gmes.mbp_rdy) {
+	if (!hfs2.mbp_rdy) {
 		printk(BIOS_CRIT, "%s: mbp is not ready!\n",
 		       __FUNCTION__);
 		path = ME_ERROR_BIOS_PATH;
@@ -592,9 +590,9 @@ static me_bios_path intel_me_path(device_t dev)
 			.operation_state       = hfs.operation_state,
 			.operation_mode        = hfs.operation_mode,
 			.error_code            = hfs.error_code,
-			.progress_code         = gmes.progress_code,
-			.current_pmevent       = gmes.current_pmevent,
-			.current_state         = gmes.current_state,
+			.progress_code         = hfs2.progress_code,
+			.current_pmevent       = hfs2.current_pmevent,
+			.current_state         = hfs2.current_state,
 		};
 		elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
 		elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
@@ -698,54 +696,35 @@ static void intel_me_init(device_t dev)
 	/* Do initial setup and determine the BIOS path */
 	printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
 
-	switch (path) {
-	case ME_S3WAKE_BIOS_PATH:
+	if (path == ME_S3WAKE_BIOS_PATH) {
 		intel_me_hide(dev);
-		break;
-
-	case ME_NORMAL_BIOS_PATH:
+		return;
+	} else if (path == ME_NORMAL_BIOS_PATH) {
 		/* Validate the extend register */
-		if (intel_me_extend_valid(dev) < 0)
-			break; /* TODO: force recovery mode */
+		/* FIXME: force recovery mode on failure. */
+		intel_me_extend_valid(dev);
+	}
 
-		/* Prepare MEI MMIO interface */
-		if (intel_mei_setup(dev) < 0)
-			break;
+	/*
+	 * According to the ME9 BWG, BIOS is required to fetch MBP data in
+	 * all boot flows except S3 Resume.
+	 */
 
-		if(intel_me_read_mbp(&mbp_data))
-			break;
+	/* Prepare MEI MMIO interface */
+	if (intel_mei_setup(dev) < 0)
+		return;
 
-#if CONFIG_CHROMEOS && 0 /* DISABLED */
-		/*
-		 * Unlock ME in recovery mode.
-		 */
-		if (recovery_mode_enabled()) {
-			/* Unlock ME flash region */
-			mkhi_hmrfpo_enable();
-
-			/* Issue global reset */
-			mkhi_global_reset();
-			return;
-		}
-#endif
+	if(intel_me_read_mbp(&mbp_data, dev))
+		return;
 
 #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
-		me_print_fw_version(&mbp_data.fw_version_name);
-		me_print_fwcaps(&mbp_data.fw_caps_sku);
+	me_print_fw_version(&mbp_data.fw_version_name);
+	me_print_fwcaps(&mbp_data.fw_caps_sku);
 #endif
 
-		/*
-		 * Leave the ME unlocked in this path.
-		 * It will be locked via SMI command later.
-		 */
-		break;
-
-	case ME_ERROR_BIOS_PATH:
-	case ME_RECOVERY_BIOS_PATH:
-	case ME_DISABLE_BIOS_PATH:
-	case ME_FIRMWARE_UPDATE_BIOS_PATH:
-		break;
-	}
+	/*
+	 * Leave the ME unlocked. It will be locked via SMI command later.
+	 */
 }
 
 static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
@@ -805,22 +784,49 @@ static u32 host_to_me_words_room(void)
 		(csr.buffer_depth - 1);
 }
 #endif
+
+/*
+ * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
+ * state machine on the BIOS end doesn't match the ME's state machine.
+ */
+static void intel_me_mbp_give_up(device_t dev)
+{
+	u32 reg32;
+	struct mei_csr csr;
+
+	reg32 = PCI_ME_MBP_GIVE_UP;
+	pci_write_config32(dev, PCI_ME_H_GS3, reg32);
+	read_host_csr(&csr);
+	csr.reset = 1;
+	csr.interrupt_generate = 1;
+	write_host_csr(&csr);
+}
+
 /*
  * mbp seems to be following its own flow, let's retrieve it in a dedicated
  * function.
  */
-static int intel_me_read_mbp(me_bios_payload *mbp_data)
+static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev)
 {
 	mbp_header mbp_hdr;
 	mbp_item_header	mbp_item_hdr;
 	u32 me2host_pending;
-	u32 mbp_item_id;
+	u32 mbp_ident;
 	struct mei_csr host;
+	struct me_hfs2 hfs2;
+	int count;
+
+	pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
+
+	if (!hfs2.mbp_rdy) {
+		printk(BIOS_ERR, "ME: MBP not ready\n");
+		goto mbp_failure;
+	}
 
 	me2host_pending = me_to_host_words_pending();
 	if (!me2host_pending) {
 		printk(BIOS_ERR, "ME: no mbp data!\n");
-		return -1;
+		goto mbp_failure;
 	}
 
 	/* we know for sure that at least the header is there */
@@ -832,7 +838,7 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data)
 		       " buffer contains %d words\n",
 		       mbp_hdr.num_entries, mbp_hdr.mbp_size,
 		       me2host_pending);
-		return -1;
+		goto mbp_failure;
 	}
 
 	me2host_pending--;
@@ -846,7 +852,7 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data)
 		if (!me2host_pending) {
 			printk(BIOS_ERR, "ME: no mbp data %d entries to go!\n",
 			       mbp_hdr.num_entries + 1);
-			return -1;
+			goto mbp_failure;
 		}
 
 		mei_read_dword_ptr(&mbp_item_hdr, MEI_ME_CB_RW);
@@ -855,13 +861,13 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data)
 			printk(BIOS_ERR, "ME: insufficient mbp data %d "
 			       "entries to go!\n",
 			       mbp_hdr.num_entries + 1);
-			return -1;
+			goto mbp_failure;
 		}
 
 		me2host_pending -= mbp_item_hdr.length;
 
-		mbp_item_id = (((u32)mbp_item_hdr.item_id) << 8) +
-			mbp_item_hdr.app_id;
+		mbp_ident = MBP_MAKE_IDENT(mbp_item_hdr.app_id,
+		                           mbp_item_hdr.item_id);
 
 		copy_size = mbp_item_hdr.length - 1;
 
@@ -873,44 +879,44 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data)
 		p = &mbp_item_hdr;
 		printk(BIOS_INFO, "ME: MBP item header %8.8x\n", *((u32*)p));
 
-		switch(mbp_item_id) {
-		case 0x101:
+		switch(mbp_ident) {
+		case MBP_IDENT(KERNEL, FW_VER):
 			SET_UP_COPY(fw_version_name);
 
-		case 0x102:
+		case MBP_IDENT(ICC, PROFILE):
 			SET_UP_COPY(icc_profile);
 
-		case 0x103:
+		case MBP_IDENT(INTEL_AT, STATE):
 			SET_UP_COPY(at_state);
 
-		case 0x201:
+		case MBP_IDENT(KERNEL, FW_CAP):
 			mbp_data->fw_caps_sku.available = 1;
 			SET_UP_COPY(fw_caps_sku.fw_capabilities);
 
-		case 0x301:
+		case MBP_IDENT(KERNEL, ROM_BIST):
 			SET_UP_COPY(rom_bist_data);
 
-		case 0x401:
+		case MBP_IDENT(KERNEL, PLAT_KEY):
 			SET_UP_COPY(platform_key);
 
-		case 0x501:
+		case MBP_IDENT(KERNEL, FW_TYPE):
 			mbp_data->fw_plat_type.available = 1;
 			SET_UP_COPY(fw_plat_type.rule_data);
 
-		case 0x601:
+		case MBP_IDENT(KERNEL, MFS_FAILURE):
 			SET_UP_COPY(mfsintegrity);
 
 		default:
 			printk(BIOS_ERR, "ME: unknown mbp item id 0x%x!!!\n",
-			       mbp_item_id);
-			return -1;
+			       mbp_ident);
+			goto mbp_failure;
 		}
 
 		if (buffer_room != copy_size) {
 			printk(BIOS_ERR, "ME: buffer room %d != %d copy size"
 			       " for item  0x%x!!!\n",
-			       buffer_room, copy_size, mbp_item_id);
-			return -1;
+			       buffer_room, copy_size, mbp_ident);
+			goto mbp_failure;
 		}
 		while(copy_size--)
 			*copy_addr++ = read_cb();
@@ -920,16 +926,23 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data)
 	host.interrupt_generate = 1;
 	write_host_csr(&host);
 
-	{
-		int cntr = 0;
-		while(host.interrupt_generate) {
-			read_host_csr(&host);
-			cntr++;
-		}
-		printk(BIOS_SPEW, "ME: mbp read OK after %d cycles\n", cntr);
+	for (count = ME_RETRY; count > 0; --count) {
+		pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
+		if (hfs2.mbp_cleared)
+			break;
+		udelay(ME_DELAY);
+	}
+
+	if (count == 0) {
+		printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n");
+		intel_me_mbp_give_up(dev);
 	}
 
 	return 0;
+
+mbp_failure:
+	intel_me_mbp_give_up(dev);
+	return -1;
 }
 
 #endif /* !__SMM__ */
diff --git a/src/southbridge/intel/lynxpoint/me_status.c b/src/southbridge/intel/lynxpoint/me_status.c
index b2f38d6..1feaf7d 100644
--- a/src/southbridge/intel/lynxpoint/me_status.c
+++ b/src/southbridge/intel/lynxpoint/me_status.c
@@ -62,89 +62,89 @@ static const char *me_error_values[] = {
 	[ME_HFS_ERROR_DEBUG]	= "Debug Failure"
 };
 
-/* GMES[31:28] ME Progress Code */
+/* HFS2[31:28] ME Progress Code */
 static const char *me_progress_values[] = {
-	[ME_GMES_PHASE_ROM]	= "ROM Phase",
-	[ME_GMES_PHASE_BUP]	= "BUP Phase",
-	[ME_GMES_PHASE_UKERNEL]	= "uKernel Phase",
-	[ME_GMES_PHASE_POLICY]	= "Policy Module",
-	[ME_GMES_PHASE_MODULE]	= "Module Loading",
-	[ME_GMES_PHASE_UNKNOWN]	= "Unknown",
-	[ME_GMES_PHASE_HOST]	= "Host Communication"
+	[ME_HFS2_PHASE_ROM]		= "ROM Phase",
+	[ME_HFS2_PHASE_BUP]		= "BUP Phase",
+	[ME_HFS2_PHASE_UKERNEL]		= "uKernel Phase",
+	[ME_HFS2_PHASE_POLICY]		= "Policy Module",
+	[ME_HFS2_PHASE_MODULE_LOAD]	= "Module Loading",
+	[ME_HFS2_PHASE_UNKNOWN]		= "Unknown",
+	[ME_HFS2_PHASE_HOST_COMM]	= "Host Communication"
 };
 
-/* GMES[27:24] Power Management Event */
+/* HFS2[27:24] Power Management Event */
 static const char *me_pmevent_values[] = {
-	[0x00] = "Clean Moff->Mx wake",
-	[0x01] = "Moff->Mx wake after an error",
-	[0x02] = "Clean global reset",
-	[0x03] = "Global reset after an error",
-	[0x04] = "Clean Intel ME reset",
-	[0x05] = "Intel ME reset due to exception",
-	[0x06] = "Pseudo-global reset",
-	[0x07] = "S0/M0->Sx/M3",
-	[0x08] = "Sx/M3->S0/M0",
-	[0x09] = "Non-power cycle reset",
-	[0x0a] = "Power cycle reset through M3",
-	[0x0b] = "Power cycle reset through Moff",
-	[0x0c] = "Sx/Mx->Sx/Moff"
+	[ME_HFS2_PMEVENT_CLEAN_MOFF_MX_WAKE] = "Clean Moff->Mx wake",
+	[ME_HFS2_PMEVENT_MOFF_MX_WAKE_ERROR] = "Moff->Mx wake after an error",
+	[ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET] = "Clean global reset",
+	[ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET_ERROR] = "Global reset after an error",
+	[ME_HFS2_PMEVENT_CLEAN_ME_RESET] = "Clean Intel ME reset",
+	[ME_HFS2_PMEVENT_ME_RESET_EXCEPTION] = "Intel ME reset due to exception",
+	[ME_HFS2_PMEVENT_PSEUDO_ME_RESET] = "Pseudo-global reset",
+	[ME_HFS2_PMEVENT_S0MO_SXM3] = "S0/M0->Sx/M3",
+	[ME_HFS2_PMEVENT_SXM3_S0M0] = "Sx/M3->S0/M0",
+	[ME_HFS2_PMEVENT_NON_PWR_CYCLE_RESET] = "Non-power cycle reset",
+	[ME_HFS2_PMEVENT_PWR_CYCLE_RESET_M3] = "Power cycle reset through M3",
+	[ME_HFS2_PMEVENT_PWR_CYCLE_RESET_MOFF] = "Power cycle reset through Moff",
+	[ME_HFS2_PMEVENT_SXMX_SXMOFF] = "Sx/Mx->Sx/Moff"
 };
 
 /* Progress Code 0 states */
 static const char *me_progress_rom_values[] = {
-	[0x00] = "BEGIN",
-	[0x06] = "DISABLE"
+	[ME_HFS2_STATE_ROM_BEGIN] = "BEGIN",
+	[ME_HFS2_STATE_ROM_DISABLE] = "DISABLE"
 };
 
 /* Progress Code 1 states */
 static const char *me_progress_bup_values[] = {
-	[0x00] = "Initialization starts",
-	[0x01] = "Disable the host wake event",
-	[0x04] = "Flow determination start process",
-	[0x08] = "Error reading/matching the VSCC table in the descriptor",
-	[0x0a] = "Check to see if straps say ME DISABLED",
-	[0x0b] = "Timeout waiting for PWROK",
-	[0x0d] = "Possibly handle BUP manufacturing override strap",
-	[0x11] = "Bringup in M3",
-	[0x12] = "Bringup in M0",
-	[0x13] = "Flow detection error",
-	[0x15] = "M3 clock switching error",
-	[0x18] = "M3 kernel load",
-	[0x1c] = "T34 missing - cannot program ICC",
-	[0x1f] = "Waiting for DID BIOS message",
-	[0x20] = "Waiting for DID BIOS message failure",
-	[0x21] = "DID reported an error",
-	[0x22] = "Enabling UMA",
-	[0x23] = "Enabling UMA error",
-	[0x24] = "Sending DID Ack to BIOS",
-	[0x25] = "Sending DID Ack to BIOS error",
-	[0x26] = "Switching clocks in M0",
-	[0x27] = "Switching clocks in M0 error",
-	[0x28] = "ME in temp disable",
-	[0x32] = "M0 kernel load",
+	[ME_HFS2_STATE_BUP_INIT] = "Initialization starts",
+	[ME_HFS2_STATE_BUP_DIS_HOST_WAKE] = "Disable the host wake event",
+	[ME_HFS2_STATE_BUP_FLOW_DET] = "Flow determination start process",
+	[ME_HFS2_STATE_BUP_VSCC_ERR] = "Error reading/matching the VSCC table in the descriptor",
+	[ME_HFS2_STATE_BUP_CHECK_STRAP] = "Check to see if straps say ME DISABLED",
+	[ME_HFS2_STATE_BUP_PWR_OK_TIMEOUT] = "Timeout waiting for PWROK",
+	[ME_HFS2_STATE_BUP_MANUF_OVRD_STRAP] = "Possibly handle BUP manufacturing override strap",
+	[ME_HFS2_STATE_BUP_M3] = "Bringup in M3",
+	[ME_HFS2_STATE_BUP_M0] = "Bringup in M0",
+	[ME_HFS2_STATE_BUP_FLOW_DET_ERR] = "Flow detection error",
+	[ME_HFS2_STATE_BUP_M3_CLK_ERR] = "M3 clock switching error",
+	[ME_HFS2_STATE_BUP_M3_KERN_LOAD] = "M3 kernel load",
+	[ME_HFS2_STATE_BUP_T32_MISSING] = "T34 missing - cannot program ICC",
+	[ME_HFS2_STATE_BUP_WAIT_DID] = "Waiting for DID BIOS message",
+	[ME_HFS2_STATE_BUP_WAIT_DID_FAIL] = "Waiting for DID BIOS message failure",
+	[ME_HFS2_STATE_BUP_DID_NO_FAIL] = "DID reported no error",
+	[ME_HFS2_STATE_BUP_ENABLE_UMA] = "Enabling UMA",
+	[ME_HFS2_STATE_BUP_ENABLE_UMA_ERR] = "Enabling UMA error",
+	[ME_HFS2_STATE_BUP_SEND_DID_ACK] = "Sending DID Ack to BIOS",
+	[ME_HFS2_STATE_BUP_SEND_DID_ACK_ERR] = "Sending DID Ack to BIOS error",
+	[ME_HFS2_STATE_BUP_M0_CLK] = "Switching clocks in M0",
+	[ME_HFS2_STATE_BUP_M0_CLK_ERR] = "Switching clocks in M0 error",
+	[ME_HFS2_STATE_BUP_TEMP_DIS] = "ME in temp disable",
+	[ME_HFS2_STATE_BUP_M0_KERN_LOAD] = "M0 kernel load",
 };
 
 /* Progress Code 3 states */
 static const char *me_progress_policy_values[] = {
-	[0x00] = "Entery into Policy Module",
-	[0x03] = "Received S3 entry",
-	[0x04] = "Received S4 entry",
-	[0x05] = "Received S5 entry",
-	[0x06] = "Received UPD entry",
-	[0x07] = "Received PCR entry",
-	[0x08] = "Received NPCR entry",
-	[0x09] = "Received host wake",
-	[0x0a] = "Received AC<>DC switch",
-	[0x0b] = "Received DRAM Init Done",
-	[0x0c] = "VSCC Data not found for flash device",
-	[0x0d] = "VSCC Table is not valid",
-	[0x0e] = "Flash Partition Boundary is outside address space",
-	[0x0f] = "ME cannot access the chipset descriptor region",
-	[0x10] = "Required VSCC values for flash parts do not match",
+	[ME_HFS2_STATE_POLICY_ENTRY] = "Entery into Policy Module",
+	[ME_HFS2_STATE_POLICY_RCVD_S3] = "Received S3 entry",
+	[ME_HFS2_STATE_POLICY_RCVD_S4] = "Received S4 entry",
+	[ME_HFS2_STATE_POLICY_RCVD_S5] = "Received S5 entry",
+	[ME_HFS2_STATE_POLICY_RCVD_UPD] = "Received UPD entry",
+	[ME_HFS2_STATE_POLICY_RCVD_PCR] = "Received PCR entry",
+	[ME_HFS2_STATE_POLICY_RCVD_NPCR] = "Received NPCR entry",
+	[ME_HFS2_STATE_POLICY_RCVD_HOST_WAKE] = "Received host wake",
+	[ME_HFS2_STATE_POLICY_RCVD_AC_DC] = "Received AC<>DC switch",
+	[ME_HFS2_STATE_POLICY_RCVD_DID] = "Received DRAM Init Done",
+	[ME_HFS2_STATE_POLICY_VSCC_NOT_FOUND] = "VSCC Data not found for flash device",
+	[ME_HFS2_STATE_POLICY_VSCC_INVALID] = "VSCC Table is not valid",
+	[ME_HFS2_STATE_POLICY_FPB_ERR] = "Flash Partition Boundary is outside address space",
+	[ME_HFS2_STATE_POLICY_DESCRIPTOR_ERR] = "ME cannot access the chipset descriptor region",
+	[ME_HFS2_STATE_POLICY_VSCC_NO_MATCH] = "Required VSCC values for flash parts do not match",
 };
 #endif
 
-void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes)
+void intel_me_status(struct me_hfs *hfs, struct me_hfs2 *hfs2)
 {
 #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
 	/* Check Current States */
@@ -169,44 +169,45 @@ void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes)
 	printk(BIOS_DEBUG, "ME: Error Code              : %s\n",
 	       me_error_values[hfs->error_code]);
 	printk(BIOS_DEBUG, "ME: Progress Phase          : %s\n",
-	       me_progress_values[gmes->progress_code]);
+	       me_progress_values[hfs2->progress_code]);
 	printk(BIOS_DEBUG, "ME: Power Management Event  : %s\n",
-	       me_pmevent_values[gmes->current_pmevent]);
+	       me_pmevent_values[hfs2->current_pmevent]);
 
 	printk(BIOS_DEBUG, "ME: Progress Phase State    : ");
-	switch (gmes->progress_code) {
-	case ME_GMES_PHASE_ROM:		/* ROM Phase */
+	switch (hfs2->progress_code) {
+	case ME_HFS2_PHASE_ROM:		/* ROM Phase */
 		printk(BIOS_DEBUG, "%s",
-		       me_progress_rom_values[gmes->current_state]);
+		       me_progress_rom_values[hfs2->current_state]);
 		break;
 
-	case ME_GMES_PHASE_BUP:		/* Bringup Phase */
-		if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values)
-		    && me_progress_bup_values[gmes->current_state])
+	case ME_HFS2_PHASE_BUP:		/* Bringup Phase */
+		if (hfs2->current_state < ARRAY_SIZE(me_progress_bup_values)
+		    && me_progress_bup_values[hfs2->current_state])
 			printk(BIOS_DEBUG, "%s",
-			       me_progress_bup_values[gmes->current_state]);
+			       me_progress_bup_values[hfs2->current_state]);
 		else
-			printk(BIOS_DEBUG, "0x%02x", gmes->current_state);
+			printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
 		break;
 
-	case ME_GMES_PHASE_POLICY:	/* Policy Module Phase */
-		if (gmes->current_state < ARRAY_SIZE(me_progress_policy_values)
-		    && me_progress_policy_values[gmes->current_state])
+	case ME_HFS2_PHASE_POLICY:	/* Policy Module Phase */
+		if (hfs2->current_state < ARRAY_SIZE(me_progress_policy_values)
+		    && me_progress_policy_values[hfs2->current_state])
 			printk(BIOS_DEBUG, "%s",
-			       me_progress_policy_values[gmes->current_state]);
+			       me_progress_policy_values[hfs2->current_state]);
 		else
-			printk(BIOS_DEBUG, "0x%02x", gmes->current_state);
+			printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
 		break;
 
-	case ME_GMES_PHASE_HOST:	/* Host Communication Phase */
-		if (!gmes->current_state)
+	case ME_HFS2_PHASE_HOST_COMM:	/* Host Communication Phase */
+		if (!hfs2->current_state)
 			printk(BIOS_DEBUG, "Host communication established");
 		else
-			printk(BIOS_DEBUG, "0x%02x", gmes->current_state);
+			printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
 		break;
 
 	default:
-		printk(BIOS_DEBUG, "Unknown 0x%02x", gmes->current_state);
+		printk(BIOS_DEBUG, "Unknown phase: 0x%02x sate: 0x%02x",
+		       hfs2->progress_code, hfs2->current_state);
 	}
 	printk(BIOS_DEBUG, "\n");
 #endif



More information about the coreboot mailing list