# Copyright (c) 2016 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

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest

class firmware_TPMNotCorruptedDevMode(FirmwareTest):
    """
    Checks the firmware and kernel verion stored in TPMC and boots to USB and
    checks the firmware verion and kernel version in crossystem.

    This test requires a USB disk plugged-in, which contains a Chrome OS test
    image (built by "build_image test").
    """
    version = 1

    TPMC_KNOWN_VALUES = set(['1 4c 57 52 47 1 0 1 0 0 0 0 0',
                             '2 4c 57 52 47 1 0 1 0 0 0 0 55'])

    def initialize(self, host, cmdline_args, ec_wp=None):
        dict_args = utils.args_to_dict(cmdline_args)
        super(firmware_TPMNotCorruptedDevMode, self).initialize(
            host, cmdline_args, ec_wp=ec_wp)

        self.assert_test_image_in_usb_disk()
        self.switcher.setup_mode('dev')
        self.setup_usbkey(usbkey=True, host=False)

        self.original_dev_boot_usb = self.faft_client.system.get_dev_boot_usb()
        logging.info(
            'Original dev_boot_usb value: %s',
            str(self.original_dev_boot_usb))

    def cleanup(self):
        self.ensure_internal_device_boot()
        super(firmware_TPMNotCorruptedDevMode, self).cleanup()

    def ensure_internal_device_boot(self):
        """Ensure internal device boot; if not, reboot into it.

        If not, it may be a test failure during step 2 or 3, try to reboot
        and press Ctrl-D to internal device boot.
        """
        if self.faft_client.system.is_removable_device_boot():
            logging.info('Reboot into internal disk...')
            self.faft_client.system.set_dev_boot_usb(self.original_dev_boot_usb)
            self.switcher.mode_aware_reboot()

        self.check_state((self.checkers.dev_boot_usb_checker,
                          False,
                          'Did not boot from internal disk.'))

    def ensure_usb_device_boot(self):
        """Ensure USB device boot and if not reboot into USB."""
        if not self.faft_client.system.is_removable_device_boot():
            logging.info('Reboot into USB...')
            self.faft_client.system.set_dev_boot_usb(1)
            self.switcher.simple_reboot()
            self.switcher.bypass_dev_boot_usb()
            self.switcher.wait_for_client()

        self.check_state((self.checkers.dev_boot_usb_checker,
                          True,
                          'Did not boot from USB.'))

    def check_tpmc(self, tpmc_output):
        """Checks that the kern and fw version from the tpmc read command is one
        of the expected values.
        """
        if len(tpmc_output) != 1:
          return False

        tpmc_fw_kern_version = tpmc_output[0]

        return (tpmc_fw_kern_version in self.TPMC_KNOWN_VALUES)

    def read_tmpc(self):
        """First checks if internal device boot and if not reboots into it.
        Then stops the tcsd then reads the value of `tpmc read 0x1008 0x0d` then
        checks if the output of that command is what is expected.
        """
        self.ensure_internal_device_boot()
        logging.info('Reading tpmc data.')
        self.faft_client.tpm.stop_daemon()
        tpmc_output = self.faft_client.system.run_shell_command_get_output(
            'tpmc read 0x1008 0x0d')
        self.faft_client.tpm.restart_daemon()

        logging.info('===== TPMC OUTPUT: %s =====' % tpmc_output)
        if self.check_tpmc(tpmc_output):
          raise error.TestFail(
              'TPMC version is incorrect. Actual: %s Expected one of: %s' %
                  (tpmc_output, self.TPMC_KNOWN_VALUES))

    def read_kern_fw_ver(self):
        """First ensures that we are botted on a USB device. Then checks the
        firmware and kernel version reported by crossystem.
        """
        self.ensure_usb_device_boot()
        logging.info('Checking kernel and fw version in crossystem.')

        if self.checkers.crossystem_checker({
                    'tpm_fwver': '0xffffffff',
                    'tpm_kernver': '0xffffffff', }):
            raise error.TestFail('tpm versions invalid.')

    def check_tpmc(self, tpmc_output):
      """Checks that the kern and fw version from the tpmc read command is one
      of the expected values.
      """
      if len(tpmc_output) != 1:
        return False

      tpmc_fw_kern_version = set(tpmc_output)

      return (tpmc_fw_kern_version in self.TPMC_KNOWN_VALUES)

    def run_once(self):
        self.read_tmpc()
        self.read_kern_fw_ver()
