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