firmware_ECRestoreFW: corrupts EC w/ a zero-binary
This patch makes firmware_ECRestoreFW to flash a zero-filled
file on EC to brick it, and checks if the firmware restoration
after it works.
BUG=b:137386185
TEST=ran the test on Octopus
$ test_that -b octopus 192.168.5.177 --autotest_dir ${AUTOTEST_DIR}
--args="local_tarball=${LOCAL_TARBALL}" firmware_ECRestoreFW
Change-Id: Ie4d22d44e7f83fced49dac85aaf9b9a59157dd54
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/3059771
Commit-Queue: Namyoon Woo <namyoon@chromium.org>
Tested-by: Namyoon Woo <namyoon@chromium.org>
Reviewed-by: Wai-Hong Tam <waihong@google.com>
Reviewed-by: Otabek Kasimov <otabek@google.com>
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index cc40a16..8b3d340 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -1469,12 +1469,13 @@
self._programmer.program_ec(image)
- def extract_ec_image(self, board, model, tarball_path):
+ def extract_ec_image(self, board, model, tarball_path, fake_image=False):
"""Helper function to extract EC image from downloaded tarball.
@param board: The DUT board name.
@param model: The DUT model name.
@param tarball_path: The path of the downloaded build tarball.
+ @param fake_image: True to return a fake zero-filled image instead.
@return: Path to extracted EC image.
"""
@@ -1518,6 +1519,17 @@
_extract_image_from_tarball(tarball_path, dest_dir, mon_candidates,
self.EXTRACT_TIMEOUT_SECS)
+ if fake_image:
+ # Create a small (25% of original size) zero-filled binary to
+ # replace the real ec_image
+ file_size = os.path.getsize(ec_image) / 4
+ ec_image = os.path.join(os.path.dirname(ec_image),
+ "zero_ec.bin")
+ dump_cmd = 'dd if=/dev/zero of=%s bs=4096 count=%d' % (
+ os.path.join(dest_dir, ec_image), file_size / 4096)
+ if server_utils.system(dump_cmd, ignore_status=True) != 0:
+ return None
+
return os.path.join(dest_dir, ec_image)
else:
raise error.TestError('Failed to extract EC image from %s' %
diff --git a/server/hosts/cros_host.py b/server/hosts/cros_host.py
index 8182170..f74d011 100644
--- a/server/hosts/cros_host.py
+++ b/server/hosts/cros_host.py
@@ -829,7 +829,8 @@
verify_version=False,
try_scp=False,
install_ec=True,
- install_bios=True):
+ install_bios=True,
+ corrupt_ec=False):
"""Install firmware to the DUT.
Use stateful update if the DUT is already running the same build.
@@ -856,6 +857,7 @@
the firmware and programming from the DUT.
@param install_ec: True to install EC FW, and False to skip it.
@param install_bios: True to install BIOS, and False to skip it.
+ @param corrupt_ec: True to flash EC with a false image (for test purpose).
TODO(dshi): After bug 381718 is fixed, update here with corresponding
exceptions that could be raised.
@@ -904,7 +906,8 @@
if install_ec:
# Extract EC image from tarball
logging.info('Extracting EC image.')
- ec_image = self.servo.extract_ec_image(board, model, local_tarball)
+ ec_image = self.servo.extract_ec_image(board, model, local_tarball,
+ corrupt_ec)
logging.info('Extracted: %s', ec_image)
bios_image = None
diff --git a/server/site_tests/firmware_ECRestoreFW/control b/server/site_tests/firmware_ECRestoreFW/control
index 5284bd5..6aa538b 100644
--- a/server/site_tests/firmware_ECRestoreFW/control
+++ b/server/site_tests/firmware_ECRestoreFW/control
@@ -17,6 +17,9 @@
DOC = """
This test flashes a wrong EC RW firmware and checks FW gets restored.
+
+If you want to use a local tarball file to test,
+add --args="local_tarball=<path>" to test_that command line.
"""
if 'args_dict' not in locals():
diff --git a/server/site_tests/firmware_ECRestoreFW/firmware_ECRestoreFW.py b/server/site_tests/firmware_ECRestoreFW/firmware_ECRestoreFW.py
index 29df033..7790e8c 100644
--- a/server/site_tests/firmware_ECRestoreFW/firmware_ECRestoreFW.py
+++ b/server/site_tests/firmware_ECRestoreFW/firmware_ECRestoreFW.py
@@ -5,6 +5,7 @@
"""The autotest performing FW update, both EC and AP in CCD mode."""
import logging
+import re
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
@@ -24,6 +25,33 @@
if not self.check_ec_capability():
raise error.TestNAError('Nothing needs to be tested on this device')
+ self.local_tarball = None
+ self.build = None
+ # find if "local_tarball" was given in the command line arguments.
+ for arg in cmdline_args:
+ match = re.search(r'^local_tarball=(.+)', arg)
+ if match:
+ self.local_tarball = match.group(1)
+ logging.info('Use local tarball %s', self.local_tarball)
+ break
+ else:
+ # Get the latest firmware release from the server.
+ # Even this test uses a fake EC image, it needs to download
+ # the release to get some subsidiary binary (like npcx_monitor.bin).
+ platform = self.faft_config.platform
+
+ # Get the parent (a.k.a. reference board or baseboard), and hand it
+ # to get_latest_release_version so that it can use it in search as
+ # secondary candidate. For example, bob doesn't have its own release
+ # directory, but its parent, gru does.
+ parent = getattr(self.faft_config, 'parent', None)
+
+ self.build = host.get_latest_release_version(platform, parent)
+
+ if not self.build:
+ raise error.TestError(
+ 'Cannot locate the latest release for %s' % platform)
+ logging.info('Will use the build %s', self.build)
self.backup_firmware()
def cleanup(self):
@@ -48,10 +76,12 @@
"""
try:
- host.firmware_install(build="",
+ host.firmware_install(build=self.build,
dest=self.resultsdir,
+ local_tarball=self.local_tarball,
install_ec=True,
- install_bios=False)
+ install_bios=False,
+ corrupt_ec=True)
except error.TestError as e:
# It failed before the test attempts to install firmware.
# It could be either devserver timeout or servo device error.