blob: 55c79b86d7c251e69bfd08c39f53b91d82d539c3 [file] [log] [blame]
# 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.
"""Auto test for Bizlink firmware updater functionality and udev rule."""
from __future__ import print_function
import logging
import os
import re
import time
from autotest_lib.client.common_lib import error
from autotest_lib.server import test
UPDATER_WAIT_TIME = 180 # seconds
CMD_CHECK_FW_UPDATE_OUTPUT = 'grep bizlink-updater /var/log/messages'
FW_PATH = '/lib/firmware/bizlink/'
OLD_FW_NAME = 'megachips-firmware-old.bin'
NEW_FW_NAME = 'megachips-firmware.bin'
class enterprise_CFM_BizlinkUpdater(test.test):
"""
Bizlink dongle firmware updater functionality test in Chrome Box.
The procedure of the test is:
1. flash old version FW to device,
2. Reboot the device, which should be able to trigger udev rule and run the
updater,
3. wait for the updater to finish,
4. run fw updater again and verify that the FW in device is consistent with
latest FW within system by checking the output.
"""
version = 1
def initialize(self, host):
self.host = host
self.old_fw_path = os.path.join(FW_PATH, OLD_FW_NAME)
self.new_fw_path = os.path.join(FW_PATH, NEW_FW_NAME)
def cleanup(self):
cmd = 'rm -f {}'.format(self.old_fw_path)
self.host.run(cmd)
super(enterprise_CFM_BizlinkUpdater, self).cleanup()
def check_update_result(self, expected_output=''):
"""
Checks FW update result.
Queries the syslog and checks if expected_output occurs in it.
@param expected_output: the string to query syslog for.
@returns True if expected_output is in syslog. Otherwise return false.
"""
result = self.host.run(CMD_CHECK_FW_UPDATE_OUTPUT)
# Only check last 5 logs for the most recent run.
messages = result.stdout.strip().split('\n')
if len(messages) < 5:
return False
messages = ''.join(messages[-5:])
if expected_output in messages:
return True
else:
return False
def convert_rootfs_writable(self):
"""
Removes rootfs verification on DUT and reboots.
"""
logging.info('Disabling rootfs verification...')
self.remove_rootfs_verification()
logging.info('Rebooting...')
self.host.reboot()
def remove_rootfs_verification(self):
"""Removes rootfs verification."""
# 2 & 4 are default partitions, and the system boots from one of them.
# Code from chromite/scripts/deploy_chrome.py
KERNEL_A_PARTITION = 2
KERNEL_B_PARTITION = 4
cmd_template = ('/usr/share/vboot/bin/make_dev_ssd.sh --partitions %d '
'--remove_rootfs_verification --force')
for partition in (KERNEL_A_PARTITION, KERNEL_B_PARTITION):
cmd = cmd_template % partition
self.host.run(cmd)
def is_filesystem_readwrite(self):
"""Checks if the root file system is read-writable.
Queries the DUT's filesystem /dev/root, checks for keyword 'rw'.
@returns True if /dev/root is read-writable. False otherwise.
"""
cmd = 'cat /proc/mounts | grep "/dev/root"'
result = self.host.run(cmd)
if result.stderr:
output = result.stderr
else:
output = result.stdout
fields = re.split(' |,', output)
return True if fields.__len__() >= 4 and fields[3] == 'rw' else False
def copy_firmware(self):
"""Copies test firmware from server to DUT."""
current_dir = os.path.dirname(os.path.realpath(__file__))
src_firmware_path = os.path.join(current_dir, OLD_FW_NAME)
dst_firmware_path = FW_PATH
logging.info('Copy firmware from {} to {}.'.format(src_firmware_path,
dst_firmware_path))
self.host.send_file(src_firmware_path, dst_firmware_path,
delete_dest=True)
def triger_updater(self):
"""Trigers udev rule to run fw updater."""
self.host.reboot()
def flash_fw(self, fw_path):
"""
Flashes certain firmware to device.
Runs Bizlink firmware updater on DUT to flashes the firmware given
by fw_path to target device.
@param fw_path: the path to the firmware to flash.
"""
cmd_run_updater = ('/usr/sbin/bizlink-updater --update=true '
'--fw_path={}'.format(fw_path))
logging.info('executing {}'.format(cmd_run_updater))
self.host.run(cmd_run_updater)
def run_once(self):
# Make the DUT filesystem writable.
if not self.is_filesystem_readwrite():
logging.info('DUT root file system is not read-writable. '
'Converting it read-writable...')
self.convert_rootfs_writable()
else:
logging.info('DUT is read-writable.')
# Copy old FW to device.
self.copy_firmware()
# Flash old FW to device.
self.flash_fw(self.old_fw_path)
expect_output = 'FW update succeed.'
succeed = self.check_update_result(expected_output=expect_output)
if not succeed:
raise error.TestFail('Expect \'{}\' in output, '
'but didn\'t find it.'.format(expect_output))
self.triger_updater()
# Wait for fw updater to finish.
time.sleep(UPDATER_WAIT_TIME)
# Try flash the new firmware, should detect same fw version.
expect_output = 'Same FW version, no update required.'
self.flash_fw(self.new_fw_path)
succeed = self.check_update_result(expected_output=expect_output)
if not succeed:
raise error.TestFail('Expect {} in output '
'but didn\'t find it.'.format(expect_output))