1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import os
7
8from autotest_lib.server import utils
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10from autotest_lib.client.common_lib import error
11
12
13class firmware_UpdateKernelSubkeyVersion(FirmwareTest):
14    """
15    This test requires firmware id matches fwid of shellball
16    chromeos-firmwareupdate. On runtime, this test modifies shellball and runs
17    autoupdate. Check kernel subkey version after boot with firmware B, and
18    then recover firmware A and B to original shellball.
19
20    """
21    version = 1
22
23    def resign_kernel_subkey_version(self, host):
24        """Resigns the kernel subkey version."""
25        host.send_file(os.path.join(self.bindir,
26                                    'files/common.sh'),
27                       os.path.join(self.faft_client.updater.get_temp_path(),
28                                     'common.sh'))
29        host.send_file(os.path.join(self.bindir,
30                                    'files/make_keys.sh'),
31                       os.path.join(self.faft_client.updater.get_temp_path(),
32                                    'make_keys.sh'))
33
34        self.faft_client.system.run_shell_command('/bin/bash %s %s' % (
35            os.path.join(self.faft_client.updater.get_temp_path(),
36                         'make_keys.sh'),
37            self._update_version))
38
39    def check_kernel_subkey_version(self, expected_ver):
40        """Checks the kernel subkey version."""
41        actual_ver = self.faft_client.bios.get_kernel_subkey_version(
42                'b' if self.fw_vboot2 else 'a')
43        if actual_ver != expected_ver:
44            raise error.TestFail(
45                    'Kernel subkey version should be %s, but got %s.' %
46                    (expected_ver, actual_ver))
47        else:
48            logging.info(
49                'Update success, now subkey version is %s',
50                actual_ver)
51
52
53    def initialize(self, host, cmdline_args, dev_mode=True):
54        """Initialize the test"""
55        dict_args = utils.args_to_dict(cmdline_args)
56        shellball_path = dict_args.get('shellball', None)
57        super(firmware_UpdateKernelSubkeyVersion, self).initialize(
58            host, cmdline_args)
59        self.backup_firmware()
60        self.switcher.setup_mode('dev' if dev_mode else 'normal',
61                                 allow_gbb_force=True)
62        self.setup_firmwareupdate_shellball(shellball_path)
63
64        # Update firmware if needed
65        if shellball_path:
66            self.set_ap_write_protect_and_reboot(enable=False)
67            self.faft_client.updater.run_factory_install()
68            self.switcher.mode_aware_reboot()
69
70        self._fwid = self.faft_client.updater.get_section_fwid()
71
72        ver = self.faft_client.bios.get_kernel_subkey_version('a')
73        logging.info('Origin version is %s', ver)
74        self._update_version = ver + 1
75        logging.info('Kernel subkey version will update to version %s',
76                     self._update_version)
77
78        self.resign_kernel_subkey_version(host)
79        self.faft_client.updater.resign_firmware(1)
80        self.faft_client.updater.repack_shellball('test')
81
82    def cleanup(self):
83        """Cleanup after the test"""
84        try:
85            self.restore_firmware()
86            self.invalidate_firmware_setup()
87        except Exception as e:
88            logging.error("Caught exception: %s", str(e))
89        super(firmware_UpdateKernelSubkeyVersion, self).cleanup()
90
91    def run_once(self):
92        """Runs a single iteration of the test."""
93        logging.info("Update firmware with new kernel subkey version.")
94        self.check_state((self.checkers.crossystem_checker, {
95                          'fwid': self._fwid
96                          }))
97        self.check_state((self.checkers.fw_tries_checker, 'A'))
98        self.faft_client.updater.run_autoupdate('test')
99        self.switcher.mode_aware_reboot()
100
101        logging.info("Check firmware data key version and Rollback.")
102        self.faft_client.updater.run_bootok('test')
103        self.check_state((self.checkers.fw_tries_checker, 'B'))
104        self.check_kernel_subkey_version(self._update_version)
105        self.faft_client.updater.run_recovery()
106        self.switcher.mode_aware_reboot()
107
108        logging.info("Check Rollback version.")
109        self.check_state((self.checkers.crossystem_checker, {
110                          'fwid': self._fwid
111                          }))
112        self.check_state((self.checkers.fw_tries_checker,
113                          'B' if self.fw_vboot2 else 'A'))
114        self.check_kernel_subkey_version(self._update_version - 1)
115