diff --git a/src/soc/intel/skylake/include/soc/me.h b/src/soc/intel/skylake/include/soc/me.h index e4b6abf193..590bfb722d 100644 --- a/src/soc/intel/skylake/include/soc/me.h +++ b/src/soc/intel/skylake/include/soc/me.h @@ -202,9 +202,13 @@ union me_hfs6 { } __packed fields; }; +#define MKHI_GEN_GROUP_ID 0xff + /* Reset Request */ #define MKHI_GLOBAL_RESET 0x0b +#define MKHI_GET_FW_VERSION 0x02 + #define GR_ORIGIN_BIOS_MEM_INIT 0x01 #define GR_ORIGIN_BIOS_POST 0x02 #define GR_ORIGIN_MEBX 0x03 diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c index 2569bcff00..67d7bc0362 100644 --- a/src/soc/intel/skylake/me.c +++ b/src/soc/intel/skylake/me.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -203,6 +204,79 @@ static const char * const me_progress_bup_values[] = { "M0 kernel load", }; +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; + + 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); + union me_hfs hfs; + + /* + * Print ME version only if UART debugging is enabled. Else, it takes ~1 + * second to talk to ME and get this information. + */ + if (!IS_ENABLED(CONFIG_UART_DEBUG)) + return; + + hfs.data = me_read_config32(PCI_ME_HFSTS1); + /* + * This command can be run only if: + * - Working state is normal and + * - Operation mode is normal. + */ + if ((hfs.fields.working_state != ME_HFS_CWS_NORMAL) || + (hfs.fields.operation_mode != ME_HFS_MODE_NORMAL)) + goto failed; + + if (!heci_send(&fw_ver_msg, sizeof(fw_ver_msg), BIOS_HOST_ADD, + HECI_MKHI_ADD)) + goto failed; + + if (!heci_receive(&resp, &resp_size)) + goto failed; + + if (resp.hdr.result) + goto failed; + + printk(BIOS_DEBUG, "ME: Version : %d.%d.%d.%d\n", resp.code.major, + resp.code.minor, resp.code.hotfix, resp.code.build); + return; + +failed: + printk(BIOS_DEBUG, "ME: Version : Unavailable\n"); +} +/* + * This can't be put in intel_me_status because by the time control + * reaches there, ME doesn't respond to GET_FW_VERSION command. + */ +BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_EXIT, print_me_version, NULL); + void intel_me_status(void) { union me_hfs hfs;