# 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)
