# 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.mode_aware_reboot(wait_for_dut_up=False)
            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.')
        tpmc_output = self.faft_client.system.run_shell_command_get_output(
            'tpmc read 0x1008 0x0d')

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