# Copyright 2018 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.

from __future__ import print_function

import logging
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import tpm_utils
from autotest_lib.server import autotest
from autotest_lib.server.cros.faft.cr50_test import Cr50Test


class firmware_Cr50FactoryResetVC(Cr50Test):
    """A test verifying factory mode vendor command."""
    version = 1

    FWMP_DEV_DISABLE_CCD_UNLOCK = (1 << 6)
    # Short wait to make sure cr50 has had enough time to update the ccd state
    SLEEP = 2
    BOOL_VALUES = (True, False)

    def initialize(self, host, cmdline_args, full_args):
        """Initialize servo check if cr50 exists."""
        super(firmware_Cr50FactoryResetVC, self).initialize(host, cmdline_args,
                full_args)
        if not self.cr50.has_command('bpforce'):
            raise error.TestNAError('Cannot run test without bpforce')
        self.fast_ccd_open(enable_testlab=True)
        # Reset ccd completely.
        self.cr50.send_command('ccd reset')

        # If we can fake battery connect/disconnect, then we can test the vendor
        # command.
        try:
            self.bp_override(True)
            self.bp_override(False)
        except Exception as e:
            logging.info(e)
            raise error.TestNAError('Cannot fully test factory mode vendor '
                    'command without the ability to fake battery presence')

    def cleanup(self):
        """Clear the FWMP and ccd state"""
        try:
            self.clear_state()
        finally:
            super(firmware_Cr50FactoryResetVC, self).cleanup()


    def bp_override(self, connect):
        """Deassert BATT_PRES signal, so cr50 will think wp is off."""
        self.cr50.send_command('ccd testlab open')
        self.cr50.set_batt_pres_state('connect' if connect else 'disconnect',
                                      False)
        if self.cr50.get_batt_pres_state()[1] != connect:
            raise error.TestError('Could not fake battery %sconnect' %
                    ('' if connect else 'dis'))
        self.cr50.set_ccd_level('lock')


    def fwmp_ccd_lockout(self):
        """Returns True if FWMP is locking out CCD."""
        return 'fwmp_lock' in self.cr50.get_ccd_info('TPM')


    def set_fwmp_lockout(self, enable):
        """Change the FWMP to enable or disable ccd.

        Args:
            enable: True if FWMP flags should lock out ccd.
        """
        logging.info('%sing FWMP ccd lockout', 'enabl' if enable else 'clear')
        if enable:
            flags = hex(self.FWMP_DEV_DISABLE_CCD_UNLOCK)
            logging.info('Setting FWMP flags to %s', flags)
            autotest.Autotest(self.host).run_test('firmware_SetFWMP',
                    flags=flags, fwmp_cleared=True, check_client_result=True)

        if (not self.fwmp_ccd_lockout()) != (not enable):
            raise error.TestError('Could not %s fwmp lockout' %
                    ('set' if enable else 'clear'))


    def setup_ccd_password(self, set_password):
        """Set the Cr50 CCD password.

        Args:
            set_password: if True set the password. The password is already
                    cleared, so if False just check the password is cleared
        """
        if set_password:
            self.cr50.send_command('ccd testlab open')
            # Set the ccd password
            self.set_ccd_password('ccd_dummy_pw')
        if self.cr50.password_is_reset() == set_password:
            raise error.TestError('Could not %s password' %
                    ('set' if set_password else 'clear'))


    def factory_mode_enabled(self):
        """Returns True if factory mode is enabled."""
        caps = self.cr50.get_cap_dict()
        caps.pop('GscFullConsole')
        return self.cr50.get_cap_overview(caps)[0]


    def get_relevant_state(self):
        """Returns cr50 state that can lock out factory mode.

        FWMP, battery presence, or a password can all lock out enabling factory
        mode using the vendor command. If any item in state is True, factory
        mode should be locked out.
        """
        state = []
        state.append(self.fwmp_ccd_lockout())
        state.append(self.cr50.get_batt_pres_state()[1])
        state.append(not self.cr50.password_is_reset())
        return state


    def get_state_message(self):
        """Convert relevant state into a useful log message."""
        fwmp, bp, password = self.get_relevant_state()
        return ('fwmp %s bp %sconnected password %s' %
                ('set' if fwmp else 'cleared',
                 '' if bp else 'dis',
                 'set' if password else 'cleared'))


    def factory_locked_out(self):
        """Returns True if any state preventing factory mode is True."""
        return True in self.get_relevant_state()


    def set_factory_mode(self, enable):
        """Use the vendor command to control factory mode.

        Args:
            enable: Enable factory mode if True. Disable it if False.
        """
        enable_fail = self.factory_locked_out() and enable
        time.sleep(self.SLEEP)
        logging.info('%sABLING FACTORY MODE', 'EN' if enable else 'DIS')
        if enable:
            logging.info('EXPECT: %s', 'failure' if enable_fail else 'success')
        cmd = 'enable' if enable else 'disable'

        result = self.host.run('gsctool -a -F %s' % cmd,
                ignore_status=(enable_fail or not enable))
        logging.debug(result)
        expect_enabled = enable and not enable_fail

        if expect_enabled:
            # Cr50 will reboot after it enables factory mode.
            self.cr50.wait_for_reboot(timeout=10)
        else:
            # Wait long enoug for cr50 to udpate the ccd state.
            time.sleep(self.SLEEP)
        if self.factory_mode_enabled() != expect_enabled:
            raise error.TestFail('Unexpected factory mode %s result' % cmd)


    def clear_state(self):
        """Clear the FWMP and reset CCD"""
        # Clear the FWMP
        self.clear_fwmp()
        # make sure all of the ccd stuff is reset
        self.cr50.send_command('ccd testlab open')
        # Run ccd reset to make sure all ccd state is cleared
        self.cr50.send_command('ccd reset')
        # Clear the TPM owner, so we can set the ccd password and
        # create the FWMP
        tpm_utils.ClearTPMOwnerRequest(self.host, wait_for_ready=True)


    def run_once(self):
        """Verify FWMP disable with different flag values."""
        errors = []
        # Try enabling factory mode in each valid state. Cr50 checks write
        # protect, password, and fwmp before allowing fwmp to be enabled.
        for lockout_ccd_with_fwmp in self.BOOL_VALUES:
            for set_password in self.BOOL_VALUES:
                for connect in self.BOOL_VALUES:
                    # Clear relevant state, so we can set the fwmp and password
                    self.clear_state()

                    # Setup the cr50 state
                    self.setup_ccd_password(set_password)
                    self.bp_override(connect)
                    self.set_fwmp_lockout(lockout_ccd_with_fwmp)
                    self.cr50.set_ccd_level('lock')

                    logging.info('RUN: %s', self.get_state_message())

                    try:
                        self.set_factory_mode(True)
                        self.set_factory_mode(False)
                    except Exception as e:
                        message = 'FAILURE %r %r' % (self.get_state_message(),
                                e)
                        logging.info(message)
                        errors.append(message)
        if errors:
            raise error.TestFail(errors)
