1# Lint as: python2, python3
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os, os.path, re
7from autotest_lib.client.common_lib import error
8from autotest_lib.server import autotest, test
9
10class hardware_DiskFirmwareUpgrade(test.test):
11    """
12    Integrity stress test for storage device
13    """
14    version = 1
15
16    TEST_NAME='hardware_DiskFirmwareUpgrade'
17    TEST_SCRIPT='/usr/sbin/chromeos-disk-firmware-update.sh'
18    DEFAULT_LOCATION='/opt/google/disk/firmware'
19
20    _client_install_path = None
21
22
23    def _exists_on_client(self, f):
24        return self._client.run('ls "%s"' % f,
25                               ignore_status=True).exit_status == 0
26
27    def _get_model_name(self):
28        """ Return the name of an ATA/SCSI device. """
29        return self._client.run(
30            'cat /sys/block/$(basename $(rootdev -s -d))/device/model').stdout
31
32    def _get_device_name(self):
33        """ Return the name of an eMMC device, using cid data."""
34        return self._client.run(
35            'cat /sys/block/$(basename $(rootdev -s -d))/device/cid | cut -c 7-18').stdout
36
37    def run_once(self, host, disk_fw_packages):
38        """
39        For every firmware package in disk_fw_packages, we launch the sibbling
40        client test if:
41        - the script to install the package is present
42        - the model of the device present matches the defined model regex.
43        We launch the slibbing client test a second time to put the machine
44        in a well-known state.
45
46        @param host:     machine to use.
47        @param disk_fw_packages: directory of firmware to use and
48                         expected return code. See control for details.
49        """
50
51        self._client = host
52        self._client_at = autotest.Autotest(self._client)
53        # First, check if the machine image contains the
54        # upgrade script.
55        if not self._exists_on_client(self.TEST_SCRIPT):
56            raise error.TestNAError('Firmware upgrade not supported')
57
58        # Retrieve model name.
59        try:
60            model = self._get_model_name()
61        except error.AutoservRunError:
62            model = self._get_device_name()
63
64        i = 0
65        for model_re, package_desc in list(disk_fw_packages.items()):
66            if not re.match(model_re, model):
67                continue
68            for p, results in list(package_desc.items()):
69                result_dir = '-'.join([self.TEST_NAME, str(i), p])
70                if p.startswith('test_'):
71                    self._client_at.run_test(
72                            self.TEST_NAME,
73                            results_dir=result_dir,
74                            disk_firmware_package=self.DEFAULT_LOCATION + '-test',
75                            expected_result=results[0],
76                            upgrade_required=results[1])
77                else:
78                    # We are not expecting downloads.
79                    self._tmpdir = self._client.get_tmp_dir()
80                    self._client.send_file(os.path.join(self.bindir, p),
81                                           self._tmpdir)
82                    self._client_at.run_test(
83                            self.TEST_NAME,
84                            results_dir=result_dir,
85                            disk_firmware_package=os.path.join(self._tmpdir, p),
86                            expected_result=results[0],
87                            upgrade_required=results[1])
88                result_dir = '-'.join([self.TEST_NAME, str(i), '~base'])
89                # After the test run, reinstall regular firmware.
90                self._client_at.run_test(
91                        self.TEST_NAME,
92                        results_dir=result_dir,
93                        disk_firmware_package=self.DEFAULT_LOCATION,
94                        upgrade_required=results[1])
95                i += 1
96