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    version = 1
21
22    def resign_kernel_subkey_version(self, host):
23        host.send_file(os.path.join(self.bindir,
24                                    'files/common.sh'),
25                       os.path.join(self.faft_client.updater.get_temp_path(),
26                                     'common.sh'))
27        host.send_file(os.path.join(self.bindir,
28                                    'files/make_keys.sh'),
29                       os.path.join(self.faft_client.updater.get_temp_path(),
30                                    'make_keys.sh'))
31
32        self.faft_client.system.run_shell_command('/bin/bash %s %s' % (
33            os.path.join(self.faft_client.updater.get_temp_path(),
34                         'make_keys.sh'),
35            self._update_version))
36
37    def check_kernel_subkey_version(self, expected_ver):
38        actual_ver = self.faft_client.bios.get_kernel_subkey_version(
39                'b' if self.fw_vboot2 else 'a')
40        if actual_ver != expected_ver:
41            raise error.TestFail(
42                    'Kernel subkey version should be %s, but got %s.' %
43                    (expected_ver, actual_ver))
44        else:
45            logging.info(
46                'Update success, now subkey version is %s',
47                actual_ver)
48
49
50    def initialize(self, host, cmdline_args, dev_mode=True):
51        dict_args = utils.args_to_dict(cmdline_args)
52        shellball_path = dict_args.get('shellball', None)
53        super(firmware_UpdateKernelSubkeyVersion, self).initialize(
54            host, cmdline_args)
55        self.backup_firmware()
56        self.switcher.setup_mode('dev' if dev_mode else 'normal')
57        self.setup_firmwareupdate_shellball(shellball_path)
58
59        # Update firmware if needed
60        if shellball_path:
61            self.set_hardware_write_protect(enable=False)
62            self.faft_client.updater.run_factory_install()
63            self.switcher.mode_aware_reboot()
64
65        self._fwid = self.faft_client.updater.get_fwid()
66
67        ver = self.faft_client.bios.get_kernel_subkey_version('a')
68        logging.info('Origin version is %s', ver)
69        self._update_version = ver + 1
70        logging.info('Kernel subkey version will update to version %s',
71                     self._update_version)
72
73        self.resign_kernel_subkey_version(host)
74        self.faft_client.updater.resign_firmware(1)
75        self.faft_client.updater.repack_shellball('test')
76
77    def cleanup(self):
78        try:
79            self.restore_firmware()
80            self.invalidate_firmware_setup()
81        except Exception as e:
82            logging.error("Caught exception: %s", str(e))
83        super(firmware_UpdateKernelSubkeyVersion, self).cleanup()
84
85    def run_once(self):
86        logging.info("Update firmware with new kernel subkey version.")
87        self.check_state((self.checkers.crossystem_checker, {
88                          'fwid': self._fwid
89                          }))
90        self.check_state((self.checkers.fw_tries_checker, 'A'))
91        self.faft_client.updater.run_autoupdate('test')
92        self.switcher.mode_aware_reboot()
93
94        logging.info("Check firmware data key version and Rollback.")
95        self.faft_client.updater.run_bootok('test')
96        self.check_state((self.checkers.fw_tries_checker, 'B'))
97        self.check_kernel_subkey_version(self._update_version)
98        self.faft_client.updater.run_recovery()
99        self.switcher.mode_aware_reboot()
100
101        logging.info("Check Rollback version.")
102        self.check_state((self.checkers.crossystem_checker, {
103                          'fwid': self._fwid
104                          }))
105        self.check_state((self.checkers.fw_tries_checker,
106                          'B' if self.fw_vboot2 else 'A'))
107        self.check_kernel_subkey_version(self._update_version - 1)
108