# Copyright 2017 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. """ The autotest performing Cr50 update.""" import logging import os from autotest_lib.client.common_lib import error 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 provision_Cr50Update(Cr50Test): """A test that can provision a machine to the correct cr50 version and board id. The value is the image rw version/image board id. The chip board id will be set to the image board id unless the image board id is empty (''). If it's empty, the chip board id will be set to the device brand:0x7f80. value=0.0.23/ZZAF:ffffffff:7f00 value=0.3.25/ """ version = 1 def initialize(self, host, cmdline_args, full_args, value='', release_path='', force=False): """Initialize get the cr50 update version information""" super(provision_Cr50Update, self).initialize(host, cmdline_args, full_args, provision_update=True) # TODO(mruthven): remove once the test is successfully scheduled. logging.info('SUCCESSFULLY SCHEDULED PROVISION CR50 UPDATE with %r', value) if not force: return self.host = host image_info = None if os.path.isfile(release_path): image_info = self.init_local_image(release_path) else: # The value is rw_ver/image_bid. The image_bid will also be used for # the chip board id. rw_ver, bid = value.split('/') image_info = self.download_cr50_release_image(rw_ver, bid) if not image_info: raise error.TestError('Could not find new cr50 image') self.local_path, self.image_ver = image_info self.image_rw = self.image_ver[1] self.image_bid = self.image_ver[2] self.chip_bid = cr50_utils.GetChipBIDFromImageBID( self.image_bid, self.get_device_brand()) def init_local_image(self, release_path): """Get the version of the local image. Args: release_path: The local path to the cr50 image Returns: the local path, image version tuple """ ver = cr50_utils.InstallImage(self.host, release_path, '/tmp/release.bin')[1] return release_path, ver def run_once(self, force=False): """The method called by the control file to start the update.""" # TODO(mruthven): remove once the test is successfully scheduled. if not force: logging.info('skipping update') return update_state = {} update_state['chip_bid'] = self.chip_bid update_state['prepvt_version'] = self.image_ver update_state['prod_version'] = self.image_ver update_state['running_image_bid'] = self.image_ver[2] # The test can't rollback RO. The newest RO should be running at the end # of the test. max_ro will be none if the versions are the same. Use the # running_ro in that case. running_ro = self.get_saved_cr50_original_version()[0] max_ro = cr50_utils.GetNewestVersion(running_ro, self.image_ver[0]) update_state['running_image_ver'] = (max_ro or running_ro, self.image_ver[1], None) mismatch = self._check_running_image_and_board_id(update_state) if not mismatch: logging.info('No update needed.') return filesystem_util.make_rootfs_writable(self.host) if self._cleanup_required(mismatch, self.DBG_IMAGE): logging.info('Updating to image %s with chip board id %s', self.image_ver, '%08x:%08x:%08x' % self.chip_bid) self.update_cr50_image_and_board_id(self.local_path, self.chip_bid) # Copy the image onto the DUT. cr50-update uses both cr50.bin.prod and # cr50.bin.prepvt in /opt/google/cr50/firmware/, so copy it to both # places. Rootfs verification has to be disabled to do the copy. cr50_utils.InstallImage(self.host, self.local_path, cr50_utils.CR50_PREPVT) cr50_utils.InstallImage(self.host, self.local_path, cr50_utils.CR50_PROD) # Verify everything updated correctly mismatch = self._check_running_image_and_board_id(update_state) if mismatch: raise error.TestFail('Failed to update cr50: %s', mismatch)