1#!/bin/bash 2 3# Copyright 2019 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7set -e 8 9# nocturne does not support unibuild, so the cros_config command will exit 10# with error and not print a board. 11readonly _BOARD="$(cros_config /fingerprint board || true)" 12 13# TODO(b/149590275): remove once fixed 14if [[ "${_BOARD}" == "bloonchipper" ]]; then 15 readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR 16Flash protect flags: 0x0000040f wp_gpio_asserted ro_at_boot ro_now rollback_now all_now 17Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT 18Writable flags: 0x00000000 19SETVAR 20 )" 21else 22 readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR 23Flash protect flags: 0x0000000b wp_gpio_asserted ro_at_boot ro_now 24Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT 25Writable flags: 0x00000004 all_now 26SETVAR 27 )" 28fi 29 30if [[ "${_BOARD}" == "bloonchipper" ]]; then 31 readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED_RO="$(cat <<SETVAR 32Flash protect flags: 0x0000000b wp_gpio_asserted ro_at_boot ro_now 33Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT 34Writable flags: 0x00000004 all_now 35SETVAR 36 )" 37else 38 readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED_RO="${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED}" 39fi 40 41readonly _FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_DISABLED="$(cat <<SETVAR 42Flash protect flags: 0x00000000 43Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT 44Writable flags: 0x00000001 ro_at_boot 45SETVAR 46)" 47 48# TODO(b/149590275): remove once fixed 49if [[ "${_BOARD}" == "bloonchipper" ]]; then 50 readonly _FLASHPROTECT_OUTPUT_HW_WRITE_PROTECT_DISABLED_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR 51Flash protect flags: 0x00000407 ro_at_boot ro_now rollback_now all_now 52Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT 53Writable flags: 0x00000000 54SETVAR 55)" 56else 57 readonly _FLASHPROTECT_OUTPUT_HW_WRITE_PROTECT_DISABLED_AND_SW_WRITE_PROTECT_ENABLED="$(cat <<SETVAR 58Flash protect flags: 0x00000003 ro_at_boot ro_now 59Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT 60Writable flags: 0x00000000 61SETVAR 62 )" 63fi 64 65# SYSTEM_IS_LOCKED 66# SYSTEM_JUMP_ENABLED 67# SYSTEM_JUMPED_TO_CURRENT_IMAGE 68# See https://chromium.googlesource.com/chromiumos/platform/ec/+/10fe09bf9aaf59213d141fc1d479ed259f786049/include/ec_commands.h#1865 69readonly _SYSINFO_SYSTEM_IS_LOCKED_FLAGS="0x0000000d" 70 71if [[ "${_BOARD}" == "bloonchipper" ]]; then 72 readonly _ROLLBACK_FLASH_OFFSET="0x20000" 73else 74 readonly _ROLLBACK_FLASH_OFFSET="0xe0000" 75fi 76 77readonly _FP_FRAME_RAW_ACCESS_DENIED_ERROR="$(cat <<SETVAR 78EC result 4 (ACCESS_DENIED) 79Failed to get FP sensor frame 80SETVAR 81)" 82 83readonly _FW_NAMES="rb0 rb1 rb9 dev" 84readonly _FW_TYPES="ro rw" 85 86flash_rw_firmware() { 87 local fw_file="${1}" 88 check_file_exists "${fw_file}" 89 flashrom --fast-verify -V -p ec:type=fp -i EC_RW -w "${fw_file}" 90} 91 92get_ectool_output_val() { 93 local key="${1}" 94 local ectool_output="${2}" 95 echo "${ectool_output}" | grep "${key}" | sed "s#${key}:[[:space:]]*\.*##" 96} 97 98run_ectool_cmd() { 99 local ectool_output 100 ectool_output="$(ectool --name=cros_fp "${@}")" 101 if [[ $? -ne 0 ]]; then 102 echo "Failed to run ectool cmd: ${@}" 103 exit 1 104 fi 105 echo "${ectool_output}" 106} 107 108run_ectool_cmd_ignoring_error() { 109 ectool --name=cros_fp "${@}" || true 110} 111 112add_entropy() { 113 run_ectool_cmd "addentropy" "${@}" 114} 115 116reboot_ec() { 117 # TODO(b/116396469): The reboot_ec command returns an error even on success. 118 run_ectool_cmd_ignoring_error "reboot_ec" 119 sleep 2 120} 121 122reboot_ec_to_ro() { 123 # TODO(b/116396469): The reboot_ec command returns an error even on success. 124 run_ectool_cmd_ignoring_error "reboot_ec" 125 sleep 0.5 126 run_ectool_cmd "rwsigaction" "abort" 127 sleep 2 128} 129 130get_raw_fpframe() { 131 run_ectool_cmd "fpframe" "raw" 132} 133 134check_raw_fpframe_fails() { 135 local stderr_output_file="$(mktemp)" 136 # Using sub-shell since we have "set -e" enabled 137 if (get_raw_fpframe 2> "${stderr_output_file}"); then 138 echo "Firmware should not allow getting raw fpframe" 139 exit 1 140 fi 141 142 local stderr_output="$(cat "${stderr_output_file}")" 143 if [[ "${stderr_output}" != "${_FP_FRAME_RAW_ACCESS_DENIED_ERROR}" ]]; then 144 echo "raw fpframe command returned unexpected value" 145 echo "stderr_output: ${stderr_output}" 146 exit 1 147 fi 148} 149 150read_from_flash() { 151 local output_file="${1}" 152 run_ectool_cmd "flashread" "${_ROLLBACK_FLASH_OFFSET}" "0x1000" "${output_file}" 153} 154 155read_from_flash_in_bootloader_mode_without_modifying_RDP_level() { 156 local output_file="${1}" 157 flash_fp_mcu --read --noremove_flash_read_protect "${output_file}" 158} 159 160read_from_flash_in_bootloader_mode_while_setting_RDP_to_level_0() { 161 local output_file="${1}" 162 flash_fp_mcu --read "${output_file}" 163} 164 165 166get_sysinfo_flags() { 167 run_ectool_cmd "sysinfo" "flags" 168} 169 170get_running_firmware_copy() { 171 local ectool_output 172 ectool_output="$(run_ectool_cmd "version")" 173 get_ectool_output_val "Firmware copy" "${ectool_output}" 174} 175 176_get_firmware_version() { 177 local fw_type="${1}" 178 local ectool_output 179 ectool_output="$(run_ectool_cmd "version")" 180 get_ectool_output_val "${fw_type} version" "${ectool_output}" 181} 182 183get_rw_firmware_version() { 184 _get_firmware_version "RW" 185} 186 187get_ro_firmware_version() { 188 _get_firmware_version "RO" 189} 190 191_get_rollback_info() { 192 run_ectool_cmd "rollbackinfo" 193} 194 195get_rollback_block_id() { 196 get_ectool_output_val "Rollback block id" "$(_get_rollback_info)" 197} 198 199get_rollback_min_version() { 200 get_ectool_output_val "Rollback min version" "$(_get_rollback_info)" 201} 202 203get_rollback_rw_version() { 204 get_ectool_output_val "RW rollback version" "$(_get_rollback_info)" 205} 206 207_check_rollback_matches() { 208 local rb_type="${1}" 209 local expected="${2}" 210 local rb_info 211 rb_info="$(get_rollback_${rb_type})" 212 if [[ "${rb_info}" != "${expected}" ]]; then 213 echo "Rollback ${rb_type} does not match, expected: ${expected}, actual: ${rb_info}" 214 exit 1 215 fi 216} 217 218check_rollback_block_id_matches() { 219 _check_rollback_matches "block_id" "${1}" 220} 221 222check_rollback_min_version_matches() { 223 _check_rollback_matches "min_version" "${1}" 224} 225 226check_rollback_rw_version_matches() { 227 _check_rollback_matches "rw_version" "${1}" 228} 229 230check_is_rollback_set_to_initial_val() { 231 check_rollback_block_id_matches "1" 232 check_rollback_min_version_matches "0" 233 check_rollback_rw_version_matches "0" 234} 235 236check_rollback_is_unset() { 237 check_rollback_block_id_matches "0" 238 check_rollback_min_version_matches "0" 239 check_rollback_rw_version_matches "0" 240} 241 242check_file_exists() { 243 if [[ ! -f "${1}" ]]; then 244 echo "Cannot find file: ${1}" 245 exit 1 246 fi 247} 248 249check_running_rw_firmware() { 250 local fw_copy 251 fw_copy="$(get_running_firmware_copy)" 252 if [[ "${fw_copy}" != "RW" ]]; then 253 echo "Not running RW copy of firmware" 254 exit 1 255 fi 256} 257 258check_running_ro_firmware() { 259 local fw_copy 260 fw_copy="$(get_running_firmware_copy)" 261 if [[ "${fw_copy}" != "RO" ]]; then 262 echo "Not running RO copy of firmware" 263 exit 1 264 fi 265} 266 267_check_has_mp_firmware_type() { 268 local fw_type="${1}" 269 local fw_version 270 fw_version="$(get_${fw_type}_firmware_version)" 271 272 # The MP version string is not "special", so we compare against all the 273 # "special" version strings and only succeed if it doesn't match any of them. 274 for fw_name in ${_FW_NAMES}; do 275 if [[ "${fw_version}" == *.${fw_name} ]]; then 276 echo "Not running MP ${fw_type} firmware: ${fw_version}" 277 exit 1 278 fi 279 done 280} 281 282check_has_mp_ro_firmware() { 283 _check_has_mp_firmware_type "ro" 284} 285 286check_has_mp_rw_firmware() { 287 _check_has_mp_firmware_type "rw" 288} 289 290# generate check_has_dev_rw_firmware/check_has_dev_ro_firmware, etc 291for fw_name in ${_FW_NAMES}; do 292 for fw_type in ${_FW_TYPES}; do 293 eval " 294 check_has_${fw_name}_${fw_type}_firmware() { 295 local fw_version 296 fw_version=\"\$(get_${fw_type}_firmware_version)\" 297 if [[ \"\${fw_version}\" != *.${fw_name} ]]; then 298 echo \"Not running ${fw_name} ${fw_type} firmware: \${fw_version}\" 299 exit 1 300 fi 301 } 302 " 303 done 304done 305 306get_flashprotect_status() { 307 run_ectool_cmd "flashprotect" 308} 309 310enable_sw_write_protect() { 311 # TODO(b/116396469): The reboot_ec command returns an error even on success. 312 run_ectool_cmd_ignoring_error "flashprotect" "enable" 313 314 # TODO(b/116396469): "flashprotect enable" command is slow, so wait for 315 # it to complete before attempting to reboot. 316 sleep 2 317 318 reboot_ec 319} 320 321disable_sw_write_protect() { 322 run_ectool_cmd "flashprotect" "disable" 323} 324 325_get_hw_write_protect_state() { 326 local output 327 # NOTE: "wspw_cur" stands for "write protect switch current" 328 output="$(crossystem wpsw_cur)" 329 if [[ $? -ne 0 ]]; then 330 echo "Error getting hardware write protect state" 331 exit 1 332 fi 333 echo "${output}" 334} 335 336check_hw_write_protect_enabled() { 337 local output 338 output="$(_get_hw_write_protect_state)" 339 if [[ "${output}" -ne 1 ]]; then 340 echo "Expected HW write protect to be enabled, but it is not" 341 exit 1 342 fi 343} 344 345check_hw_write_protect_disabled() { 346 local output 347 output="$(_get_hw_write_protect_state)" 348 echo "output: ${output}" 349 if [[ "${output}" -ne 0 ]]; then 350 echo "Expected HW write protect to be disabled, but it is not" 351 exit 1 352 fi 353} 354 355check_hw_and_sw_write_protect_enabled() { 356 local output 357 output="$(get_flashprotect_status)" 358 359 if [[ "${output}" != "${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED}" ]]; then 360 echo "Incorrect flashprotect state: ${output}" 361 echo "Make sure HW write protect is enabled (wp_gpio_asserted)" 362 exit 1 363 fi 364} 365 366check_hw_and_sw_write_protect_enabled_ro() { 367 local output 368 output="$(get_flashprotect_status)" 369 370 if [[ "${output}" != "${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_ENABLED_RO}" ]]; then 371 echo "Incorrect flashprotect state: ${output}" 372 echo "Make sure HW write protect is enabled (wp_gpio_asserted)" 373 exit 1 374 fi 375} 376 377check_hw_and_sw_write_protect_disabled() { 378 local output 379 output="$(get_flashprotect_status)" 380 381 if [[ "${output}" != "${_FLASHPROTECT_OUTPUT_HW_AND_SW_WRITE_PROTECT_DISABLED}" ]]; then 382 echo "Incorrect flashprotect state: ${output}" 383 echo "Make sure HW write protect is disabled" 384 exit 1 385 fi 386} 387 388check_hw_write_protect_disabled_and_sw_write_protect_enabled() { 389 local output 390 output="$(get_flashprotect_status)" 391 392 if [[ "${output}" != \ 393 "${_FLASHPROTECT_OUTPUT_HW_WRITE_PROTECT_DISABLED_AND_SW_WRITE_PROTECT_ENABLED}" ]]; then 394 echo "Incorrect flashprotect state: ${output}" 395 echo "Make sure HW write protect is disabled and SW write protect is enabled" 396 exit 1 397 fi 398} 399 400check_fingerprint_task_is_running() { 401 run_ectool_cmd "fpinfo" 402} 403 404check_fingerprint_task_is_not_running() { 405 if (check_fingerprint_task_is_running) ; then 406 echo "Fingerprint task should not be running" 407 exit 1 408 fi 409} 410 411check_firmware_is_functional() { 412 run_ectool_cmd "version" 413} 414 415check_firmware_is_not_functional() { 416 if (check_firmware_is_functional); then 417 echo "Firmware should not be responding to commands" 418 exit 1 419 fi 420} 421 422check_files_match() { 423 cmp $1 $2 424 if [[ $? -ne 0 ]]; then 425 echo "Expected files to match, but they do not" 426 exit 1 427 fi 428} 429 430check_files_do_not_match() { 431 if (check_files_match); then 432 echo "Expected files to not match, but they do" 433 exit 1 434 fi 435} 436 437get_file_size() { 438 stat --printf %s "${1}" 439} 440 441check_file_size_equals_zero() { 442 local file_size="$(get_file_size ${1})" 443 if [[ "${file_size}" -ne 0 ]]; then 444 echo "File is not empty" 445 exit 1 446 fi 447} 448 449check_file_contains_all_0xFF_bytes() { 450 local tmp_file="all_0xff.bin" 451 local file_to_compare="$1" 452 local file_expected_byte_size="$2" 453 # create file full of zeros and then replace with 0xFF 454 dd if='/dev/zero' bs=1 count="${file_expected_byte_size}" | \ 455 sed 's#\x00#\xFF#g' > "${tmp_file}" 456 457 check_files_match "${file_to_compare}" "${tmp_file}" 458 459 rm -rf "${tmp_file}" 460} 461 462check_system_is_locked() { 463 local flags 464 flags="$(get_sysinfo_flags)" 465 if [[ "${flags}" != "${_SYSINFO_SYSTEM_IS_LOCKED_FLAGS}" ]]; then 466 echo "sysinfo flags do not match. expected: "\ 467 "${_SYSINFO_SYSTEM_IS_LOCKED_FLAGS}, actual: ${flags}" 468 exit 1 469 fi 470} 471