113 lines
4.2 KiB
Python
113 lines
4.2 KiB
Python
# Copyright (c) 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 random
|
|
import time
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
|
|
|
|
# Serial number cannot contain vowels after the first character, so don't allow
|
|
# any vowels in this test.
|
|
VALID_CHARS = "BCDFGHJKLMNPQRSTVWXYZ0123456789"
|
|
|
|
class firmware_SetSerialNumber(FirmwareTest):
|
|
"""
|
|
Servo based test to set serial number in firmware.
|
|
|
|
Test that setting the serial number in firmware during an onsite RMA works.
|
|
Mainboards for onsite RMA will have WP# asserted, flash WP bit cleared,
|
|
the serial_number in VPD set to all spaces, and be in dev mode. After the
|
|
serial number is set in firmware flash write protect will be enabled and
|
|
the device will be in normal mode.
|
|
"""
|
|
version = 1
|
|
|
|
def start_serial_number_prompt(self):
|
|
"""Repeatedly press ctrl-s to bring up serial number prompt."""
|
|
logging.info("Pressing Ctrl-S.")
|
|
timeout = time.time() + (self.faft_config.firmware_screen)
|
|
while time.time() < timeout:
|
|
self.servo.set_nocheck('ctrl_s', 'tab')
|
|
time.sleep(1)
|
|
|
|
def generate_serial_number_string(self):
|
|
"""Generate a valid serial number based on config"""
|
|
return ''.join(random.choice(VALID_CHARS)
|
|
for _ in range(self.faft_config.serial_number_length))
|
|
|
|
def send_string(self, keys):
|
|
"""Send a string over a servo"""
|
|
for key in keys.lower():
|
|
self.servo.set_nocheck('arb_key_config', key)
|
|
self.servo.set_nocheck('arb_key', 'tab')
|
|
|
|
def initialize(self, host, cmdline_args):
|
|
super(firmware_SetSerialNumber, self).initialize(host, cmdline_args)
|
|
|
|
if self.faft_config.serial_number_length == 0:
|
|
raise error.TestNAError("This test is only valid on devices where "
|
|
"serial number can be set in firmware.")
|
|
|
|
# This test is run on developer mode only.
|
|
self.switcher.setup_mode('dev')
|
|
|
|
# Disable fw wp to clear VPD value
|
|
self.set_hardware_write_protect(False)
|
|
|
|
self.faft_client.system.run_shell_command_get_output(
|
|
'flashrom -p host --wp-disable')
|
|
|
|
self.faft_client.system.run_shell_command_get_output(
|
|
'vpd -i RO_VPD -s serial_number="%s"' %
|
|
(' ' * self.faft_config.serial_number_length)
|
|
)
|
|
|
|
self.set_hardware_write_protect(True)
|
|
|
|
def run_once(self):
|
|
"""Run the test"""
|
|
serial_number = self.generate_serial_number_string()
|
|
logging.info("Setting serial number to '%s'.", serial_number)
|
|
|
|
self.switcher.simple_reboot()
|
|
if not self.faft_config.rma_entered_automatically:
|
|
self.start_serial_number_prompt()
|
|
else:
|
|
time.sleep(self.faft_config.firmware_screen)
|
|
self.send_string(serial_number)
|
|
# Press enter on set
|
|
self.servo.enter_key()
|
|
# Press enter on confirm
|
|
self.servo.enter_key()
|
|
self.switcher.wait_for_client()
|
|
|
|
# Check that device is no longer in dev mode
|
|
self.checkers.mode_checker('normal')
|
|
|
|
# Check that serial_number is correctly set
|
|
result = self.faft_client.system.run_shell_command_get_output(
|
|
'vpd -i RO_VPD -g serial_number')[0]
|
|
|
|
if result != serial_number:
|
|
raise error.TestFail("Expected serial number '%s' but got '%s'" % (
|
|
serial_number, result))
|
|
|
|
# Check that write protect is correctly set
|
|
result = self.faft_client.system.run_shell_command_get_output(
|
|
'flashrom -p host --wp-status')
|
|
|
|
result = '\n'.join(result)
|
|
|
|
if ('is disabled' in result or
|
|
'start=0x00000000' in result or
|
|
'len=0x00000000' in result):
|
|
raise error.TestFail('Expected write protection to be enabled '
|
|
'but output was:\n\n%s' % result)
|
|
|
|
def cleanup(self):
|
|
self.servo.set_nocheck('fw_wp_state', 'reset')
|
|
super(firmware_SetSerialNumber, self).cleanup()
|