summaryrefslogtreecommitdiff
path: root/src/soc/intel/skylake
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/skylake')
-rw-r--r--src/soc/intel/skylake/Makefile.inc3
-rw-r--r--src/soc/intel/skylake/include/soc/me.h92
-rw-r--r--src/soc/intel/skylake/me.c683
-rw-r--r--src/soc/intel/skylake/me_status.c324
4 files changed, 771 insertions, 331 deletions
diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc
index ccd38abf0d..bf429ef902 100644
--- a/src/soc/intel/skylake/Makefile.inc
+++ b/src/soc/intel/skylake/Makefile.inc
@@ -36,6 +36,7 @@ romstage-y += flash_controller.c
romstage-y += gpio.c
romstage-y += memmap.c
romstage-y += monotonic_timer.c
+romstage-y += me.c
romstage-y += pch.c
romstage-y += pcr.c
romstage-y += pei_data.c
@@ -59,7 +60,7 @@ ramstage-y += i2c.c
ramstage-y += igd.c
ramstage-y += irq.c
ramstage-y += lpc.c
-ramstage-y += me_status.c
+ramstage-y += me.c
ramstage-y += memmap.c
ramstage-y += monotonic_timer.c
ramstage-$(CONFIG_PLATFORM_USES_FSP1_1) += opregion.c
diff --git a/src/soc/intel/skylake/include/soc/me.h b/src/soc/intel/skylake/include/soc/me.h
index 423e9d10cc..8dc21c381f 100644
--- a/src/soc/intel/skylake/include/soc/me.h
+++ b/src/soc/intel/skylake/include/soc/me.h
@@ -48,7 +48,9 @@
#define ME_HFS_POWER_SOURCE_AC 1
#define ME_HFS_POWER_SOURCE_DC 2
-struct me_hfs {
+union me_hfs {
+ u32 data;
+ struct {
u32 working_state: 4;
u32 mfg_mode: 1;
u32 fpt_bad: 1;
@@ -66,7 +68,8 @@ struct me_hfs {
u32 current_power_source: 2;
u32 d3_support_valid: 1;
u32 d0i3_support_valid: 1;
-} __attribute__ ((packed));
+ } __attribute__ ((packed)) fields;
+};
#define PCI_ME_HFSTS2 0x48
/* Infrastructure Progress Values */
@@ -145,7 +148,9 @@ struct me_hfs {
#define ME_HFS2_PMEVENT_CM3_CM3PG 0xe
#define ME_HFS2_PMEVENT_CM0PG_CM0 0xf
-struct me_hfs2 {
+union me_hfs2 {
+ u32 data;
+ struct {
u32 reserved1: 3;
u32 invoke_mebx: 1;
u32 cpu_replaced_sts: 1;
@@ -161,13 +166,16 @@ struct me_hfs2 {
u32 current_state: 8;
u32 current_pmevent: 4;
u32 progress_code: 4;
-} __attribute__ ((packed));
+ } __attribute__ ((packed)) fields;
+};
#define PCI_ME_HFSTS3 0x60
#define ME_HFS3_FW_SKU_CONSUMER 0x2
#define ME_HFS3_FW_SKU_CORPORATE 0x3
-struct me_hfs3 {
+union me_hfs3 {
+ u32 data;
+ struct {
u32 reserved1: 4;
u32 fw_sku: 3;
u32 encrypt_key_check: 1;
@@ -175,8 +183,80 @@ struct me_hfs3 {
u32 reserved2: 21;
u32 encrypt_key_override: 1;
u32 power_down_mitigation: 1;
-} __attribute__ ((packed));
+ } __attribute__ ((packed)) fields;
+};
+
+/*
+ * Management Engine MMIO registers
+ */
+#define MMIO_ME_CB_WW 0x00
+#define MMIO_HOST_CSR 0x04
+
+union host_csr {
+ u32 data;
+ struct {
+ u32 int_en: 1;
+ u32 int_sts: 1;
+ u32 int_gen: 1;
+ u32 host_ready: 1;
+ u32 host_reset: 1;
+ u32 rsv: 3;
+ u32 host_read_offset: 8;
+ u32 host_write_offset: 8;
+ u32 me_cir_depth: 8;
+ } __attribute__ ((packed)) fields;
+};
+
+#define MMIO_ME_CB_RW 0x08
+#define MMIO_ME_CSR 0x0C
+
+union me_csr {
+ u32 data;
+ struct {
+ u32 int_en: 1;
+ u32 int_sts: 1;
+ u32 int_gen: 1;
+ u32 host_ready: 1;
+ u32 host_reset: 1;
+ u32 rsv: 3;
+ u32 me_read_offset: 8;
+ u32 me_write_offset: 8;
+ u32 me_cir_buff: 8;
+ } __attribute__ ((packed)) fields;
+};
+
+#define MMIO_ME_D0I3 0x800
+
+/* Reset Request */
+#define MKHI_GLOBAL_RESET 0x0b
+
+#define GR_ORIGIN_BIOS_MEM_INIT 0x01
+#define GR_ORIGIN_BIOS_POST 0x02
+#define GR_ORIGIN_MEBX 0x03
+
+#define GLOBAL_RST_TYPE 0x01
+
+#define BIOS_HOST_ADD 0x00
+#define HECI_MKHI_ADD 0x07
+
+#define MAX_HECI_MESSAGE 5
+#define HECI_TIMEOUT 15000000 /* 15sec */
+#define HECI_SEND_TIMEOUT 5000000 /* 5sec */
+#define HECI_READ_TIMEOUT 5000000 /* 5sec */
+#define HECI_DELAY 1000 /* 1ms */
+
+union mei_header {
+ u32 data;
+ struct {
+ u32 client_address: 8;
+ u32 host_address: 8;
+ u32 length: 9;
+ u32 reserved: 6;
+ u32 is_complete: 1;
+ } __attribute__ ((packed)) fields;
+};
void intel_me_status(void);
+int send_global_reset(void);
#endif
diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c
new file mode 100644
index 0000000000..2f94123374
--- /dev/null
+++ b/src/soc/intel/skylake/me.c
@@ -0,0 +1,683 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/me.h>
+#include <delay.h>
+#include <timer.h>
+
+static inline u32 me_read_config32(int offset)
+{
+ return pci_read_config32(PCH_DEV_ME, offset);
+}
+
+static inline void me_write_config32(int offset, u32 value)
+{
+ pci_write_config32(PCH_DEV_ME, offset, value);
+}
+
+static inline u32 me_read_mmio32(int offset)
+{
+ return read32((void *)(HECI1_BASE_ADDRESS + offset));
+}
+
+static inline void me_write_mmio32(u16 offset, u32 value)
+{
+ write32((void *)(HECI1_BASE_ADDRESS + offset), value);
+}
+
+/* HFSTS1[3:0] Current Working State Values */
+static const char *me_cws_values[] = {
+ [ME_HFS_CWS_RESET] = "Reset",
+ [ME_HFS_CWS_INIT] = "Initializing",
+ [ME_HFS_CWS_REC] = "Recovery",
+ [3] = "Unknown (3)",
+ [4] = "Unknown (4)",
+ [ME_HFS_CWS_NORMAL] = "Normal",
+ [ME_HFS_CWS_WAIT] = "Platform Disable Wait",
+ [ME_HFS_CWS_TRANS] = "OP State Transition",
+ [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In",
+ [9] = "Unknown (9)",
+ [10] = "Unknown (10)",
+ [11] = "Unknown (11)",
+ [12] = "Unknown (12)",
+ [13] = "Unknown (13)",
+ [14] = "Unknown (14)",
+ [15] = "Unknown (15)",
+};
+
+/* HFSTS1[8:6] Current Operation State Values */
+static const char *me_opstate_values[] = {
+ [ME_HFS_STATE_PREBOOT] = "Preboot",
+ [ME_HFS_STATE_M0_UMA] = "M0 with UMA",
+ [ME_HFS_STATE_M3] = "M3 without UMA",
+ [ME_HFS_STATE_M0] = "M0 without UMA",
+ [ME_HFS_STATE_BRINGUP] = "Bring up",
+ [ME_HFS_STATE_ERROR] = "M0 without UMA but with error"
+};
+
+/* HFSTS1[19:16] Current Operation Mode Values */
+static const char *me_opmode_values[] = {
+ [ME_HFS_MODE_NORMAL] = "Normal",
+ [ME_HFS_MODE_DEBUG] = "Debug",
+ [ME_HFS_MODE_DIS] = "Soft Temporary Disable",
+ [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper",
+ [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message"
+};
+
+/* HFSTS1[15:12] Error Code Values */
+static const char *me_error_values[] = {
+ [ME_HFS_ERROR_NONE] = "No Error",
+ [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure",
+ [ME_HFS_ERROR_IMAGE] = "Image Failure",
+ [ME_HFS_ERROR_DEBUG] = "Debug Failure"
+};
+
+/* HFSTS2[31:28] ME Progress Code */
+static const char *me_progress_values[] = {
+ [ME_HFS2_PHASE_ROM] = "ROM Phase",
+ [1] = "Unknown (1)",
+ [ME_HFS2_PHASE_UKERNEL] = "uKernel Phase",
+ [ME_HFS2_PHASE_BUP] = "BUP Phase",
+ [4] = "Unknown (4)",
+ [5] = "Unknown (5)",
+ [ME_HFS2_PHASE_HOST_COMM] = "Host Communication",
+ [7] = "Unknown (7)",
+ [8] = "Unknown (8)"
+};
+
+/* HFSTS2[27:24] Power Management Event */
+static const char *me_pmevent_values[] = {
+ [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_CM0_CM3] =
+ "CM0->CM3",
+ [ME_HFS2_PMEVENT_CM3_CM0] =
+ "CM3->CM0",
+ [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_CMX_CMOFF] =
+ "Cx/Mx->Cx/Moff",
+ [ME_HFS2_PMEVENT_CM0_CM0PG] =
+ "CM0->CM0PG",
+ [ME_HFS2_PMEVENT_CM3_CM3PG] =
+ "CM3->CM3PG",
+ [ME_HFS2_PMEVENT_CM0PG_CM0] =
+ "CM0PG->CM0"
+
+};
+
+/* Progress Code 0 states */
+static const char *me_progress_rom_values[] = {
+ [ME_HFS2_STATE_ROM_BEGIN] = "BEGIN",
+ [ME_HFS2_STATE_ROM_DISABLE] = "DISABLE"
+};
+
+/* Progress Code 1 states */
+static const char *me_progress_bup_values[] = {
+ [ME_HFS2_STATE_BUP_INIT] =
+ "Initialization starts",
+ [ME_HFS2_STATE_BUP_DIS_HOST_WAKE] =
+ "Disable the host wake event",
+ [ME_HFS2_STATE_BUP_CG_ENABLE] =
+ "Enabling CG for cset",
+ [ME_HFS2_STATE_BUP_PM_HND_EN] =
+ "Enabling PM handshaking",
+ [ME_HFS2_STATE_BUP_FLOW_DET] =
+ "Flow determination start process",
+ [ME_HFS2_STATE_BUP_PMC_PATCHING] =
+ "PMC Patching process",
+ [ME_HFS2_STATE_BUP_GET_FLASH_VSCC] =
+ "Get VSCC params",
+ [ME_HFS2_STATE_BUP_SET_FLASH_VSCC] =
+ "Set VSCC params",
+ [ME_HFS2_STATE_BUP_VSCC_ERR] =
+ "Error reading/matching the VSCC table in the descriptor",
+ [ME_HFS2_STATE_BUP_EFSS_INIT] =
+ "Initialize EFFS",
+ [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_STRAP_DIS] =
+ "EFFS says ME disabled",
+ [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_CPU_RESET_DID_TIMEOUT_MEM_MISSING] =
+ "Host error - CPU reset timeout, DID timeout, memory missing",
+ [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",
+};
+
+void intel_me_status(void)
+{
+ union me_hfs hfs;
+ union me_hfs2 hfs2;
+ union me_hfs3 hfs3;
+
+ hfs.data = me_read_config32(PCI_ME_HFSTS1);
+ hfs2.data = me_read_config32(PCI_ME_HFSTS2);
+ hfs3.data = me_read_config32(PCI_ME_HFSTS3);
+
+ /* Check Current States */
+ printk(BIOS_DEBUG, "ME: FW Partition Table : %s\n",
+ hfs.fields.fpt_bad ? "BAD" : "OK");
+ printk(BIOS_DEBUG, "ME: Bringup Loader Failure : %s\n",
+ hfs.fields.ft_bup_ld_flr ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Firmware Init Complete : %s\n",
+ hfs.fields.fw_init_complete ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n",
+ hfs.fields.mfg_mode ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Boot Options Present : %s\n",
+ hfs.fields.boot_options_present ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Update In Progress : %s\n",
+ hfs.fields.update_in_progress ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: D3 Support : %s\n",
+ hfs.fields.d3_support_valid ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: D0i3 Support : %s\n",
+ hfs.fields.d0i3_support_valid ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
+ hfs2.fields.low_power_state ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Power Gated : %s\n",
+ hfs2.fields.power_gating_ind ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: CPU Replaced : %s\n",
+ hfs2.fields.cpu_replaced_sts ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: CPU Replacement Valid : %s\n",
+ hfs2.fields.cpu_replaced_valid ? "YES" : "NO");
+ printk(BIOS_DEBUG, "ME: Current Working State : %s\n",
+ me_cws_values[hfs.fields.working_state]);
+ printk(BIOS_DEBUG, "ME: Current Operation State : %s\n",
+ me_opstate_values[hfs.fields.operation_state]);
+ printk(BIOS_DEBUG, "ME: Current Operation Mode : %s\n",
+ me_opmode_values[hfs.fields.operation_mode]);
+ printk(BIOS_DEBUG, "ME: Error Code : %s\n",
+ me_error_values[hfs.fields.error_code]);
+ printk(BIOS_DEBUG, "ME: Progress Phase : %s\n",
+ me_progress_values[hfs2.fields.progress_code]);
+ printk(BIOS_DEBUG, "ME: Power Management Event : %s\n",
+ me_pmevent_values[hfs2.fields.current_pmevent]);
+
+ printk(BIOS_DEBUG, "ME: Progress Phase State : ");
+ switch (hfs2.fields.progress_code) {
+ case ME_HFS2_PHASE_ROM: /* ROM Phase */
+ printk(BIOS_DEBUG, "%s",
+ me_progress_rom_values[hfs2.fields.current_state]);
+ break;
+
+ case ME_HFS2_PHASE_UKERNEL: /* uKernel Phase */
+ printk(BIOS_DEBUG, "0x%02x", hfs2.fields.current_state);
+ break;
+
+ case ME_HFS2_PHASE_BUP: /* Bringup Phase */
+ if (hfs2.fields.current_state < ARRAY_SIZE(me_progress_bup_values)
+ && me_progress_bup_values[hfs2.fields.current_state])
+ printk(BIOS_DEBUG, "%s",
+ me_progress_bup_values[hfs2.fields.current_state]);
+ else
+ printk(BIOS_DEBUG, "0x%02x", hfs2.fields.current_state);
+ break;
+
+ case ME_HFS2_PHASE_HOST_COMM: /* Host Communication Phase */
+ if (!hfs2.fields.current_state)
+ printk(BIOS_DEBUG, "Host communication established");
+ else
+ printk(BIOS_DEBUG, "0x%02x", hfs2.fields.current_state);
+ break;
+
+ default:
+ printk(BIOS_DEBUG, "Unknown phase: 0x%02x state: 0x%02x",
+ hfs2.fields.progress_code, hfs2.fields.current_state);
+ }
+ printk(BIOS_DEBUG, "\n");
+
+ /* Power Down Mitigation Status */
+ printk(BIOS_DEBUG, "ME: Power Down Mitigation : %s\n",
+ hfs3.fields.power_down_mitigation ? "YES" : "NO");
+
+ if (hfs3.fields.power_down_mitigation) {
+ printk(BIOS_INFO, "ME: PD Mitigation State : ");
+ if (hfs3.fields.encrypt_key_override == 1 &&
+ hfs3.fields.encrypt_key_check == 0 &&
+ hfs3.fields.pch_config_change == 0)
+ printk(BIOS_INFO, "Normal Operation");
+ else if (hfs3.fields.encrypt_key_override == 1 &&
+ hfs3.fields.encrypt_key_check == 1 &&
+ hfs3.fields.pch_config_change == 0)
+ printk(BIOS_INFO, "Issue Detected and Recovered");
+ else
+ printk(BIOS_INFO, "Issue Detected but not Recovered");
+ printk(BIOS_INFO, "\n");
+
+ printk(BIOS_DEBUG, "ME: Encryption Key Override : %s\n",
+ hfs3.fields.encrypt_key_override ? "Workaround Applied" :
+ "Unable to override");
+ printk(BIOS_DEBUG, "ME: Encryption Key Check : %s\n",
+ hfs3.fields.encrypt_key_check ? "FAIL" : "PASS");
+ printk(BIOS_DEBUG, "ME: PCH Configuration Info : %s\n",
+ hfs3.fields.pch_config_change ? "Changed" : "No Change");
+
+ printk(BIOS_DEBUG, "ME: Firmware SKU : ");
+ switch (hfs3.fields.fw_sku) {
+ case ME_HFS3_FW_SKU_CONSUMER:
+ printk(BIOS_DEBUG, "Consumer\n");
+ break;
+ case ME_HFS3_FW_SKU_CORPORATE:
+ printk(BIOS_DEBUG, "Corporate\n");
+ break;
+ default:
+ printk(BIOS_DEBUG, "Unknown (0x%x)\n", hfs3.fields.fw_sku);
+ }
+ }
+}
+
+/*
+* Aligning a byte length to length in dwords.
+*/
+static u32 get_dword_length(u32 byte_length)
+{
+ return ALIGN_UP(byte_length, sizeof(uint32_t)) / sizeof(uint32_t);
+}
+
+/*
+* Get remaining message count in dword from circular buffer based on
+* write and read offset.
+*/
+static u32 get_cb_msg_count(u32 data)
+{
+ u8 read_offset = data >> 8;
+ u8 write_offset = data >> 16;
+
+ return get_dword_length(write_offset - read_offset);
+}
+
+static int wait_heci_ready(void)
+{
+ struct stopwatch sw;
+ int timeout = 0;
+ union me_csr csr;
+
+ stopwatch_init_msecs_expire(&sw, HECI_TIMEOUT);
+ while (1) {
+ do {
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ if (csr.fields.host_ready)
+ return 0;
+ } while (!(timeout = stopwatch_expired(&sw)));
+
+ printk(BIOS_ERR, "ME_RDY bit is not set after 15 sec");
+ return -1;
+ }
+}
+
+static int wait_heci_cb_avail(u32 len)
+{
+ struct stopwatch sw;
+ union host_csr csr;
+
+ csr.data = me_read_mmio32(MMIO_HOST_CSR);
+ /*
+ * if timeout has happened, return failure as
+ * the circular buffer is not empty
+ */
+ stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);
+ /* Must have room for message and message header */
+ while (len > (get_dword_length(csr.fields.me_cir_depth) -
+ get_cb_msg_count(csr.data))) {
+ if (stopwatch_expired(&sw)) {
+ printk(BIOS_ERR,
+ "Circular Buffer never emptied within 5 sec");
+ return -1;
+ }
+ /* wait before trying again */
+ udelay(HECI_DELAY);
+ /* read HOST_CSR for next iteration */
+ csr.data = me_read_mmio32(MMIO_HOST_CSR);
+ }
+ return 0;
+}
+
+static int send_heci_packet(union mei_header *head, u32 len, u32 *payload)
+{
+ int sts;
+ int index;
+ union me_csr csr;
+ union host_csr hcsr;
+
+ /*
+ * wait until there is sufficient room in CB
+ */
+ sts = wait_heci_cb_avail(len + 1);
+ if (sts != 0)
+ return -1;
+
+ /* Write message header */
+ me_write_mmio32(MMIO_ME_CB_WW, head->data);
+
+ /* Write message body */
+ for (index = 0; index < len; index++)
+ me_write_mmio32(MMIO_ME_CB_WW, payload[index]);
+
+ /* Set Interrupt Generate bit */
+ hcsr.data = me_read_mmio32(MMIO_HOST_CSR);
+ hcsr.fields.int_gen = 1;
+ me_write_mmio32(MMIO_HOST_CSR, hcsr.data);
+
+ /* Check if ME Ready bit is set, if set to 0 then return fatal error */
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ if (csr.fields.host_ready)
+ return 0;
+ else
+ return -1;
+}
+
+static int recv_heci_packet(union mei_header *head, u32 *packet,
+ u32 *packet_size)
+{
+ union me_csr csr;
+ union host_csr hcsr;
+ int rec_msg = 0;
+ struct stopwatch sw;
+ u32 length, index;
+
+ /* Clear Interrupt Status bit */
+ hcsr.data = me_read_mmio32(MMIO_HOST_CSR);
+ hcsr.fields.int_sts = 1;
+ me_write_mmio32(MMIO_HOST_CSR, hcsr.data);
+
+ /* Check if circular buffer overflow
+ * if yes then return fatal error
+ */
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ if (get_cb_msg_count(csr.data) >
+ get_dword_length(csr.fields.me_cir_buff))
+ return -1;
+ /*
+ * if timeout has happened, return failure as
+ * the circular buffer is not empty
+ */
+ stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);
+ /* go until we got message pkt */
+ do {
+ if (stopwatch_expired(&sw)) {
+ printk(BIOS_ERR,
+ "Circular Buffer not filled within 5 sec");
+ *packet_size = 0;
+ return -1;
+ }
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ /* Read one message from HECI buffer */
+ if (get_cb_msg_count(csr.data) > 0) {
+ head->data = me_read_mmio32(MMIO_ME_CB_RW);
+ /* calculate the message length in dword */
+ length = get_dword_length(head->fields.length);
+ if (head->fields.length == 0) {
+ *packet_size = 0;
+ goto SET_IG;
+ }
+ /* Make sure, we have enough space to catch all */
+ if (head->fields.length <= *packet_size) {
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ /* get complete message into circular buffer */
+ while (length > get_cb_msg_count(csr.data)) {
+ udelay(HECI_DELAY);
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ }
+ /* here is the message */
+ for (index = 0; index < length; index++)
+ packet[index] = me_read_mmio32(MMIO_ME_CB_RW);
+
+ rec_msg = 1;
+ *packet_size = head->fields.length;
+ } else {
+ /* Too small buffer */
+ *packet_size = 0;
+ return -1;
+ }
+ }
+ } while (!rec_msg);
+
+ /*
+ * Check if ME Ready bit is set, if set to 0 then return fatal error
+ * because ME might have reset during transaction and we might have
+ * read a junk data from CB
+ */
+ csr.data = me_read_mmio32(MMIO_ME_CSR);
+ if (!(csr.fields.host_ready))
+ return -1;
+SET_IG:
+ /* Set Interrupt Generate bit */
+ hcsr.data = me_read_mmio32(MMIO_HOST_CSR);
+ hcsr.fields.int_gen = 1;
+ me_write_mmio32(MMIO_HOST_CSR, hcsr.data);
+ return 0;
+}
+
+static int
+send_heci_message(void *msg, int len, u8 hostaddress, u8 clientaddress)
+{
+ u8 retry;
+ int status = -1;
+ u32 cir_buff_depth;
+ union host_csr csr;
+ union mei_header head;
+ int cur = 0;
+ u32 slength, rlength;
+
+ for (retry = 0; retry < MAX_HECI_MESSAGE; retry++) {
+ if (wait_heci_ready() != 0)
+ continue;
+ /* HECI is ready */
+ csr.data = me_read_mmio32(MMIO_HOST_CSR);
+ cir_buff_depth = csr.fields.me_cir_depth;
+ head.fields.client_address = clientaddress;
+ head.fields.host_address = hostaddress;
+ while (len > cur) {
+ rlength = get_dword_length(len - cur);
+ /*
+ * Set the message complete bit if this is last packet
+ * in message needs to be "less than" to account for
+ * the header OR needs to be exact equal to CB depth
+ */
+ if (rlength <= cir_buff_depth)
+ head.fields.is_complete = 1;
+ else
+ head.fields.is_complete = 0;
+ /*
+ * calculate length for message header
+ * header length = smaller of CB buffer or
+ * remaining message
+ */
+ slength = ((cir_buff_depth <= rlength)
+ ? ((cir_buff_depth - 1) * 4)
+ : (len - cur));
+ head.fields.length = slength;
+ head.fields.reserved = 0;
+ /*
+ * send the current packet
+ * (cur should be treated as index for message)
+ */
+ status = send_heci_packet(&head,
+ get_dword_length(head.fields.length), msg);
+ if (status != 0)
+ break;
+ /* update the length information */
+ cur += slength;
+ msg += cur;
+ }
+ if (!status)
+ break;
+ }
+ return status;
+}
+
+static int
+recv_heci_message(void *message, u32 * message_size)
+{
+ union mei_header head;
+ int cur = 0;
+ u8 retry;
+ int status = -1;
+ int msg_complete = 0;
+ u32 pkt_buff;
+
+ for (retry = 0; retry < MAX_HECI_MESSAGE; retry++) {
+ if (wait_heci_ready() != 0)
+ continue;
+ /* HECI is ready */
+ while ((cur < *message_size) && (msg_complete == 0)) {
+ pkt_buff = *message_size - cur;
+ status = recv_heci_packet(&head, message + (cur >> 2),
+ &pkt_buff);
+ if (status == -1) {
+ *message_size = 0;
+ break;
+ }
+ msg_complete = head.fields.is_complete;
+ if (pkt_buff == 0) {
+ /* if not in middle of msg and msg complete bit
+ * is set then this is a valid zero length msg
+ */
+ if ((cur == 0) && (msg_complete == 1))
+ status = 0;
+ else
+ status = -1;
+ *message_size = 0;
+ break;
+ }
+ cur += pkt_buff;
+ }
+ if (!status) {
+ *message_size = cur;
+ break;
+ }
+ }
+ return status;
+}
+
+static int send_heci_reset_message(void)
+{
+ int status;
+ struct reset_reply {
+ u8 group_id;
+ u8 command;
+ u8 reserved;
+ u8 result;
+ } __attribute__ ((packed)) reply;
+ struct reset_message {
+ u8 group_id;
+ u8 cmd;
+ u8 reserved;
+ u8 result;
+ u8 req_origin;
+ u8 reset_type;
+ } __attribute__ ((packed));
+ struct reset_message msg = {
+ .cmd = MKHI_GLOBAL_RESET,
+ .req_origin = GR_ORIGIN_BIOS_POST,
+ .reset_type = GLOBAL_RST_TYPE
+ };
+ u32 reply_size;
+
+ status= send_heci_message(&msg, sizeof(msg),
+ BIOS_HOST_ADD, HECI_MKHI_ADD);
+ if (status != 0)
+ return -1;
+
+ reply_size = sizeof(reply);
+ if (recv_heci_message(&reply, &reply_size) == -1)
+ return -1;
+ /* get reply result from HECI MSG */
+ if (reply.result != 0) {
+ printk(BIOS_DEBUG, "%s: Exit with Failure\n", __func__);
+ return -1;
+ } else {
+ printk(BIOS_DEBUG, "%s: Exit with Success\n", __func__);
+ return 0;
+ }
+}
+
+int send_global_reset(void)
+{
+ int status = -1;
+ union me_hfs hfs;
+
+ /* Check ME operating mode */
+ hfs.data = me_read_config32(PCI_ME_HFSTS1);
+ if (hfs.fields.operation_mode)
+ goto ret;
+
+ /* ME should be in Normal Mode for this command */
+ status = send_heci_reset_message();
+ret:
+ return status;
+}
diff --git a/src/soc/intel/skylake/me_status.c b/src/soc/intel/skylake/me_status.c
deleted file mode 100644
index 79d4dfb7d6..0000000000
--- a/src/soc/intel/skylake/me_status.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008-2009 coresystems GmbH
- * Copyright (C) 2014 Google Inc.
- * Copyright (C) 2016 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <arch/io.h>
-#include <console/console.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <stdlib.h>
-#include <string.h>
-#include <soc/pci_devs.h>
-#include <soc/me.h>
-#include <delay.h>
-
-static inline void me_read_dword_ptr(void *ptr, int offset)
-{
- u32 dword = pci_read_config32(PCH_DEV_ME, offset);
- memcpy(ptr, &dword, sizeof(dword));
-}
-
-/* HFSTS1[3:0] Current Working State Values */
-static const char *me_cws_values[] = {
- [ME_HFS_CWS_RESET] = "Reset",
- [ME_HFS_CWS_INIT] = "Initializing",
- [ME_HFS_CWS_REC] = "Recovery",
- [3] = "Unknown (3)",
- [4] = "Unknown (4)",
- [ME_HFS_CWS_NORMAL] = "Normal",
- [ME_HFS_CWS_WAIT] = "Platform Disable Wait",
- [ME_HFS_CWS_TRANS] = "OP State Transition",
- [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In",
- [9] = "Unknown (9)",
- [10] = "Unknown (10)",
- [11] = "Unknown (11)",
- [12] = "Unknown (12)",
- [13] = "Unknown (13)",
- [14] = "Unknown (14)",
- [15] = "Unknown (15)",
-};
-
-/* HFSTS1[8:6] Current Operation State Values */
-static const char *me_opstate_values[] = {
- [ME_HFS_STATE_PREBOOT] = "Preboot",
- [ME_HFS_STATE_M0_UMA] = "M0 with UMA",
- [ME_HFS_STATE_M3] = "M3 without UMA",
- [ME_HFS_STATE_M0] = "M0 without UMA",
- [ME_HFS_STATE_BRINGUP] = "Bring up",
- [ME_HFS_STATE_ERROR] = "M0 without UMA but with error"
-};
-
-/* HFSTS1[19:16] Current Operation Mode Values */
-static const char *me_opmode_values[] = {
- [ME_HFS_MODE_NORMAL] = "Normal",
- [ME_HFS_MODE_DEBUG] = "Debug",
- [ME_HFS_MODE_DIS] = "Soft Temporary Disable",
- [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper",
- [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message"
-};
-
-/* HFSTS1[15:12] Error Code Values */
-static const char *me_error_values[] = {
- [ME_HFS_ERROR_NONE] = "No Error",
- [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure",
- [ME_HFS_ERROR_IMAGE] = "Image Failure",
- [ME_HFS_ERROR_DEBUG] = "Debug Failure"
-};
-
-/* HFSTS2[31:28] ME Progress Code */
-static const char *me_progress_values[] = {
- [ME_HFS2_PHASE_ROM] = "ROM Phase",
- [1] = "Unknown (1)",
- [ME_HFS2_PHASE_UKERNEL] = "uKernel Phase",
- [ME_HFS2_PHASE_BUP] = "BUP Phase",
- [4] = "Unknown (4)",
- [5] = "Unknown (5)",
- [ME_HFS2_PHASE_HOST_COMM] = "Host Communication",
- [7] = "Unknown (7)",
- [8] = "Unknown (8)"
-};
-
-/* HFSTS2[27:24] Power Management Event */
-static const char *me_pmevent_values[] = {
- [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_CM0_CM3] =
- "CM0->CM3",
- [ME_HFS2_PMEVENT_CM3_CM0] =
- "CM3->CM0",
- [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_CMX_CMOFF] =
- "Cx/Mx->Cx/Moff",
- [ME_HFS2_PMEVENT_CM0_CM0PG] =
- "CM0->CM0PG",
- [ME_HFS2_PMEVENT_CM3_CM3PG] =
- "CM3->CM3PG",
- [ME_HFS2_PMEVENT_CM0PG_CM0] =
- "CM0PG->CM0"
-
-};
-
-/* Progress Code 0 states */
-static const char *me_progress_rom_values[] = {
- [ME_HFS2_STATE_ROM_BEGIN] = "BEGIN",
- [ME_HFS2_STATE_ROM_DISABLE] = "DISABLE"
-};
-
-/* Progress Code 1 states */
-static const char *me_progress_bup_values[] = {
- [ME_HFS2_STATE_BUP_INIT] =
- "Initialization starts",
- [ME_HFS2_STATE_BUP_DIS_HOST_WAKE] =
- "Disable the host wake event",
- [ME_HFS2_STATE_BUP_CG_ENABLE] =
- "Enabling CG for cset",
- [ME_HFS2_STATE_BUP_PM_HND_EN] =
- "Enabling PM handshaking",
- [ME_HFS2_STATE_BUP_FLOW_DET] =
- "Flow determination start process",
- [ME_HFS2_STATE_BUP_PMC_PATCHING] =
- "PMC Patching process",
- [ME_HFS2_STATE_BUP_GET_FLASH_VSCC] =
- "Get VSCC params",
- [ME_HFS2_STATE_BUP_SET_FLASH_VSCC] =
- "Set VSCC params",
- [ME_HFS2_STATE_BUP_VSCC_ERR] =
- "Error reading/matching the VSCC table in the descriptor",
- [ME_HFS2_STATE_BUP_EFSS_INIT] =
- "Initialize EFFS",
- [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_STRAP_DIS] =
- "EFFS says ME disabled",
- [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_CPU_RESET_DID_TIMEOUT_MEM_MISSING] =
- "Host error - CPU reset timeout, DID timeout, memory missing",
- [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",
-};
-
-void intel_me_status(void)
-{
- struct me_hfs _hfs, *hfs = &_hfs;
- struct me_hfs2 _hfs2, *hfs2 = &_hfs2;
- struct me_hfs3 _hfs3, *hfs3 = &_hfs3;
-
- me_read_dword_ptr(hfs, PCI_ME_HFSTS1);
- me_read_dword_ptr(hfs2, PCI_ME_HFSTS2);
- me_read_dword_ptr(hfs3, PCI_ME_HFSTS3);
-
- /* Check Current States */
- printk(BIOS_DEBUG, "ME: FW Partition Table : %s\n",
- hfs->fpt_bad ? "BAD" : "OK");
- printk(BIOS_DEBUG, "ME: Bringup Loader Failure : %s\n",
- hfs->ft_bup_ld_flr ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Firmware Init Complete : %s\n",
- hfs->fw_init_complete ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n",
- hfs->mfg_mode ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Boot Options Present : %s\n",
- hfs->boot_options_present ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Update In Progress : %s\n",
- hfs->update_in_progress ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: D3 Support : %s\n",
- hfs->d3_support_valid ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: D0i3 Support : %s\n",
- hfs->d0i3_support_valid ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
- hfs2->low_power_state ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Power Gated : %s\n",
- hfs2->power_gating_ind ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: CPU Replaced : %s\n",
- hfs2->cpu_replaced_sts ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: CPU Replacement Valid : %s\n",
- hfs2->cpu_replaced_valid ? "YES" : "NO");
- printk(BIOS_DEBUG, "ME: Current Working State : %s\n",
- me_cws_values[hfs->working_state]);
- printk(BIOS_DEBUG, "ME: Current Operation State : %s\n",
- me_opstate_values[hfs->operation_state]);
- printk(BIOS_DEBUG, "ME: Current Operation Mode : %s\n",
- me_opmode_values[hfs->operation_mode]);
- 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[hfs2->progress_code]);
- printk(BIOS_DEBUG, "ME: Power Management Event : %s\n",
- me_pmevent_values[hfs2->current_pmevent]);
-
- printk(BIOS_DEBUG, "ME: Progress Phase State : ");
- switch (hfs2->progress_code) {
- case ME_HFS2_PHASE_ROM: /* ROM Phase */
- printk(BIOS_DEBUG, "%s",
- me_progress_rom_values[hfs2->current_state]);
- break;
-
- case ME_HFS2_PHASE_UKERNEL: /* uKernel Phase */
- printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
- break;
-
- 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[hfs2->current_state]);
- else
- printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
- break;
-
- 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", hfs2->current_state);
- break;
-
- default:
- printk(BIOS_DEBUG, "Unknown phase: 0x%02x state: 0x%02x",
- hfs2->progress_code, hfs2->current_state);
- }
- printk(BIOS_DEBUG, "\n");
-
- /* Power Down Mitigation Status */
- printk(BIOS_DEBUG, "ME: Power Down Mitigation : %s\n",
- hfs3->power_down_mitigation ? "YES" : "NO");
-
- if (hfs3->power_down_mitigation) {
- printk(BIOS_INFO, "ME: PD Mitigation State : ");
- if (hfs3->encrypt_key_override == 1 &&
- hfs3->encrypt_key_check == 0 &&
- hfs3->pch_config_change == 0)
- printk(BIOS_INFO, "Normal Operation");
- else if (hfs3->encrypt_key_override == 1 &&
- hfs3->encrypt_key_check == 1 &&
- hfs3->pch_config_change == 0)
- printk(BIOS_INFO, "Issue Detected and Recovered");
- else
- printk(BIOS_INFO, "Issue Detected but not Recovered");
- printk(BIOS_INFO, "\n");
-
- printk(BIOS_DEBUG, "ME: Encryption Key Override : %s\n",
- hfs3->encrypt_key_override ? "Workaround Applied" :
- "Unable to override");
- printk(BIOS_DEBUG, "ME: Encryption Key Check : %s\n",
- hfs3->encrypt_key_check ? "FAIL" : "PASS");
- printk(BIOS_DEBUG, "ME: PCH Configuration Info : %s\n",
- hfs3->pch_config_change ? "Changed" : "No Change");
-
- printk(BIOS_DEBUG, "ME: Firmware SKU : ");
- switch (hfs3->fw_sku) {
- case ME_HFS3_FW_SKU_CONSUMER:
- printk(BIOS_DEBUG, "Consumer\n");
- break;
- case ME_HFS3_FW_SKU_CORPORATE:
- printk(BIOS_DEBUG, "Corporate\n");
- break;
- default:
- printk(BIOS_DEBUG, "Unknown (0x%x)\n", hfs3->fw_sku);
- }
- }
-}