• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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