soc/intel/cannonlake: Dump ME f/w version and status information
At the end of device enable, print the ME f/w version number. Before resume or loading payload, dump the ME's Host Firmware Status registers. BUG=b:131437724 BRANCH=none TEST=Prints seemingly sane values on WHL and CML devices. Change-Id: Ibeb3a2a85cd84c9baa45f90f20a3dcf69f7d5646 Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/32527 Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org> Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Subrata Banik <subrata.banik@intel.com> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
fa6233daeb
commit
d93531bcc8
|
@ -43,6 +43,7 @@ ramstage-y += gspi.c
|
|||
ramstage-y += i2c.c
|
||||
ramstage-y += lockdown.c
|
||||
ramstage-y += lpc.c
|
||||
ramstage-y += me.c
|
||||
ramstage-y += memmap.c
|
||||
ramstage-y += nhlt.c
|
||||
ramstage-y += p2sb.c
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <intelblocks/tco.h>
|
||||
#include <reg_script.h>
|
||||
#include <spi-generic.h>
|
||||
#include <soc/me.h>
|
||||
#include <soc/p2sb.h>
|
||||
#include <soc/pci_devs.h>
|
||||
#include <soc/pcr_ids.h>
|
||||
|
@ -94,6 +95,8 @@ static void soc_finalize(void *unused)
|
|||
{
|
||||
printk(BIOS_DEBUG, "Finalizing chipset.\n");
|
||||
|
||||
dump_me_status();
|
||||
|
||||
pch_finalize();
|
||||
|
||||
printk(BIOS_DEBUG, "Finalizing SMM.\n");
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2019 Google LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CANNONLAKE_ME_H_
|
||||
#define _CANNONLAKE_ME_H_
|
||||
|
||||
void dump_me_status(void);
|
||||
|
||||
#endif /* _CANNONLAKE_ME_H_ */
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2019 Google LLC.
|
||||
*
|
||||
* 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 <device/pci_ops.h>
|
||||
#include <bootstate.h>
|
||||
#include <commonlib/helpers.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci.h>
|
||||
#include <intelblocks/cse.h>
|
||||
#include <soc/me.h>
|
||||
#include <soc/pci_devs.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Miscellaneous constants */
|
||||
enum {
|
||||
MKHI_GEN_GROUP_ID = 0xFF,
|
||||
MKHI_GET_FW_VERSION = 0x02,
|
||||
ME_OPMODE_NORMAL = 0x00,
|
||||
ME_WSTATE_NORMAL = 0x05,
|
||||
};
|
||||
|
||||
/* HFSTS register offsets in PCI config space */
|
||||
enum {
|
||||
PCI_ME_HFSTS1 = 0x40,
|
||||
PCI_ME_HFSTS2 = 0x48,
|
||||
PCI_ME_HFSTS3 = 0x60,
|
||||
PCI_ME_HFSTS4 = 0x64,
|
||||
PCI_ME_HFSTS5 = 0x68,
|
||||
PCI_ME_HFSTS6 = 0x6C,
|
||||
};
|
||||
|
||||
/* Host Firmware Status Register 1 */
|
||||
union hfsts1 {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint32_t working_state : 4;
|
||||
uint32_t mfg_mode : 1;
|
||||
uint32_t fpt_bad : 1;
|
||||
uint32_t operation_state : 3;
|
||||
uint32_t fw_init_complete : 1;
|
||||
uint32_t ft_bup_ld_flr : 1;
|
||||
uint32_t fw_upd_in_progress : 1;
|
||||
uint32_t error_code : 4;
|
||||
uint32_t operation_mode : 4;
|
||||
uint32_t reset_count : 4;
|
||||
uint32_t boot_options : 1;
|
||||
uint32_t rsvd0 : 1;
|
||||
uint32_t bist_state : 1;
|
||||
uint32_t bist_reset_req : 1;
|
||||
uint32_t power_source : 2;
|
||||
uint32_t reserved1 : 1;
|
||||
uint32_t d0i3_support_valid : 1;
|
||||
} __packed fields;
|
||||
};
|
||||
|
||||
/* Host Firmware Status Register 2 */
|
||||
union hfsts2 {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint32_t nftp_load_failure : 1;
|
||||
uint32_t icc_prog_status : 2;
|
||||
uint32_t invoke_mebx : 1;
|
||||
uint32_t cpu_replaced : 1;
|
||||
uint32_t rsvd0 : 1;
|
||||
uint32_t mfs_failure : 1;
|
||||
uint32_t warm_reset_rqst : 1;
|
||||
uint32_t cpu_replaced_valid : 1;
|
||||
uint32_t low_power_state : 1;
|
||||
uint32_t me_power_gate : 1;
|
||||
uint32_t ipu_needed : 1;
|
||||
uint32_t forced_safe_boot : 1;
|
||||
uint32_t rsvd1 : 2;
|
||||
uint32_t listener_change : 1;
|
||||
uint32_t status_data : 8;
|
||||
uint32_t current_pmevent : 4;
|
||||
uint32_t phase : 4;
|
||||
} __packed fields;
|
||||
};
|
||||
|
||||
/* Host Firmware Status Register 3 */
|
||||
union hfsts3 {
|
||||
uint32_t raw;
|
||||
};
|
||||
|
||||
/* Host Firmware Status Register 4 */
|
||||
union hfsts4 {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint32_t rsvd0 : 9;
|
||||
uint32_t enforcement_flow : 1;
|
||||
uint32_t sx_resume_type : 1;
|
||||
uint32_t rsvd1 : 1;
|
||||
uint32_t tpms_disconnected : 1;
|
||||
uint32_t rvsd2 : 1;
|
||||
uint32_t fwsts_valid : 1;
|
||||
uint32_t boot_guard_self_test : 1;
|
||||
uint32_t rsvd3 : 16;
|
||||
} __packed fields;
|
||||
};
|
||||
|
||||
/* Host Firmware Status Register 5 */
|
||||
union hfsts5 {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint32_t acm_active : 1;
|
||||
uint32_t valid : 1;
|
||||
uint32_t result_code_source : 1;
|
||||
uint32_t error_status_code : 5;
|
||||
uint32_t acm_done_sts : 1;
|
||||
uint32_t timeout_count : 7;
|
||||
uint32_t scrtm_indicator : 1;
|
||||
uint32_t inc_boot_guard_acm : 4;
|
||||
uint32_t inc_key_manifest : 4;
|
||||
uint32_t inc_boot_policy : 4;
|
||||
uint32_t rsvd0 : 2;
|
||||
uint32_t start_enforcement : 1;
|
||||
} __packed fields;
|
||||
};
|
||||
|
||||
/* Host Firmware Status Register 6 */
|
||||
union hfsts6 {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint32_t force_boot_guard_acm : 1;
|
||||
uint32_t cpu_debug_disable : 1;
|
||||
uint32_t bsp_init_disable : 1;
|
||||
uint32_t protect_bios_env : 1;
|
||||
uint32_t rsvd0 : 2;
|
||||
uint32_t error_enforce_policy : 2;
|
||||
uint32_t measured_boot : 1;
|
||||
uint32_t verified_boot : 1;
|
||||
uint32_t boot_guard_acmsvn : 4;
|
||||
uint32_t kmsvn : 4;
|
||||
uint32_t bpmsvn : 4;
|
||||
uint32_t key_manifest_id : 4;
|
||||
uint32_t boot_policy_status : 1;
|
||||
uint32_t error : 1;
|
||||
uint32_t boot_guard_disable : 1;
|
||||
uint32_t fpf_disable : 1;
|
||||
uint32_t fpf_soc_lock : 1;
|
||||
uint32_t txt_support : 1;
|
||||
} __packed fields;
|
||||
};
|
||||
|
||||
static uint32_t me_read_config32(int offset)
|
||||
{
|
||||
return pci_read_config32(PCH_DEV_CSE, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* From reading the documentation, this should work for both WHL and CML
|
||||
* platforms. Also, calling this function from dump_me_status() does not
|
||||
* work, as the ME does not respond and the command times out.
|
||||
*/
|
||||
static void print_me_version(void *unused)
|
||||
{
|
||||
struct mkhi_hdr {
|
||||
uint8_t group_id;
|
||||
uint8_t command :7;
|
||||
uint8_t is_resp :1;
|
||||
uint8_t rsvd;
|
||||
uint8_t result;
|
||||
} __packed;
|
||||
|
||||
struct version {
|
||||
uint16_t minor;
|
||||
uint16_t major;
|
||||
uint16_t build;
|
||||
uint16_t hotfix;
|
||||
} __packed;
|
||||
|
||||
struct fw_ver_resp {
|
||||
struct mkhi_hdr hdr;
|
||||
struct version code;
|
||||
struct version rec;
|
||||
struct version fitc;
|
||||
} __packed;
|
||||
|
||||
union hfsts1 hfsts1;
|
||||
const struct mkhi_hdr fw_ver_msg = {
|
||||
.group_id = MKHI_GEN_GROUP_ID,
|
||||
.command = MKHI_GET_FW_VERSION,
|
||||
};
|
||||
struct fw_ver_resp resp;
|
||||
size_t resp_size = sizeof(resp);
|
||||
|
||||
/* Ignore if UART debugging is disabled */
|
||||
if (!CONFIG(CONSOLE_SERIAL))
|
||||
return;
|
||||
|
||||
hfsts1.raw = me_read_config32(PCI_ME_HFSTS1);
|
||||
|
||||
/*
|
||||
* Prerequisites:
|
||||
* 1) HFSTS1 Current Working State is Normal
|
||||
* 2) HFSTS1 Current Operation Mode is Normal
|
||||
* 3) It's after DRAM INIT DONE message (taken care of by calling it
|
||||
* during ramstage
|
||||
*/
|
||||
if ((hfsts1.fields.working_state != ME_WSTATE_NORMAL) ||
|
||||
(hfsts1.fields.operation_mode != ME_OPMODE_NORMAL))
|
||||
goto fail;
|
||||
|
||||
heci_reset();
|
||||
|
||||
if (!heci_send(&fw_ver_msg, sizeof(fw_ver_msg), BIOS_HOST_ADDR,
|
||||
HECI_MKHI_ADDR))
|
||||
goto fail;
|
||||
|
||||
if (!heci_receive(&resp, &resp_size))
|
||||
goto fail;
|
||||
|
||||
if (resp.hdr.result)
|
||||
goto fail;
|
||||
|
||||
printk(BIOS_DEBUG, "ME: Version: %d.%d.%d.%d\n", resp.code.major,
|
||||
resp.code.minor, resp.code.hotfix, resp.code.build);
|
||||
return;
|
||||
|
||||
fail:
|
||||
printk(BIOS_DEBUG, "ME: Version: Unavailable\n");
|
||||
}
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_EXIT, print_me_version, NULL);
|
||||
|
||||
void dump_me_status(void)
|
||||
{
|
||||
union hfsts1 hfsts1;
|
||||
union hfsts2 hfsts2;
|
||||
union hfsts3 hfsts3;
|
||||
union hfsts4 hfsts4;
|
||||
union hfsts5 hfsts5;
|
||||
union hfsts6 hfsts6;
|
||||
|
||||
hfsts1.raw = me_read_config32(PCI_ME_HFSTS1);
|
||||
hfsts2.raw = me_read_config32(PCI_ME_HFSTS2);
|
||||
hfsts3.raw = me_read_config32(PCI_ME_HFSTS3);
|
||||
hfsts4.raw = me_read_config32(PCI_ME_HFSTS4);
|
||||
hfsts5.raw = me_read_config32(PCI_ME_HFSTS5);
|
||||
hfsts6.raw = me_read_config32(PCI_ME_HFSTS6);
|
||||
|
||||
printk(BIOS_DEBUG, "ME: HFSTS1 : 0x%08X\n",
|
||||
hfsts1.raw);
|
||||
printk(BIOS_DEBUG, "ME: HFSTS2 : 0x%08X\n",
|
||||
hfsts2.raw);
|
||||
printk(BIOS_DEBUG, "ME: HFSTS3 : 0x%08X\n",
|
||||
hfsts3.raw);
|
||||
printk(BIOS_DEBUG, "ME: HFSTS4 : 0x%08X\n",
|
||||
hfsts4.raw);
|
||||
printk(BIOS_DEBUG, "ME: HFSTS5 : 0x%08X\n",
|
||||
hfsts5.raw);
|
||||
printk(BIOS_DEBUG, "ME: HFSTS6 : 0x%08X\n",
|
||||
hfsts6.raw);
|
||||
|
||||
printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n",
|
||||
hfsts1.fields.mfg_mode ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: FW Partition Table : %s\n",
|
||||
hfsts1.fields.fpt_bad ? "BAD" : "OK");
|
||||
printk(BIOS_DEBUG, "ME: Bringup Loader Failure : %s\n",
|
||||
hfsts1.fields.ft_bup_ld_flr ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: Firmware Init Complete : %s\n",
|
||||
hfsts1.fields.fw_init_complete ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: Boot Options Present : %s\n",
|
||||
hfsts1.fields.boot_options ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: Update In Progress : %s\n",
|
||||
hfsts1.fields.fw_upd_in_progress ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: D0i3 Support : %s\n",
|
||||
hfsts1.fields.d0i3_support_valid ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
|
||||
hfsts2.fields.low_power_state ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: CPU Replaced : %s\n",
|
||||
hfsts2.fields.cpu_replaced ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: CPU Replacement Valid : %s\n",
|
||||
hfsts2.fields.cpu_replaced_valid ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: Current Working State : %u\n",
|
||||
hfsts1.fields.working_state);
|
||||
printk(BIOS_DEBUG, "ME: Current Operation State : %u\n",
|
||||
hfsts1.fields.operation_state);
|
||||
printk(BIOS_DEBUG, "ME: Current Operation Mode : %u\n",
|
||||
hfsts1.fields.operation_mode);
|
||||
printk(BIOS_DEBUG, "ME: Error Code : %u\n",
|
||||
hfsts1.fields.error_code);
|
||||
printk(BIOS_DEBUG, "ME: CPU Debug Disabled : %s\n",
|
||||
hfsts6.fields.cpu_debug_disable ? "YES" : "NO");
|
||||
printk(BIOS_DEBUG, "ME: TXT Support : %s\n",
|
||||
hfsts6.fields.txt_support ? "YES" : "NO");
|
||||
}
|
Loading…
Reference in New Issue