blob: 34616698f239aa01dc4cc3ff20d713954a927ad6 [file] [log] [blame]
#!/bin/bash
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
# nocturne does not support unibuild, so the cros_config command will exit
# with error and not print a board.
readonly _BOARD="$(cros_config /fingerprint board || true)"
# TODO(b/149590275): remove once fixed
if [[ "${_BOARD}" == "bloonchipper" ]]; then
readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR
Flash protect flags: 0x0000040f wp_gpio_asserted ro_at_boot ro_now rollback_now all_now
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000000
SETVAR
)"
else
readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR
Flash protect flags: 0x0000000b wp_gpio_asserted ro_at_boot ro_now
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000004 all_now
SETVAR
)"
fi
if [[ "${_BOARD}" == "bloonchipper" ]]; then
readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED_RO="$(cat <<SETVAR
Flash protect flags: 0x0000000b wp_gpio_asserted ro_at_boot ro_now
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000004 all_now
SETVAR
)"
else
readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED_RO="${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED}"
fi
readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_DISABLED="$(cat <<SETVAR
Flash protect flags: 0x00000000
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000001 ro_at_boot
SETVAR
)"
# TODO(b/149590275): remove once fixed
if [[ "${_BOARD}" == "bloonchipper" ]]; then
readonly _FLASHPROTECT_OUTPUT_HW_WRITE_PROTECT_DISABLED_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR
Flash protect flags: 0x00000407 ro_at_boot ro_now rollback_now all_now
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000000
SETVAR
)"
else
readonly _FLASHPROTECT_OUTPUT_HW_WRITE_PROTECT_DISABLED_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR
Flash protect flags: 0x00000003 ro_at_boot ro_now
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000000
SETVAR
)"
fi
# SYSTEM_IS_LOCKED
# SYSTEM_JUMP_ENABLED
# SYSTEM_JUMPED_TO_CURRENT_IMAGE
# See https://chromium.googlesource.com/chromiumos/platform/ec/+/10fe09bf9aaf59213d141fc1d479ed259f786049/include/ec_commands.h#1865
readonly _SYSINFO_SYSTEM_IS_LOCKED_FLAGS="0x0000000d"
if [[ "${_BOARD}" == "bloonchipper" ]]; then
readonly _ROLLBACK_FLASH_OFFSET="0x20000"
else
readonly _ROLLBACK_FLASH_OFFSET="0xe0000"
fi
readonly _FP_FRAME_RAW_ACCESS_DENIED_ERROR="$(cat <<SETVAR
EC result 4 (ACCESS_DENIED)
Failed to get FP sensor frame
SETVAR
)"
readonly _FW_NAMES="rb0 rb1 rb9 dev"
readonly _FW_TYPES="ro rw"
flash_rw_firmware() {
local fw_file="${1}"
check_file_exists "${fw_file}"
flashrom --fast-verify -V -p ec:type=fp -i EC_RW -w "${fw_file}"
}
get_ectool_output_val() {
local key="${1}"
local ectool_output="${2}"
echo "${ectool_output}" | grep "${key}" | sed "s#${key}:[[:space:]]*\.*##"
}
run_ectool_cmd() {
local ectool_output
ectool_output="$(ectool --name=cros_fp "${@}")"
if [[ $? -ne 0 ]]; then
echo "Failed to run ectool cmd: ${@}"
exit 1
fi
echo "${ectool_output}"
}
run_ectool_cmd_ignoring_error() {
ectool --name=cros_fp "${@}" || true
}
add_entropy() {
run_ectool_cmd "addentropy" "${@}"
}
reboot_ec() {
# TODO(b/116396469): The reboot_ec command returns an error even on success.
run_ectool_cmd_ignoring_error "reboot_ec"
sleep 2
}
reboot_ec_to_ro() {
# TODO(b/116396469): The reboot_ec command returns an error even on success.
run_ectool_cmd_ignoring_error "reboot_ec"
sleep 0.5
run_ectool_cmd "rwsigaction" "abort"
sleep 2
}
get_raw_fpframe() {
run_ectool_cmd "fpframe" "raw"
}
check_raw_fpframe_fails() {
local stderr_output_file="$(mktemp)"
# Using sub-shell since we have "set -e" enabled
if (get_raw_fpframe 2> "${stderr_output_file}"); then
echo "Firmware should not allow getting raw fpframe"
exit 1
fi
local stderr_output="$(cat "${stderr_output_file}")"
if [[ "${stderr_output}" != "${_FP_FRAME_RAW_ACCESS_DENIED_ERROR}" ]]; then
echo "raw fpframe command returned unexpected value"
echo "stderr_output: ${stderr_output}"
exit 1
fi
}
read_from_flash() {
local output_file="${1}"
run_ectool_cmd "flashread" "${_ROLLBACK_FLASH_OFFSET}" "0x1000" "${output_file}"
}
read_from_flash_in_bootloader_mode_without_modifying_RDP_level() {
local output_file="${1}"
flash_fp_mcu --read --noremove_flash_read_protect "${output_file}"
}
read_from_flash_in_bootloader_mode_while_setting_RDP_to_level_0() {
local output_file="${1}"
flash_fp_mcu --read "${output_file}"
}
get_sysinfo_flags() {
run_ectool_cmd "sysinfo" "flags"
}
get_running_firmware_copy() {
local ectool_output
ectool_output="$(run_ectool_cmd "version")"
get_ectool_output_val "Firmware copy" "${ectool_output}"
}
_get_firmware_version() {
local fw_type="${1}"
local ectool_output
ectool_output="$(run_ectool_cmd "version")"
get_ectool_output_val "${fw_type} version" "${ectool_output}"
}
get_rw_firmware_version() {
_get_firmware_version "RW"
}
get_ro_firmware_version() {
_get_firmware_version "RO"
}
_get_rollback_info() {
run_ectool_cmd "rollbackinfo"
}
get_rollback_block_id() {
get_ectool_output_val "Rollback block id" "$(_get_rollback_info)"
}
get_rollback_min_version() {
get_ectool_output_val "Rollback min version" "$(_get_rollback_info)"
}
get_rollback_rw_version() {
get_ectool_output_val "RW rollback version" "$(_get_rollback_info)"
}
_check_rollback_matches() {
local rb_type="${1}"
local expected="${2}"
local rb_info
rb_info="$(get_rollback_${rb_type})"
if [[ "${rb_info}" != "${expected}" ]]; then
echo "Rollback ${rb_type} does not match, expected: ${expected}, actual: ${rb_info}"
exit 1
fi
}
check_rollback_block_id_matches() {
_check_rollback_matches "block_id" "${1}"
}
check_rollback_min_version_matches() {
_check_rollback_matches "min_version" "${1}"
}
check_rollback_rw_version_matches() {
_check_rollback_matches "rw_version" "${1}"
}
check_is_rollback_set_to_initial_val() {
check_rollback_block_id_matches "1"
check_rollback_min_version_matches "0"
check_rollback_rw_version_matches "0"
}
check_rollback_is_unset() {
check_rollback_block_id_matches "0"
check_rollback_min_version_matches "0"
check_rollback_rw_version_matches "0"
}
check_file_exists() {
if [[ ! -f "${1}" ]]; then
echo "Cannot find file: ${1}"
exit 1
fi
}
check_running_rw_firmware() {
local fw_copy
fw_copy="$(get_running_firmware_copy)"
if [[ "${fw_copy}" != "RW" ]]; then
echo "Not running RW copy of firmware"
exit 1
fi
}
check_running_ro_firmware() {
local fw_copy
fw_copy="$(get_running_firmware_copy)"
if [[ "${fw_copy}" != "RO" ]]; then
echo "Not running RO copy of firmware"
exit 1
fi
}
_check_has_mp_firmware_type() {
local fw_type="${1}"
local fw_version
fw_version="$(get_${fw_type}_firmware_version)"
# The MP version string is not "special", so we compare against all the
# "special" version strings and only succeed if it doesn't match any of them.
for fw_name in ${_FW_NAMES}; do
if [[ "${fw_version}" == *.${fw_name} ]]; then
echo "Not running MP ${fw_type} firmware: ${fw_version}"
exit 1
fi
done
}
check_has_mp_ro_firmware() {
_check_has_mp_firmware_type "ro"
}
check_has_mp_rw_firmware() {
_check_has_mp_firmware_type "rw"
}
# generate check_has_dev_rw_firmware/check_has_dev_ro_firmware, etc
for fw_name in ${_FW_NAMES}; do
for fw_type in ${_FW_TYPES}; do
eval "
check_has_${fw_name}_${fw_type}_firmware() {
local fw_version
fw_version=\"\$(get_${fw_type}_firmware_version)\"
if [[ \"\${fw_version}\" != *.${fw_name} ]]; then
echo \"Not running ${fw_name} ${fw_type} firmware: \${fw_version}\"
exit 1
fi
}
"
done
done
get_flashprotect_status() {
run_ectool_cmd "flashprotect"
}
enable_sw_write_protect() {
# TODO(b/116396469): The reboot_ec command returns an error even on success.
run_ectool_cmd_ignoring_error "flashprotect" "enable"
# TODO(b/116396469): "flashprotect enable" command is slow, so wait for
# it to complete before attempting to reboot.
sleep 2
reboot_ec
}
disable_sw_write_protect() {
run_ectool_cmd "flashprotect" "disable"
}
_get_hw_write_protect_state() {
local output
# NOTE: "wspw_cur" stands for "write protect switch current"
output="$(crossystem wpsw_cur)"
if [[ $? -ne 0 ]]; then
echo "Error getting hardware write protect state"
exit 1
fi
echo "${output}"
}
check_hw_write_protect_enabled() {
local output
output="$(_get_hw_write_protect_state)"
if [[ "${output}" -ne 1 ]]; then
echo "Expected HW write protect to be enabled, but it is not"
exit 1
fi
}
check_hw_write_protect_disabled() {
local output
output="$(_get_hw_write_protect_state)"
echo "output: ${output}"
if [[ "${output}" -ne 0 ]]; then
echo "Expected HW write protect to be disabled, but it is not"
exit 1
fi
}
check_hw_and_sw_write_protect_enabled() {
local output
output="$(get_flashprotect_status)"
if [[ "${output}" != "${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED}" ]]; then
echo "Incorrect flashprotect state: ${output}"
echo "Make sure HW write protect is enabled (wp_gpio_asserted)"
exit 1
fi
}
check_hw_and_sw_write_protect_enabled_ro() {
local output
output="$(get_flashprotect_status)"
if [[ "${output}" != "${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED_RO}" ]]; then
echo "Incorrect flashprotect state: ${output}"
echo "Make sure HW write protect is enabled (wp_gpio_asserted)"
exit 1
fi
}
check_hw_and_sw_write_protect_disabled() {
local output
output="$(get_flashprotect_status)"
if [[ "${output}" != "${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_DISABLED}" ]]; then
echo "Incorrect flashprotect state: ${output}"
echo "Make sure HW write protect is disabled"
exit 1
fi
}
check_hw_write_protect_disabled_and_sw_write_protect_enabled() {
local output
output="$(get_flashprotect_status)"
if [[ "${output}" != \
"${_FLASHPROTECT_OUTPUT_HW_WRITE_PROTECT_DISABLED_AND_SW_WRITE_PROTECT_ENABLED}" ]]; then
echo "Incorrect flashprotect state: ${output}"
echo "Make sure HW write protect is disabled and SW write protect is enabled"
exit 1
fi
}
check_fingerprint_task_is_running() {
run_ectool_cmd "fpinfo"
}
check_fingerprint_task_is_not_running() {
if (check_fingerprint_task_is_running) ; then
echo "Fingerprint task should not be running"
exit 1
fi
}
check_firmware_is_functional() {
run_ectool_cmd "version"
}
check_firmware_is_not_functional() {
if (check_firmware_is_functional); then
echo "Firmware should not be responding to commands"
exit 1
fi
}
check_files_match() {
cmp $1 $2
if [[ $? -ne 0 ]]; then
echo "Expected files to match, but they do not"
exit 1
fi
}
check_files_do_not_match() {
if (check_files_match); then
echo "Expected files to not match, but they do"
exit 1
fi
}
get_file_size() {
stat --printf %s "${1}"
}
check_file_size_equals_zero() {
local file_size="$(get_file_size ${1})"
if [[ "${file_size}" -ne 0 ]]; then
echo "File is not empty"
exit 1
fi
}
check_file_contains_all_0xFF_bytes() {
local tmp_file="all_0xff.bin"
local file_to_compare="$1"
local file_expected_byte_size="$2"
# create file full of zeros and then replace with 0xFF
dd if='/dev/zero' bs=1 count="${file_expected_byte_size}" | \
sed 's#\x00#\xFF#g' > "${tmp_file}"
check_files_match "${file_to_compare}" "${tmp_file}"
rm -rf "${tmp_file}"
}
check_system_is_locked() {
local flags
flags="$(get_sysinfo_flags)"
if [[ "${flags}" != "${_SYSINFO_SYSTEM_IS_LOCKED_FLAGS}" ]]; then
echo "sysinfo flags do not match. expected: "\
"${_SYSINFO_SYSTEM_IS_LOCKED_FLAGS}, actual: ${flags}"
exit 1
fi
}