blob: b838e651506bf04e68376671e2cf313a57d3fb61 [file] [log] [blame]
# Copyright (c) 2020 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 string
import random
import logging
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
def random_string(length, chars):
"""Generate a random string of characters.
@param length: the length of string to generate.
@param chars: the set of characters to use when generating the string.
@returns The generated string.
"""
return ''.join(random.SystemRandom().choice(chars) for _ in range(length))
class firmware_SysfsVPD(FirmwareTest):
"""
Servo based test for reading VPD data through sysfs.
This test writes random test strings to the RO and RW sections of VPD data
and verifies that they can be read through sysfs after a reboot.
"""
version = 1
# Length of test string to generate and write to VPD
_TEST_VAL_LENGTH = 8
# Character set to use when generating string to write to VPD
_TEST_VAL_CHARS = string.ascii_lowercase + string.digits
# Name of key to write to RO section of VPD
VPD_RO_TEST_KEY = "RO_TEST"
# Name of key to write to RW section of VPD
VPD_RW_TEST_KEY = "RW_TEST"
def initialize(self, host, cmdline_args, dev_mode=False):
"""Initialize the test"""
super(firmware_SysfsVPD, self).initialize(host, cmdline_args)
self.host = host
self.backup_firmware()
self.switcher.setup_mode('dev' if dev_mode else 'normal')
def cleanup(self):
"""Cleanup the test"""
try:
if self.is_firmware_saved():
self.restore_firmware()
finally:
super(firmware_SysfsVPD, self).cleanup()
def run_once(self, dev_mode=False):
"""Runs a single iteration of the test."""
# Log the initial VPD sections so we can manually restore VPD from
# test logs if necessary.
logging.info("Logging initial RO+RW VPD data")
self.host.run("vpd -i RO_VPD -l")
self.host.run("vpd -i RW_VPD -l")
# Generate a random string and write it to RO section of VPD
vpd_ro_test_val = random_string(length=self._TEST_VAL_LENGTH,
chars=self._TEST_VAL_CHARS)
logging.info("Writting RO test data to VPD (key = %s, val = %s)",
self.VPD_RO_TEST_KEY, vpd_ro_test_val)
self.host.run("vpd -i RO_VPD -s %s=%s" %
(self.VPD_RO_TEST_KEY, vpd_ro_test_val))
# Generate a random string and write it to RW section of VPD
vpd_rw_test_val = random_string(length=self._TEST_VAL_LENGTH,
chars=self._TEST_VAL_CHARS)
logging.info("Writting RW test data to VPD (key = %s, val = %s)",
self.VPD_RW_TEST_KEY, vpd_rw_test_val)
self.host.run("vpd -i RW_VPD -s %s=%s" %
(self.VPD_RW_TEST_KEY, vpd_rw_test_val))
# Reboot DUT to load new VPD data in sysfs
logging.info('Rebooting DUT')
self.servo.get_power_state_controller().reset()
# Verify RO test string can be read through sysfs and matches test value
logging.info('Verifying RO VPD test data in sysfs')
try:
path = "/sys/firmware/vpd/ro/%s" % self.VPD_RO_TEST_KEY
result = self.host.run("cat %s" % path)
value = result.stdout.strip()
except error.AutoservRunError:
raise error.TestFail("Failed to read back RO VPD data")
if value != vpd_ro_test_val:
raise error.TestFail(
"Mismatched RO VPD data, read %s (expected %s)" %
(value, vpd_ro_test_val))
# Verify RW test string can be read through sysfs and matches test value
logging.info('Verifying RW VPD test data in sysfs')
try:
path = "/sys/firmware/vpd/rw/%s" % self.VPD_RW_TEST_KEY
result = self.host.run("cat %s" % path)
value = result.stdout.strip()
except error.AutoservRunError:
raise error.TestFail("Failed to read back RW VPD data")
if value != vpd_rw_test_val:
raise error.TestFail(
"Mismatched RW VPD data, read %s (expected %s)" %
(value, vpd_rw_test_val))
# Remove the test keys from VPD
logging.info("Deleting test data from VPD")
self.host.run("vpd -i RO_VPD -d %s" % self.VPD_RO_TEST_KEY)
self.host.run("vpd -i RW_VPD -d %s" % self.VPD_RW_TEST_KEY)