184 lines
6.9 KiB
Python
184 lines
6.9 KiB
Python
# Copyright 2022 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.
|
|
|
|
import logging
|
|
import re
|
|
import time
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.common_lib.cros import cr50_utils
|
|
from autotest_lib.server.cros.faft.cr50_test import Cr50Test
|
|
|
|
|
|
class firmware_GSCAPROV1Trigger(Cr50Test):
|
|
"""Verify GSC response after triggering AP RO V1 verification."""
|
|
version = 1
|
|
|
|
# This only verifies V1 output right now.
|
|
TEST_AP_RO_VER = 1
|
|
|
|
# DBG image has to be able to set the AP RO hash with the board id set.
|
|
MIN_DBG_VER = '1.6.100'
|
|
|
|
VERIFICATION_PASSED = 1
|
|
VERIFICATION_FAILED = 2
|
|
|
|
DIGEST_RE = r' digest ([0-9a-f]{64})'
|
|
CALCULATED_DIGEST_RE = 'Calculated' + DIGEST_RE
|
|
STORED_DIGEST_RE = 'Stored' + DIGEST_RE
|
|
|
|
def initialize(self, host, cmdline_args, full_args={}):
|
|
"""Initialize servo"""
|
|
self.ran_test = False
|
|
super(firmware_GSCAPROV1Trigger,
|
|
self).initialize(host,
|
|
cmdline_args,
|
|
full_args,
|
|
restore_cr50_image=True)
|
|
if not self.cr50.ap_ro_version_is_supported(self.TEST_AP_RO_VER):
|
|
raise error.TestNAError('GSC does not support AP RO v%s' %
|
|
self.TEST_AP_RO_VER)
|
|
|
|
dbg_ver = cr50_utils.InstallImage(self.host,
|
|
self.get_saved_dbg_image_path(),
|
|
'/tmp/cr50.bin')[1][1]
|
|
if cr50_utils.GetNewestVersion(dbg_ver,
|
|
self.MIN_DBG_VER) == self.MIN_DBG_VER:
|
|
raise error.TestNAError('Update DBG image to 6.100 or newer.')
|
|
|
|
def update_to_dbg_and_clear_hash(self):
|
|
"""Clear the Hash."""
|
|
# Make sure the AP is up before trying to update.
|
|
self.recover_dut()
|
|
self._retry_cr50_update(self._dbg_image_path, 3, False)
|
|
self.cr50.send_command('ap_ro_info erase')
|
|
time.sleep(3)
|
|
ap_ro_info = self.cr50.get_ap_ro_info()
|
|
logging.info(ap_ro_info)
|
|
if ap_ro_info['hash']:
|
|
raise error.TestError('Could not erase hash')
|
|
|
|
def after_run_once(self):
|
|
"""Reboot cr50 to recover the dut."""
|
|
try:
|
|
self.recover_dut()
|
|
finally:
|
|
super(firmware_GSCAPROV1Trigger, self).after_run_once()
|
|
|
|
def set_hash(self):
|
|
"""Set the Hash."""
|
|
self.recover_dut()
|
|
result = self.host.run('ap_ro_hash.py -v True GBB')
|
|
logging.info(result)
|
|
time.sleep(3)
|
|
ap_ro_info = self.cr50.get_ap_ro_info()
|
|
logging.info(ap_ro_info)
|
|
if not ap_ro_info['hash']:
|
|
raise error.TestError('Could not set hash %r' % result)
|
|
|
|
def rollback_to_release_image(self):
|
|
"""Update to the release image."""
|
|
self._retry_cr50_update(self.get_saved_cr50_original_path(),
|
|
3,
|
|
rollback=True)
|
|
logging.info(self.cr50.get_ap_ro_info())
|
|
|
|
def cleanup(self):
|
|
"""Clear the AP RO hash."""
|
|
try:
|
|
if not self.ran_test:
|
|
return
|
|
logging.info('Cleanup')
|
|
self.recover_dut()
|
|
self.update_to_dbg_and_clear_hash()
|
|
self.rollback_to_release_image()
|
|
finally:
|
|
super(firmware_GSCAPROV1Trigger, self).cleanup()
|
|
|
|
def recover_dut(self):
|
|
"""Reboot gsc to recover the dut."""
|
|
logging.info('Recover DUT')
|
|
ap_ro_info = self.cr50.get_ap_ro_info()
|
|
logging.info(ap_ro_info)
|
|
if ap_ro_info['result'] != self.VERIFICATION_FAILED:
|
|
self._try_to_bring_dut_up()
|
|
return
|
|
time.sleep(3)
|
|
self.cr50.send_command('ccd testlab open')
|
|
time.sleep(3)
|
|
self.cr50.reboot()
|
|
time.sleep(self.faft_config.delay_reboot_to_ping)
|
|
logging.info(self.cr50.get_ap_ro_info())
|
|
self._try_to_bring_dut_up()
|
|
self.cr50.send_command('ccd testlab open')
|
|
|
|
def trigger_verification(self):
|
|
"""Trigger verification."""
|
|
try:
|
|
self.recover_dut()
|
|
result = self.host.run('gsctool -aB start',
|
|
ignore_timeout=True,
|
|
ignore_status=True,
|
|
timeout=20)
|
|
logging.info(result)
|
|
finally:
|
|
time.sleep(5)
|
|
ap_ro_info = self.cr50.get_ap_ro_info()
|
|
logging.info(ap_ro_info)
|
|
self.hash_results.append(ap_ro_info['result'])
|
|
self.servo.record_uart_capture()
|
|
|
|
def run_once(self):
|
|
"""Save hash and trigger verification"""
|
|
self.ran_test = True
|
|
self.hash_results = []
|
|
# The DBG image can set the hash when the board id is saved. The release
|
|
# image can't. Set the hash with the DBG image, so the test doesn't need
|
|
# to erase the board id. This test verifies triggering AP RO
|
|
# verification. It's not about saving the hash.
|
|
self.update_to_dbg_and_clear_hash()
|
|
self.set_hash()
|
|
self.rollback_to_release_image()
|
|
# CCD has to be open to trigger verification.
|
|
self.fast_ccd_open(True)
|
|
|
|
# Trigger verification multiple times. Make sure it doesn't fail or
|
|
# change.
|
|
self.trigger_verification()
|
|
self.trigger_verification()
|
|
self.trigger_verification()
|
|
self.trigger_verification()
|
|
|
|
self.servo.record_uart_capture()
|
|
cr50_uart_file = self.servo.get_uart_logfile('cr50')
|
|
if not cr50_uart_file:
|
|
logging.info('No cr50 uart file')
|
|
return
|
|
with open(cr50_uart_file, 'r') as f:
|
|
contents = f.read()
|
|
|
|
self.recover_dut()
|
|
|
|
# GSC only prints calculated and stored hashes after AP RO verificaiton
|
|
# fails. These sets will be empty if verification passed every time.
|
|
calculated = set(re.findall(self.CALCULATED_DIGEST_RE, contents))
|
|
stored = set(re.findall(self.STORED_DIGEST_RE, contents))
|
|
logging.info('Stored: %r', stored)
|
|
logging.info('Calculated: %r', calculated)
|
|
logging.info('Results: %r', self.hash_results)
|
|
|
|
if self.VERIFICATION_FAILED in self.hash_results:
|
|
raise error.TestFail(
|
|
'Verification failed -- stored: %r calculated: %r' %
|
|
(stored, calculated))
|
|
if len(calculated) > 1:
|
|
raise error.TestFail('Multiple calculated digests %r' % calculated)
|
|
# This shouldn't happen. Raise TestNA, so it's easy to see.
|
|
if self.VERIFICATION_PASSED not in self.hash_results:
|
|
raise error.TestNAError(
|
|
'Verification Not Run -- stored: %r calculated: %r' %
|
|
(stored, calculated))
|
|
|
|
# TODO(b/218705748): change the hash and verify verification fails.
|