aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2022-05-13 09:40:29 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-23 17:50:41 +0000
commitdd449d394d7eec0eb10193201cb96cf13c395a5d (patch)
tree4e460d2854c47ca515416a7494d5af29c87b41d9
parent1323054002480ac878213f194ab0b36c95712a58 (diff)
downloadautotest-dd449d394d7eec0eb10193201cb96cf13c395a5d.tar.gz
faft-cr50: add test to verify trigger v1 ap ro verify
Add a test that saves the hash with the dbg image and then triggers verification. This test only verifies triggering verification. It doesn't test saving the hash since that requires erasing the board id. BUG=b:218705748 TEST=run on hatch Change-Id: Ia766c6bed858e00f134328c9c223a54d333cd8cc Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/3652630 Tested-by: Mary Ruthven <mruthven@chromium.org> Commit-Queue: Mary Ruthven <mruthven@chromium.org> Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
-rw-r--r--server/site_tests/firmware_GSCAPROV1Trigger/control33
-rw-r--r--server/site_tests/firmware_GSCAPROV1Trigger/firmware_GSCAPROV1Trigger.py183
2 files changed, 216 insertions, 0 deletions
diff --git a/server/site_tests/firmware_GSCAPROV1Trigger/control b/server/site_tests/firmware_GSCAPROV1Trigger/control
new file mode 100644
index 0000000000..b38b6065c1
--- /dev/null
+++ b/server/site_tests/firmware_GSCAPROV1Trigger/control
@@ -0,0 +1,33 @@
+# 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.
+
+AUTHOR = "mruthven"
+NAME = "firmware_GSCAPROV1Trigger"
+PURPOSE = "Test triggering AP RO verification."
+ATTRIBUTES = "suite:faft_cr50_experimental"
+TIME = "SHORT"
+TEST_TYPE = "server"
+DEPENDENCIES = "servo_state:WORKING"
+PY_VERSION = 3
+
+DOC = """
+Verify triggering AP RO verification on GSC.
+"""
+
+from autotest_lib.client.common_lib import error
+from autotest_lib.server import utils
+
+if 'args_dict' not in locals():
+ args_dict = {}
+
+args_dict.update(utils.args_to_dict(args))
+servo_args = hosts.CrosHost.get_servo_arguments(args_dict)
+
+def run(machine):
+ host = hosts.create_host(machine, servo_args=servo_args)
+
+ job.run_test("firmware_GSCAPROV1Trigger", host=host, cmdline_args=args,
+ full_args=args_dict)
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/firmware_GSCAPROV1Trigger/firmware_GSCAPROV1Trigger.py b/server/site_tests/firmware_GSCAPROV1Trigger/firmware_GSCAPROV1Trigger.py
new file mode 100644
index 0000000000..c7dc40865f
--- /dev/null
+++ b/server/site_tests/firmware_GSCAPROV1Trigger/firmware_GSCAPROV1Trigger.py
@@ -0,0 +1,183 @@
+# 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.