Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 89 additions & 48 deletions include/dts-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -596,61 +596,102 @@ check_blobs_in_binary() {
fi
}

check_me_op_mode_hfsts1() {
# This function checks the HFSTS1, then reports to logs the ME state and
# informs DTS the ME state via return value basing on the HFSTS1 value.
# Mappings between the HFSTS1 values and the prints are done according to:
#
# * coreboot source code: https://github.com/coreboot/coreboot/blob/1879b6a34a6e93a93d691a0d9f2457d6251a17c1/src/soc/intel/skylake/me.c#L44
# The 6 and 7 values were reported by a firmware developer but not confirmed
# by any public documentation/code:
local hfsts1="$1"
if [ "$hfsts1" == "0" ]; then
echo "ME is not disabled" >>$ERR_LOG_FILE
return 0
elif [ "$hfsts1" == "2" ]; then
echo "ME is disabled (HAP/Debug Mode)" >>$ERR_LOG_FILE
return 2
elif [ "$hfsts1" == "3" ]; then
echo "ME is soft disabled (HECI)" >>$ERR_LOG_FILE
return 1
elif [ "$hfsts1" == "4" ]; then
echo "ME disabled by Security Override Jumper/FDOPS" >>$ERR_LOG_FILE
return 1
elif [ "$hfsts1" == "5" ]; then
echo "ME disabled by Security Override MEI Message/HMRFPO" >>$ERR_LOG_FILE
return 1
elif [ "$hfsts1" == "6" ]; then
echo "ME disabled by Security Override MEI Message/HMRFPO" >>$ERR_LOG_FILE
return 1
elif [ "$hfsts1" == "7" ]; then
echo "ME disabled (Enhanced Debug Mode) or runs Ignition FW" >>$ERR_LOG_FILE
return 1
else
echo "Cannot determine ME operation mode from HFSTS1 register" >>$ERR_LOG_FILE
return 3
fi
}

check_if_me_disabled() {
ME_DISABLED=0
# This function checks the ME operation mode. Depending on the result of the
# check it reports the ME mode to ERR_LOG_FILE/DTS UI and informs DTS via
# ME_DISABLED global variable.
#
# Possible ME_DISABLED values:
# 0: ME is enabled. This mode means the ME cannot be flashed or the flashing
# might cause issues.
# 1: ME is in any state other than enabled or HAP disabled. It is assumed to
# be a safe state to flash ME.
# 2: ME is HAP disabled. It is a safe state to flash ME.
# 3: ME is in unknown state. The variable ME_DISABLED should not have this
# value assigned after this function returns.
#
# Currently, there are 3 possible methods implemented. This function uses
# every method in the following order, and exits immediately after any of the
# methods detects that the ME is not in the enabled mode:
# 1. Check the HFSTS1 bits 19:16 via PCI
# 2. Check the coreboot logs for ME/CSE mode reports
# 3. Check the HFSTS1 bits 19:16 via coreboot logs
local hfsts1
ME_DISABLED="0"

if [ $BOARD_HAS_ME_REGION -eq 0 ]; then
# No ME region
ME_DISABLED=2
# No ME region declared in the board's DTS metadata, assume HAP disabled:
ME_DISABLED="2"
return
fi

# Check for the ME state using HFSTS1 via PCI:
if check_if_heci_present; then
ME_OPMODE="$(check_me_op_mode)"
if [ $ME_OPMODE == "0" ]; then
echo "ME is not disabled" >>$ERR_LOG_FILE
return
elif [ $ME_OPMODE == "2" ]; then
echo "ME is disabled (HAP/Debug Mode)" >>$ERR_LOG_FILE
ME_DISABLED=2
return
elif [ $ME_OPMODE == "3" ]; then
echo "ME is soft disabled (HECI)" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "4" ]; then
echo "ME disabled by Security Override Jumper/FDOPS" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "5" ]; then
echo "ME disabled by Security Override MEI Message/HMRFPO" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "6" ]; then
echo "ME disabled by Security Override MEI Message/HMRFPO" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "7" ]; then
echo "ME disabled (Enhanced Debug Mode) or runs Ignition FW" >>$ERR_LOG_FILE
ME_DISABLED=1
return
else
print_warning "Unknown ME operation mode, assuming enabled."
echo "Unknown ME operation mode, assuming enabled." >>$ERR_LOG_FILE
return
fi
else
# If we are running coreboot, check for status in logs
$CBMEM check_if_me_disabled_mock -1 |
grep "ME is disabled" &>/dev/null && ME_DISABLED=1 && return # HECI (soft) disabled
$CBMEM check_if_me_disabled_mock -1 |
grep "ME is HAP disabled" &>/dev/null && ME_DISABLED=2 && return # HAP disabled
# TODO: If proprietary BIOS, then also try to check SMBIOS for ME FWSTS
# BTW we could do the same in coreboot, expose FWSTS in SMBIOS before it
# gets disabled
print_warning "Can not determine if ME is disabled, assuming enabled."
echo "Can not determine if ME is disabled, assuming enabled." >>$ERR_LOG_FILE
fi
hfsts1="$(check_hfsts1_heci)"
check_me_op_mode_hfsts1 "$hfsts1"
ME_DISABLED="$?"
[ "$ME_DISABLED" != "3" ] && return
fi

# If we are running coreboot, check for status in logs. The CSE, CSME, and ME
# are interchangeable names for the same Intel technology: ME
# (https://www.intel.com/content/www/us/en/support/articles/000100063/processors.html).
# So it is ok to conclude on the ME state using the "CSE is disabled".
$CBMEM check_if_me_disabled_mock -1 |
grep "ME is HAP disabled" &>/dev/null && ME_DISABLED=2 && return # HAP disabled
$CBMEM check_if_me_disabled_mock -1 |
grep "\(CSE\|ME\) is disabled" &>/dev/null && ME_DISABLED=1 && return # HECI (soft) disabled

# Check for the ME state using HFSTS1 via coreboot logs:
hfsts1="$(check_hfsts1_cbmem)"
check_me_op_mode_hfsts1 "$hfsts1"
ME_DISABLED="$?"
[ "$ME_DISABLED" != "3" ] && return

# TODO: If proprietary BIOS, then also try to check SMBIOS for ME FWSTS
# BTW we could do the same in coreboot, expose FWSTS in SMBIOS before it
# gets disabled

print_warning "Can not determine if ME is disabled, assuming enabled."
echo "Can not determine if ME is disabled, assuming enabled." >>$ERR_LOG_FILE
ME_DISABLED="0"
return
}

force_me_update() {
Expand Down
15 changes: 14 additions & 1 deletion include/hal/common-mock-func.sh
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ ifdtool_check_blobs_in_binary_mock() {
################################################################################
TEST_ME_DISABLED="${TEST_ME_DISABLED:-true}"
TEST_ME_HAP_DISABLED="${TEST_ME_HAP_DISABLED:-}"
TEST_CSE_DISABLED="${TEST_CSE_DISABLED:-false}"

cbmem_common_mock() {
# should fail if fw is not coreboot
Expand All @@ -386,11 +387,23 @@ cbmem_check_if_me_disabled_mock() {
echo "ME is HAP disabled"
elif [ "$TEST_ME_DISABLED" = "true" ]; then
echo "ME is disabled"
elif [ "$TEST_CSE_DISABLED" = "true" ]; then
echo "CSE is disabled"
fi

return 0
}

cbmem_check_hfsts1_mock() {
[ "$TEST_IS_COREBOOT" != "true" ] && return 1

# Emulating current ME operation mode, check functions check_if_me_disabled and
# check_me_op_mode:
echo "HFSTS1 : 0x000${TEST_ME_OP_MODE}0000"

return 0
}

################################################################################
# cbfstool
################################################################################
Expand Down Expand Up @@ -725,7 +738,7 @@ fsread_tool_cat_mock() {
################################################################################
TEST_ME_OP_MODE="${TEST_ME_OP_MODE:-0}"

setpci_check_me_op_mode_mock() {
setpci_check_hfsts1_mock() {
# Emulating current ME operation mode, check functions check_if_me_disabled and
# check_me_op_mode:
echo "0$TEST_ME_OP_MODE"
Expand Down
14 changes: 12 additions & 2 deletions include/hal/dts-hal.sh
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,27 @@ check_if_heci_present() {
return $?
}

check_me_op_mode() {
check_hfsts1_heci() {
# Checks ME Current Operation Mode at offset 0x40 bits 19:16:
local _mode

_mode="$($SETPCI check_me_op_mode_mock -s 00:16.0 42.B 2>>"$ERR_LOG_FILE" | cut -c2-)"
_mode="$($SETPCI check_hfsts1_mock -s 00:16.0 42.B 2>>"$ERR_LOG_FILE" | cut -c2-)"

echo "$_mode"

return 0
}

check_hfsts1_cbmem() {
local _mode

_mode=$($CBMEM check_hfsts1_mock -1 | grep HFSTS1)

echo "${_mode: -5:-4}"

return 0
}

check_if_uefi() {
# Check if current firmware has UEFI payload. Returns 0 on success, otherwise
# returns 1.
Expand Down