blob: 1f76fd634c65bda98cc5198eaac9222f653dd168 [file] [log] [blame]
# Copyright 2019 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 time
import os
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
class firmware_WilcoDiagnosticsMode(FirmwareTest):
"""Corrupt the Wilco diagnostics image and then reinstall it.
Wilco supports entry into a diagnostics image from recovery mode. The image
is stored in the RW_LEGACY firmware section and updated during AP firmware
updates. Entry into the image should fail if the image is corrupted.
Updating the firmware should restore the diagnostics image.
"""
version = 1
# The delay between pressing <F12> to enter diagnostics mode and reaching
# the confirmation screen; typically about 10 seconds; overshoot to be safe.
DIAGNOSTICS_CONFIRM_SCREEN_DELAY_SECONDS = 15
# The delay between pressing <Power> to confirm entry to diagnostics mode
# and rebooting into diagnostics mode.
DIAGNOSTICS_CONFIRM_REBOOT_DELAY_SECONDS = 8
# The delay between rebooting to enter diagnostics mode and rebooting again
# if that fails.
DIAGNOSTICS_FAIL_REBOOT_DELAY_SECONDS = 8
# The name of the diagnostics image file in CBFS.
DIAG_CBFS_NAME = 'altfw/diag'
def initialize(self, host, cmdline_args):
super(firmware_WilcoDiagnosticsMode, self).initialize(
host, cmdline_args)
if not self.faft_config.has_diagnostics_image:
raise error.TestNAError('No diagnostics image for this board.')
self.setup_firmwareupdate_shellball(shellball=None)
# Make sure that the shellball is retained over subsequent power cycles.
self.blocking_sync()
self.switcher.setup_mode('normal')
def cleanup(self):
self.servo.get_power_state_controller().reset()
super(firmware_WilcoDiagnosticsMode, self).cleanup()
def _corrupt_diagnostics_image(self):
# Extract the diagnostics image from the firmware image, corrupt the
# image, and write a new firmware image with that corrupt diagnostics
# image.
local_filename = 'diag.bin'
cbfs_work_dir = self.faft_client.updater.cbfs_setup_work_dir()
bios_cbfs_path = os.path.join(cbfs_work_dir,
self.faft_client.updater.get_bios_relative_path())
diag_cbfs_path = os.path.join(cbfs_work_dir, local_filename)
logging.info('Extracting diagnostics')
self.faft_client.updater.cbfs_extract_diagnostics(self.DIAG_CBFS_NAME,
local_filename)
logging.info('Corrupting diagnostics')
self.faft_client.updater.corrupt_diagnostics_image(local_filename)
logging.info('Replacing diagnostics')
self.faft_client.updater.cbfs_replace_diagnostics(self.DIAG_CBFS_NAME,
local_filename)
logging.info('Writing back BIOS')
self.faft_client.bios.write_whole(bios_cbfs_path)
self.switcher.mode_aware_reboot()
def _press_f12(self):
self.servo.set_nocheck('arb_key_config', '<f12>')
self.servo.set_nocheck('arb_key', 'tab')
def _enter_diagnostics_mode(self):
# Reboot to the recovery screen, press <F12>, and press power to
# confirm.
logging.info('Rebooting to recovery screen')
self.switcher.enable_rec_mode_and_reboot(usb_state='host')
time.sleep(self.faft_config.firmware_screen)
logging.info('Pressing <F12>')
self._press_f12()
time.sleep(self.DIAGNOSTICS_CONFIRM_SCREEN_DELAY_SECONDS)
logging.info('Pressing <Power> to confirm')
self.servo.power_short_press()
# At this point, the DUT will try to reboot into diagnostics mode.
def run_once(self):
"""Run the body of the test."""
logging.info('Attempting to enter diagnostics mode')
self._enter_diagnostics_mode()
# Wait long enough that DUT would have rebooted to normal mode if
# diagnostics mode failed.
time.sleep(self.DIAGNOSTICS_CONFIRM_REBOOT_DELAY_SECONDS +
self.DIAGNOSTICS_FAIL_REBOOT_DELAY_SECONDS +
self.faft_config.delay_reboot_to_ping)
self.switcher.wait_for_client_offline(timeout=5)
logging.info('DUT offline after entering diagnostics mode')
self.servo.get_power_state_controller().reset()
self.switcher.wait_for_client()
# Corrupt the diagnostics image, try to reboot into diagnostics mode,
# and verify that the DUT ends up in normal mode (indicating failure to
# enter diagnostics mode).
self._corrupt_diagnostics_image()
self._enter_diagnostics_mode()
self.switcher.wait_for_client()
self.checkers.mode_checker('normal')
# Update the firmware to restore the diagnostics image, reboot into
# diagnostics mode, and verify that the DUT goes down (indicating
# success).
logging.info('Updating firmware')
self.faft_client.updater.run_autoupdate(None)
logging.info('Rebooting to apply firmware update')
self.switcher.mode_aware_reboot()
logging.info('Attempting to enter diagnostics mode')
self._enter_diagnostics_mode()
# Wait long enough that DUT would have rebooted if diagnostics mode
# failed.
time.sleep(self.DIAGNOSTICS_CONFIRM_REBOOT_DELAY_SECONDS +
self.DIAGNOSTICS_FAIL_REBOOT_DELAY_SECONDS +
self.faft_config.delay_reboot_to_ping)
self.switcher.wait_for_client_offline(timeout=5)
logging.info('DUT offline after entering diagnostics mode')