mirror of
https://git.proxmox.com/git/fwupd
synced 2025-11-06 17:17:37 +00:00
The register specifications have been taken as a superset of the coreboot documentation as different flags were documented in more detail on various different platforms. Having this new data allows us to add future tests and make the current tests much easier to understand.
386 lines
13 KiB
C
386 lines
13 KiB
C
/*
|
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "fu-mei-common.h"
|
|
|
|
const gchar *
|
|
fu_mei_common_family_to_string (FuMeiFamily family)
|
|
{
|
|
if (family == FU_MEI_FAMILY_SPS)
|
|
return "SPS";
|
|
if (family == FU_MEI_FAMILY_TXE)
|
|
return "TXE";
|
|
if (family == FU_MEI_FAMILY_ME)
|
|
return "ME";
|
|
if (family == FU_MEI_FAMILY_CSME)
|
|
return "CSME";
|
|
return "AMT";
|
|
}
|
|
|
|
static gint
|
|
fu_mei_common_cmp_version (FuMeiVersion *vers1, FuMeiVersion *vers2)
|
|
{
|
|
guint16 vers1buf[] = {
|
|
vers1->major,
|
|
vers1->minor,
|
|
vers1->hotfix,
|
|
vers1->buildno,
|
|
};
|
|
guint16 vers2buf[] = {
|
|
vers2->major,
|
|
vers2->minor,
|
|
vers2->hotfix,
|
|
vers2->buildno,
|
|
};
|
|
for (guint i = 0; i < 4; i++) {
|
|
if (vers1buf[i] < vers2buf[i])
|
|
return -1;
|
|
if (vers1buf[i] > vers2buf[i])
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
FuMeiIssue
|
|
fu_mei_common_is_csme_vulnerable (FuMeiVersion *vers)
|
|
{
|
|
if (vers->major == 11 && vers->minor == 8 && vers->hotfix >= 70)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 11 && vers->minor == 11 && vers->hotfix >= 70)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 11 && vers->minor == 22 && vers->hotfix >= 70)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 12 && vers->minor == 0 && (vers->hotfix == 49 || vers->hotfix >= 56))
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 13 && vers->minor == 0 && vers->hotfix >= 21)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 14 && vers->minor == 0 && vers->hotfix >= 11)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 15)
|
|
return FU_MEI_ISSUE_NOT_VULNERABLE;
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
}
|
|
|
|
FuMeiIssue
|
|
fu_mei_common_is_txe_vulnerable (FuMeiVersion *vers)
|
|
{
|
|
if (vers->major == 3 && vers->minor == 1 && vers->hotfix >= 70)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 4 && vers->minor == 0 && vers->hotfix >= 20)
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
if (vers->major == 5)
|
|
return FU_MEI_ISSUE_NOT_VULNERABLE;
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
}
|
|
|
|
FuMeiIssue
|
|
fu_mei_common_is_sps_vulnerable (FuMeiVersion *vers)
|
|
{
|
|
if (vers->major == 3 || vers->major > 5)
|
|
return FU_MEI_ISSUE_NOT_VULNERABLE;
|
|
if (vers->major == 4) {
|
|
if (vers->hotfix < 44)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
if (vers->platform == 0xA) { /* Purley */
|
|
FuMeiVersion ver2 = {
|
|
.major = 4,
|
|
.minor = 1,
|
|
.hotfix = 4,
|
|
.buildno = 339,
|
|
};
|
|
if (fu_mei_common_cmp_version (vers, &ver2) < 0)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
} else if (vers->platform == 0xE) { /* Bakerville */
|
|
FuMeiVersion ver2 = {
|
|
.major = 4,
|
|
.minor = 0,
|
|
.hotfix = 4,
|
|
.buildno = 112,
|
|
};
|
|
if (fu_mei_common_cmp_version (vers, &ver2) < 0)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
} else if (vers->platform == 0xB) { /* Harrisonville */
|
|
FuMeiVersion ver2 = {
|
|
.major = 4,
|
|
.minor = 0,
|
|
.hotfix = 4,
|
|
.buildno = 193,
|
|
};
|
|
if (fu_mei_common_cmp_version (vers, &ver2) < 0)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
} else if (vers->platform == 0x9) { /* Greenlow */
|
|
FuMeiVersion ver2 = {
|
|
.major = 4,
|
|
.minor = 1,
|
|
.hotfix = 4,
|
|
.buildno = 88,
|
|
};
|
|
if (vers->minor < 1)
|
|
return FU_MEI_ISSUE_NOT_VULNERABLE;
|
|
if (fu_mei_common_cmp_version (vers, &ver2) < 0)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
} else if (vers->platform == 0xD) { /* MonteVista */
|
|
FuMeiVersion ver2 = {
|
|
.major = 4,
|
|
.minor = 8,
|
|
.hotfix = 4,
|
|
.buildno = 51,
|
|
};
|
|
if (fu_mei_common_cmp_version (vers, &ver2) < 0)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
}
|
|
return FU_MEI_ISSUE_NOT_VULNERABLE;
|
|
}
|
|
if (vers->major == 5) {
|
|
if (vers->platform == 0x10) { /* Mehlow */
|
|
FuMeiVersion ver2 = { 5, 1, 3, 89 };
|
|
if (fu_mei_common_cmp_version (vers, &ver2) < 0)
|
|
return FU_MEI_ISSUE_VULNERABLE;
|
|
}
|
|
return FU_MEI_ISSUE_NOT_VULNERABLE;
|
|
}
|
|
return FU_MEI_ISSUE_PATCHED;
|
|
}
|
|
|
|
/* HFS1[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",
|
|
[ME_HFS_CWS_TEST] = "test",
|
|
[ME_HFS_CWS_DISABLED] = "disabled",
|
|
[ME_HFS_CWS_NORMAL] = "normal",
|
|
[ME_HFS_CWS_WAIT] = "wait",
|
|
[ME_HFS_CWS_TRANS] = "transition",
|
|
[ME_HFS_CWS_INVALID] = "invalid",
|
|
};
|
|
|
|
/* HFS1[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] = "error",
|
|
};
|
|
|
|
/* HFS[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] = "disable",
|
|
[ME_HFS_MODE_OVER_JMPR] = "override-jumper",
|
|
[ME_HFS_MODE_OVER_MEI] = "override-mei",
|
|
[ME_HFS_MODE_UNKNOWN_6] = "unknown-6",
|
|
[ME_HFS_MODE_MAYBE_SPS] = "maybe-sps",
|
|
};
|
|
|
|
/* HFS[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_DISABLED] = "disabled",
|
|
[ME_HFS_ERROR_IMAGE] = "image-failure",
|
|
[ME_HFS_ERROR_DEBUG] = "debug-failure",
|
|
};
|
|
|
|
void
|
|
fu_mei_hfsts1_to_string (FuMeiHfsts1 hfsts1, guint idt, GString *str)
|
|
{
|
|
fu_common_string_append_kv (str, idt, "WorkingState",
|
|
me_cws_values[hfsts1.fields.working_state]);
|
|
fu_common_string_append_kb (str, idt, "MfgMode",
|
|
hfsts1.fields.mfg_mode);
|
|
fu_common_string_append_kb (str, idt, "FptBad",
|
|
hfsts1.fields.fpt_bad);
|
|
fu_common_string_append_kv (str, idt, "OperationState",
|
|
me_opstate_values[hfsts1.fields.operation_state]);
|
|
fu_common_string_append_kb (str, idt, "FwInitComplete",
|
|
hfsts1.fields.fw_init_complete);
|
|
fu_common_string_append_kb (str, idt, "FtBupLdFlr",
|
|
hfsts1.fields.ft_bup_ld_flr);
|
|
fu_common_string_append_kb (str, idt, "UpdateInProgress",
|
|
hfsts1.fields.update_in_progress);
|
|
fu_common_string_append_kv (str, idt, "ErrorCode",
|
|
me_error_values[hfsts1.fields.error_code]);
|
|
fu_common_string_append_kv (str, idt, "OperationMode",
|
|
me_opmode_values[hfsts1.fields.operation_mode]);
|
|
fu_common_string_append_kx (str, idt, "ResetCount",
|
|
hfsts1.fields.reset_count);
|
|
fu_common_string_append_kb (str, idt, "BootOptions_present",
|
|
hfsts1.fields.boot_options_present);
|
|
fu_common_string_append_kb (str, idt, "BistFinished",
|
|
hfsts1.fields.bist_finished);
|
|
fu_common_string_append_kb (str, idt, "BistTestState",
|
|
hfsts1.fields.bist_test_state);
|
|
fu_common_string_append_kb (str, idt, "BistResetRequest",
|
|
hfsts1.fields.bist_reset_request);
|
|
fu_common_string_append_kx (str, idt, "CurrentPowerSource",
|
|
hfsts1.fields.current_power_source);
|
|
fu_common_string_append_kb (str, idt, "D3SupportValid",
|
|
hfsts1.fields.d3_support_valid);
|
|
fu_common_string_append_kb (str, idt, "D0i3SupportValid",
|
|
hfsts1.fields.d0i3_support_valid);
|
|
}
|
|
|
|
void
|
|
fu_mei_hfsts2_to_string (FuMeiHfsts2 hfsts2, guint idt, GString *str)
|
|
{
|
|
fu_common_string_append_kb (str, idt, "NftpLoadFailure",
|
|
hfsts2.fields.nftp_load_failure);
|
|
fu_common_string_append_kx (str, idt, "IccProgStatus",
|
|
hfsts2.fields.icc_prog_status);
|
|
fu_common_string_append_kb (str, idt, "InvokeMebx",
|
|
hfsts2.fields.invoke_mebx);
|
|
fu_common_string_append_kb (str, idt, "CpuReplaced",
|
|
hfsts2.fields.cpu_replaced);
|
|
fu_common_string_append_kb (str, idt, "Rsvd0",
|
|
hfsts2.fields.rsvd0);
|
|
fu_common_string_append_kb (str, idt, "MfsFailure",
|
|
hfsts2.fields.mfs_failure);
|
|
fu_common_string_append_kb (str, idt, "WarmResetRqst",
|
|
hfsts2.fields.warm_reset_rqst);
|
|
fu_common_string_append_kb (str, idt, "CpuReplacedValid",
|
|
hfsts2.fields.cpu_replaced_valid);
|
|
fu_common_string_append_kb (str, idt, "LowPowerState",
|
|
hfsts2.fields.low_power_state);
|
|
fu_common_string_append_kb (str, idt, "MePowerGate",
|
|
hfsts2.fields.me_power_gate);
|
|
fu_common_string_append_kb (str, idt, "IpuNeeded",
|
|
hfsts2.fields.ipu_needed);
|
|
fu_common_string_append_kb (str, idt, "ForcedSafeBoot",
|
|
hfsts2.fields.forced_safe_boot);
|
|
fu_common_string_append_kx (str, idt, "Rsvd1",
|
|
hfsts2.fields.rsvd1);
|
|
fu_common_string_append_kb (str, idt, "ListenerChange",
|
|
hfsts2.fields.listener_change);
|
|
fu_common_string_append_kx (str, idt, "StatusData",
|
|
hfsts2.fields.status_data);
|
|
fu_common_string_append_kx (str, idt, "CurrentPmevent",
|
|
hfsts2.fields.current_pmevent);
|
|
fu_common_string_append_kx (str, idt, "Phase",
|
|
hfsts2.fields.phase);
|
|
}
|
|
|
|
void
|
|
fu_mei_hfsts3_to_string (FuMeiHfsts3 hfsts3, guint idt, GString *str)
|
|
{
|
|
fu_common_string_append_kx (str, idt, "Reserved0",
|
|
hfsts3.fields.reserved_0);
|
|
fu_common_string_append_kx (str, idt, "FwSku",
|
|
hfsts3.fields.fw_sku);
|
|
fu_common_string_append_kb (str, idt, "EncryptKeyCheck",
|
|
hfsts3.fields.encrypt_key_check);
|
|
fu_common_string_append_kb (str, idt, "PchConfigChange",
|
|
hfsts3.fields.pch_config_change);
|
|
fu_common_string_append_kx (str, idt, "Reserved9",
|
|
hfsts3.fields.reserved_9);
|
|
fu_common_string_append_kx (str, idt, "Reserved11",
|
|
hfsts3.fields.reserved_11);
|
|
fu_common_string_append_kx (str, idt, "Reserved14",
|
|
hfsts3.fields.reserved_14);
|
|
fu_common_string_append_kb (str, idt, "EncryptKeyOverride",
|
|
hfsts3.fields.encrypt_key_override);
|
|
fu_common_string_append_kb (str, idt, "PowerDownMitigation",
|
|
hfsts3.fields.power_down_mitigation);
|
|
}
|
|
|
|
void
|
|
fu_mei_hfsts4_to_string (FuMeiHfsts4 hfsts4, guint idt, GString *str)
|
|
{
|
|
fu_common_string_append_kx (str, idt, "Rsvd0",
|
|
hfsts4.fields.rsvd0);
|
|
fu_common_string_append_kb (str, idt, "EnforcementFlow",
|
|
hfsts4.fields.enforcement_flow);
|
|
fu_common_string_append_kb (str, idt, "SxResumeType",
|
|
hfsts4.fields.sx_resume_type);
|
|
fu_common_string_append_kb (str, idt, "Rsvd1",
|
|
hfsts4.fields.rsvd1);
|
|
fu_common_string_append_kb (str, idt, "TpmsDisconnected",
|
|
hfsts4.fields.tpms_disconnected);
|
|
fu_common_string_append_kb (str, idt, "Rvsd2",
|
|
hfsts4.fields.rvsd2);
|
|
fu_common_string_append_kb (str, idt, "FwstsValid",
|
|
hfsts4.fields.fwsts_valid);
|
|
fu_common_string_append_kb (str, idt, "BootGuardSelfTest",
|
|
hfsts4.fields.boot_guard_self_test);
|
|
fu_common_string_append_kx (str, idt, "Rsvd3",
|
|
hfsts4.fields.rsvd3);
|
|
}
|
|
|
|
void
|
|
fu_mei_hfsts5_to_string (FuMeiHfsts5 hfsts5, guint idt, GString *str)
|
|
{
|
|
fu_common_string_append_kb (str, idt, "AcmActive",
|
|
hfsts5.fields.acm_active);
|
|
fu_common_string_append_kb (str, idt, "Valid",
|
|
hfsts5.fields.valid);
|
|
fu_common_string_append_kb (str, idt, "ResultCodeSource",
|
|
hfsts5.fields.result_code_source);
|
|
fu_common_string_append_kx (str, idt, "ErrorStatusCode",
|
|
hfsts5.fields.error_status_code);
|
|
fu_common_string_append_kx (str, idt, "AcmDoneSts",
|
|
hfsts5.fields.acm_done_sts);
|
|
fu_common_string_append_kx (str, idt, "TimeoutCount",
|
|
hfsts5.fields.timeout_count);
|
|
fu_common_string_append_kb (str, idt, "ScrtmIndicator",
|
|
hfsts5.fields.scrtm_indicator);
|
|
fu_common_string_append_kx (str, idt, "IncBootGuardAcm",
|
|
hfsts5.fields.inc_boot_guard_acm);
|
|
fu_common_string_append_kx (str, idt, "IncKeyManifest",
|
|
hfsts5.fields.inc_key_manifest);
|
|
fu_common_string_append_kx (str, idt, "IncBootPolicy",
|
|
hfsts5.fields.inc_boot_policy);
|
|
fu_common_string_append_kx (str, idt, "Rsvd0",
|
|
hfsts5.fields.rsvd0);
|
|
fu_common_string_append_kb (str, idt, "StartEnforcement",
|
|
hfsts5.fields.start_enforcement);
|
|
}
|
|
|
|
void
|
|
fu_mei_hfsts6_to_string (FuMeiHfsts6 hfsts6, guint idt, GString *str)
|
|
{
|
|
fu_common_string_append_kb (str, idt, "ForceBootGuardAcm",
|
|
hfsts6.fields.force_boot_guard_acm);
|
|
fu_common_string_append_kb (str, idt, "CpuDebugDisable",
|
|
hfsts6.fields.cpu_debug_disable);
|
|
fu_common_string_append_kb (str, idt, "BspInitDisable",
|
|
hfsts6.fields.bsp_init_disable);
|
|
fu_common_string_append_kb (str, idt, "ProtectBiosEnv",
|
|
hfsts6.fields.protect_bios_env);
|
|
fu_common_string_append_kx (str, idt, "Rsvd0",
|
|
hfsts6.fields.rsvd0);
|
|
fu_common_string_append_kx (str, idt, "ErrorEnforcePolicy",
|
|
hfsts6.fields.error_enforce_policy);
|
|
fu_common_string_append_kb (str, idt, "MeasuredBoot",
|
|
hfsts6.fields.measured_boot);
|
|
fu_common_string_append_kb (str, idt, "VerifiedBoot",
|
|
hfsts6.fields.verified_boot);
|
|
fu_common_string_append_kx (str, idt, "BootGuardAcmsvn",
|
|
hfsts6.fields.boot_guard_acmsvn);
|
|
fu_common_string_append_kx (str, idt, "Kmsvn",
|
|
hfsts6.fields.kmsvn);
|
|
fu_common_string_append_kx (str, idt, "Bpmsvn",
|
|
hfsts6.fields.bpmsvn);
|
|
fu_common_string_append_kx (str, idt, "KeyManifestId",
|
|
hfsts6.fields.key_manifest_id);
|
|
fu_common_string_append_kb (str, idt, "BootPolicyStatus",
|
|
hfsts6.fields.boot_policy_status);
|
|
fu_common_string_append_kb (str, idt, "Error",
|
|
hfsts6.fields.error);
|
|
fu_common_string_append_kb (str, idt, "BootGuardDisable",
|
|
hfsts6.fields.boot_guard_disable);
|
|
fu_common_string_append_kb (str, idt, "FpfDisable",
|
|
hfsts6.fields.fpf_disable);
|
|
fu_common_string_append_kb (str, idt, "FpfSocLock",
|
|
hfsts6.fields.fpf_soc_lock);
|
|
fu_common_string_append_kb (str, idt, "TxtSupport",
|
|
hfsts6.fields.txt_support);
|
|
}
|