blob: 7b7c6bc48f565465136e824015f39613fbe3ce38 [file] [log] [blame]
# Copyright (c) 2014 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.
"""Utility to get release image and firmware version."""
import logging
import os
import re
import subprocess
import factory_common # pylint: disable=W0611
from cros.factory.hwid import hwid_utils
from cros.factory.tools.mount_partition import MountPartition
from cros.factory.utils.file_utils import (
GunzipSingleFile, SetFileExecutable, TempDirectory)
from cros.factory.utils.process_utils import Spawn
def GetReleaseVersion(mount_point):
"""Gets CHROMEOS_RELEASE_VERSION of the rootfs partition.
Args:
mount_point: partition mount point.
Returns:
Release version (in mount_point/etc/lsb-release);
None if not found.
"""
lsb_release = os.path.join(mount_point, 'etc', 'lsb-release')
if not os.path.isfile(lsb_release):
return None
match = re.search('^CHROMEOS_RELEASE_VERSION=(.+)$',
open(lsb_release).read(), re.MULTILINE)
if not match:
return None
return match.group(1)
def GetFirmwareVersions(updater):
"""Gets the firmware versions in firmware updater.
Args:
updater: Path to a firmware updater.
Returns:
(bios_version, ec_version). If no firmware/EC version is found,
sets version to None.
"""
try:
command = [updater, '-V']
stdout = Spawn(command, log=True, check_output=True).stdout_data
except Exception as e:
logging.error('Unable to run "%s", reason: %s', ' '.join(command), e)
return (None, None)
versions = []
for label in ['BIOS', 'EC']:
match = re.search('^' + label + ' version:\s+(.+)$', stdout, re.MULTILINE)
versions.append(match.group(1) if match else None)
return tuple(versions)
def GetFirmwareVersionsFromOmahaChannelFile(path):
"""Gets firmware versions from Omaha channel file.
Omaha channel file (gzipped) is often in
<bundle_dir>/factory_setup/static/firmware.gz
Args:
path: Channel file path.
Returns:
(bios_version, ec_version). If no firmware/EC version is found,
sets version to None.
"""
with GunzipSingleFile(path) as unzip_path:
SetFileExecutable(unzip_path)
return GetFirmwareVersions(unzip_path)
def GetFirmwareBinaryVersion(path):
"""Gets the version stored in RO_FRID section of the firmware binary.
Note that this function relies on dump_fmap, which is only available on a CrOS
device or inside CrOS SDK chroot.
Args:
path: Path to the firmware binary.
Returns:
The extracted firmware version as a string; or None if the function fails to
extract version.
"""
binary_path = os.path.abspath(path)
result = None
try:
with TempDirectory(prefix='dump_fmap') as temp_dir:
Spawn(['dump_fmap', '-x', binary_path], ignore_stdout=True, log=True,
cwd=temp_dir, check_call=True)
with open(os.path.join(temp_dir, 'RO_FRID')) as f:
result = f.read().strip('\x00') # Strip paddings.
except (subprocess.CalledProcessError, IOError):
logging.exception(
'Failed to extract firmware version from %s.', binary_path)
return result
def GetReleaseVersionFromOmahaChannelFile(path):
"""Gets release image version from Omaha channel file.
Omaha channel file (gzipped) is often in
<bundle_dir>/factory_setup/static/rootfs-test.gz
<bundle_dir>/factory_setup/static/rootfs-release.gz
Args:
path: Channel file path.
Returns:
Release version (in mount_point/etc/lsb-release);
None if not found.
"""
with GunzipSingleFile(path) as unzip_path:
with MountPartition(unzip_path, is_omaha_channel=True) as mount_point:
return GetReleaseVersion(mount_point)
def GetHWIDVersion(path):
"""Gets HWID version from HWID v3 bundle file.
It also verifies checksum.
Args:
path: HWID v3 bundle file path ('.gz' supported).
Returns:
HWID checksum as version. None if file is not found or checksum failed.
"""
def _GetHWIDVersion(hwid_path):
with open(hwid_path) as f:
hwid = f.read()
match = re.search(r'^checksum: (.*)$\n?', hwid, flags=re.MULTILINE)
if match:
expected_checksum = match.group(1)
actual_checksum = hwid_utils.ComputeDatabaseChecksum(hwid_path)
if expected_checksum == actual_checksum:
return expected_checksum
else:
logging.warning('HWID verification failed: expected: %s actual: %s',
expected_checksum, actual_checksum)
else:
logging.warning('Cannot extract checksum from HWID: %s', path)
return None
if path.endswith('.gz'):
with GunzipSingleFile(path) as unzip_path:
return _GetHWIDVersion(unzip_path)
else:
return _GetHWIDVersion(path)