blob: 5de08f9554416c55be186335fc62cc71cf9a4174 [file] [log] [blame]
# Copyright 2023 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
from autotest_lib.client.bin import test
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import fwupd
from distutils.version import LooseVersion
class fwupd_FirmwareInstallVersion(test.test):
"""Tests that a device's firmware can be updated to a specific version.
After a successful run, the device will be running the specified
firmware version.
"""
version = 1
def setup(self):
fwupd.clear_history()
def install_firmware(self, device_id, version):
"""Installs a specific firmware version in a device.
Args:
device_id: the id of the device to update (string). It can be
an fwupd instance id or a GUID
version: the version string of the fw release to install
Raises:
error.TestError if there aren't any available fw releases for
the device in the default fwupd remotes or if there was
any problem getting the FW downgrades info.
error.TestFail if there was an error flashing the device FW or
if the reported device FW version after the update is
different than the specified version
"""
devices = fwupd.get_devices()
dev_pre = fwupd.check_device(device_id, devices)
dev_name = dev_pre.get('Name', 'Unknown Device')
if 'Releases' not in dev_pre:
raise error.TestError("No FW releases found for "
f"{device_id} ({dev_name})")
release = None
for r in dev_pre['Releases']:
if 'Version' not in r:
raise error.TestError(f"No version info in FW release: {r}")
if r['Version'] == version:
release = r
break
if not release:
raise error.TestError(f"Device {device_id} ({dev_name}) has "
f"no firmware release {version} available")
try:
# The format of the 'install' command changed on fwupdmgr
# 1.8.0, the older version needs a file path (or URI)
# instead of a version string and it doesn't support json
# output.
if LooseVersion(self.fwupd_version) >= LooseVersion('1.8.0'):
output = utils.system_output(
"fwupdmgr install --json --assume-yes "
f"{device_id} {version}")
else:
fw = release['Uri']
output = utils.system_output(
"fwupdmgr install --allow-older "
f"--allow-reinstall {fw} {device_id}")
except error.CmdError as e:
raise error.TestFail(e)
if not re.search("Successfully installed firmware", output):
raise error.TestFail(
f"Error installing firmware release {version} "
f"on {device_id} ({dev_name}): {output}")
logging.info("Firmware flashing: done")
# Verify that the device FW version has changed
ver_post = fwupd.get_device_version(device_id)
if ver_post != version:
raise error.TestFail(
f"Error installing firmware release {version} "
f"on {device_id} ({dev_name}): "
f"Current FW version: {ver_post}")
def run_once(self, device_id, version, cert_id):
"""Install a FW version in a device FW and check the result.
Args:
device_id: the instance id of the device or any of its GUIDs (string)
version: version string of the FW release to install, as
specified in the release
cert_id: the serial ID of the certificate for reports signing
Fails if fwupd is not working properly.
"""
if not device_id:
raise error.TestError(
"No device id specified (test argument: device_id)")
if not version:
raise error.TestError(
"No FW version specified (test argument: version)")
self.fwupd_version = fwupd.get_fwupdmgr_version()
if not self.fwupd_version:
raise error.TestError("Error checking fwupd status")
fwupd.ensure_remotes()
fwupd.ensure_certificate(cert_id)
fwupd.get_device_version(device_id)
try:
self.install_firmware(device_id, version)
finally:
fwupd.send_signed_report(cert_id)