187 lines
6.6 KiB
Python
187 lines
6.6 KiB
Python
# Copyright 2018 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, utils
|
|
from autotest_lib.client.common_lib.cros import cr50_utils
|
|
from autotest_lib.server.cros import filesystem_util
|
|
from autotest_lib.server.cros.faft.cr50_test import Cr50Test
|
|
|
|
|
|
class firmware_Cr50GetName(Cr50Test):
|
|
"""Verify cr50-get-name.sh
|
|
|
|
Verify cr50-get-name sets the correct board id and flags based on the
|
|
given stage.
|
|
"""
|
|
version = 1
|
|
|
|
GET_NAME_SCRIPT = '/usr/share/cros/cr50-get-name.sh'
|
|
# This translates to 'TEST'
|
|
TEST_BRAND = 0x54455354
|
|
MAX_VAL = 0xffffffff
|
|
|
|
|
|
def initialize(self, host, cmdline_args, full_args={}):
|
|
# Restore the original image, rlz code, and board id during cleanup.
|
|
super(firmware_Cr50GetName, self).initialize(host, cmdline_args,
|
|
full_args, restore_cr50_image=True, restore_cr50_board_id=True)
|
|
|
|
if not self.host.path_exists(self.GET_NAME_SCRIPT):
|
|
raise error.TestNAError('Device does not have "cr50-get-name"')
|
|
|
|
efi_path = self.get_saved_eraseflashinfo_image_path()
|
|
|
|
filesystem_util.make_rootfs_writable(self.host)
|
|
cr50_utils.InstallImage(self.host, efi_path, cr50_utils.CR50_PROD)
|
|
cr50_utils.InstallImage(self.host, efi_path, cr50_utils.CR50_PREPVT)
|
|
|
|
# Update to the eraseflashinfo image so we can erase the board id after
|
|
# we set it. This test is verifying cr50-get-name, so it is ok if cr50
|
|
# is running a non-prod image.
|
|
self.cr50_update(self.get_saved_dbg_image_path())
|
|
self.cr50_update(efi_path, rollback=True)
|
|
|
|
# Stop trunksd so it wont interfere with the update
|
|
cr50_utils.StopTrunksd(self.host)
|
|
|
|
# Get the current cr50 update messages. The test will keep track of the
|
|
# last message and separate the current output from actual test results.
|
|
self.get_result()
|
|
|
|
|
|
def cleanup(self):
|
|
"""Reset the DUT to restore trunksd."""
|
|
try:
|
|
self.host.reset_via_servo()
|
|
finally:
|
|
super(firmware_Cr50GetName, self).cleanup()
|
|
|
|
|
|
def get_result(self):
|
|
"""Return the new cr50 update messages from /var/log/messages"""
|
|
# Get the cr50 messages
|
|
result = self.host.run('grep cr50 /var/log/messages').stdout.strip()
|
|
|
|
if hasattr(self, '_last_message'):
|
|
result = result.rsplit(self._last_message, 1)[-1]
|
|
|
|
# Save the last line. It will be used to separate the current results
|
|
# from later runs.
|
|
self._last_message = result.rsplit('\n', 1)[-1]
|
|
logging.debug('last cr50 update message: "%s"', self._last_message)
|
|
return result
|
|
|
|
|
|
def get_expected_result_re(self, brand, flags, erased):
|
|
"""Return the expected update message re given the test flags
|
|
|
|
Args:
|
|
brand: The board id value to test.
|
|
flags: The flag value to test.
|
|
erased: True if the board id is erased
|
|
|
|
Returns:
|
|
A string with info that must be found in /var/log/messages for valid
|
|
update results.
|
|
"""
|
|
expected_result = []
|
|
|
|
if erased:
|
|
board_id = 'ffffffff:ffffffff:ffffffff'
|
|
# If the board id is erased, the device should update to the prod
|
|
# image.
|
|
ext = 'prod'
|
|
expected_result.append('board ID is erased using prod image')
|
|
else:
|
|
board_id = '%08x:%08x:%08x' % (brand, brand ^ self.MAX_VAL, flags)
|
|
ext = 'prepvt' if flags & 0x10 else 'prod'
|
|
|
|
flag_str = board_id.rsplit(':', 1)[-1]
|
|
|
|
expected_result.append("board_id: '%s' board_flags: '0x%s', extension: "
|
|
"'%s'" % (board_id, flag_str, ext))
|
|
expected_result.append('hashing /opt/google/cr50/firmware/cr50.bin.%s' %
|
|
ext)
|
|
return '(%s)' % '\n.*'.join(expected_result)
|
|
|
|
|
|
def check_result(self, brand, flags, erased):
|
|
"""Verify the expected result string is found in the update messages
|
|
|
|
Args:
|
|
brand: The board id value to test.
|
|
flags: The flag value to test.
|
|
erased: True if the board id is erased
|
|
|
|
Raises:
|
|
TestFail if the expected result message did not match the update
|
|
output
|
|
"""
|
|
expected_result_re = self.get_expected_result_re(brand, flags, erased)
|
|
result = self.get_result()
|
|
match = re.search(expected_result_re, result)
|
|
|
|
logging.debug('EXPECT: %s', expected_result_re)
|
|
logging.debug('GOT: %s', result)
|
|
|
|
if not match:
|
|
raise error.TestFail('Unexpected result during update with %s' %
|
|
('erased board id' if erased else '%x:%x' % (brand, flags)))
|
|
|
|
logging.info('FOUND UPDATE RESULT:\n%s', match.groups()[0])
|
|
|
|
|
|
def cr50_update_is_running(self):
|
|
"""Returns True if cr50-update is running on the host"""
|
|
time.sleep(1)
|
|
status = self.host.run('status cr50-update').stdout
|
|
logging.info('cr50-update status: %s', status)
|
|
return 'running' in status
|
|
|
|
|
|
def run_update(self, brand, flags, clear_bid=False):
|
|
"""Set the board id then run cr50-update
|
|
|
|
Args:
|
|
brand: The board id int to test.
|
|
flags: The flag int to test.
|
|
clear_bid: True if the board id should be erased and not reset.
|
|
"""
|
|
if not self.cr50.eraseflashinfo():
|
|
raise error.TestError('Unable to erase the board id')
|
|
|
|
if not clear_bid:
|
|
cr50_utils.SetChipBoardId(self.host, brand, flags)
|
|
|
|
# Get the current cr50 update messages. The test will keep track of the
|
|
# last message and separate the current output from actual test results.
|
|
self.get_result()
|
|
# Run the update script script
|
|
self.host.run('start cr50-update')
|
|
utils.wait_for_value(self.cr50_update_is_running, expected_value=False,
|
|
timeout_sec=30)
|
|
|
|
# Make sure cr50 used the right image.
|
|
self.check_result(brand, flags, clear_bid)
|
|
|
|
|
|
def run_once(self):
|
|
"""Verify cr50-get-name.sh"""
|
|
# Test the MP flags
|
|
self.run_update(self.TEST_BRAND, 0x7f00)
|
|
|
|
# Test the pre-PVT flags
|
|
self.run_update(self.TEST_BRAND, 0x7f10)
|
|
|
|
# Erase the board id
|
|
self.run_update(0, 0, clear_bid=True)
|
|
|
|
# Make sure the script can tell the difference between an erased board
|
|
# id and one set to 0xffffffff:0xffffffff.
|
|
self.run_update(self.MAX_VAL, self.MAX_VAL)
|