blob: 9b264479d9235d27a25de709cd2148c2cd290312 [file] [log] [blame]
# Copyright 2021 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Update vendor plugin firmware using fwupdtool.
Description
-----------
This test updates the vendor plugin firmware by calling fwupdtool. User has to
specify the path to firmware and also the name of the plugin to be updated.
Test Procedure
--------------
This is an automatic test that doesn't need any user interaction.
1. Firstly, this test will create a DUT link.
2. If the firmware image is from the station, the image would be sent to DUT.
3. If the firmware image is in release partition, the test mounts the release
partition to get the image.
4. If the firmware image is in test partition, the test mounts the test
partition to get the image.
Dependency
----------
- DUT link must be ready before running this test.
- `fwupdtool` on DUT.
Examples
--------
To update the nvme firmware with the image in DUT release partition,
add this in test list::
{
"pytest_name": "update_plugin_firmware",
"args": {
"firmware_file": "/path/to/firmware/file/image.cab",
"plugin": "nvme"
}
}
To update the nvme firmware with the image in DUT test partition,
and allow downgrading the firmware version, add this in test list::
{
"pytest_name": "update_plugin_firmware",
"args": {
"allow_older": true,
"firmware_file": "/path/to/firmware/file/image.cab",
"from_release": false,
"plugin": "nvme"
}
}
"""
import logging
from cros.factory.device import device_utils
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import sys_utils
FWUPDTOOL = 'fwupdtool'
class UpdateUsingFwUpdTest(test_case.TestCase):
related_components = tuple()
ARGS = [
Arg('allow_older', bool, 'Allow downgrading the firmware.',
default=False),
Arg('firmware_file', str, 'Name of the firmware binary file (.cab).'),
Arg('from_release', bool, 'Get the firmware file from release rootfs.',
default=True),
Arg('plugin', str, 'Specify the name of the plugin.'),
]
ui_class = test_ui.ScrollableLogUI
def setUp(self):
self._dut = device_utils.CreateDUTInterface()
# yapf: disable
self._allow_older = self.args.allow_older # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
self._firmware_file = None
# yapf: disable
self._from_release = self.args.from_release # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
# yapf: disable
self._plugin = self.args.plugin # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
def runTest(self):
# yapf: disable
if self.args.from_release: # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
logging.info('Get firmware from release rootfs...')
with sys_utils.MountPartition(self._dut.partitions.RELEASE_ROOTFS.path,
dut=self._dut) as root:
self._firmware_file = self._dut.path.join(root,
# yapf: disable
self.args.firmware_file[1:]) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
self.UpdatePlugin()
else:
if self._dut.link.IsLocal():
# yapf: disable
self._firmware_file = self.args.firmware_file # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
self.UpdatePlugin()
else:
with self._dut.temp.TempFile() as dut_temp_file:
# yapf: disable
self._dut.SendFile(self.args.firmware_file, dut_temp_file) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
self._firmware_file = dut_temp_file
self.UpdatePlugin()
def UpdatePlugin(self):
# Skip reboot prompt by adding `--no-reboot-check`.
update_command = [FWUPDTOOL, 'install', '--no-reboot-check']
# We add `nocheck` in the comment to skip the blocked_term checking.
# In older version of fwupdtool, the option `--plugins` is called
# `--plugin-whitelist`. nocheck
support_plugins = self._dut.CallOutput(
f'{FWUPDTOOL} --help | grep -- --plugins')
if support_plugins:
update_command += ['--plugins', self._plugin]
else:
update_command += ['--plugin-whitelist', self._plugin] # nocheck
if self._allow_older:
update_command += ['--allow-older']
logging.warning('Allow downgrading plugin %s firmware.', self._plugin)
# yapf: disable
update_command += [self._firmware_file] # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
logging.info('Update plugins: %s', update_command)
# yapf: disable
returncode = self.ui.PipeProcessOutputToUI(update_command) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
self.assertEqual(returncode, 0,
f'Firmware update failed: {int(returncode)}.')